Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| vendors:cisco:uc:ucce:baselinereskiller [2023/06/12 17:21] – [Database] gerardorourke | vendors:cisco:uc:ucce:baselinereskiller [2023/07/31 10:05] (current) – [Python Scripts] gerardorourke | ||
|---|---|---|---|
| Line 177: | Line 177: | ||
| ===== Database ===== | ===== Database ===== | ||
| + | ==== Database Views ==== | ||
| *Add UCCE AW SQL Server as a linked server | *Add UCCE AW SQL Server as a linked server | ||
| *When adding - on the security tab, set "Be made using this security context" | *When adding - on the security tab, set "Be made using this security context" | ||
| Line 256: | Line 257: | ||
| </ | </ | ||
| + | ==== Database Tables ==== | ||
| + | <code sql> | ||
| + | USE [reskiller_db] | ||
| + | GO | ||
| + | |||
| + | /****** Object: | ||
| + | SET ANSI_NULLS ON | ||
| + | GO | ||
| + | |||
| + | SET QUOTED_IDENTIFIER ON | ||
| + | GO | ||
| + | |||
| + | CREATE TABLE [dbo].[Department]( | ||
| + | [DepartmentID] [int] NOT NULL, | ||
| + | [DepartmentName] [varchar](50) NOT NULL, | ||
| + | [Supervisor] [varchar](50) NOT NULL, | ||
| + | [Password] [varchar](50) NOT NULL, | ||
| + | [ScheduleID] [int] NULL, | ||
| + | [Active] [char](1) NOT NULL | ||
| + | ) ON [PRIMARY] | ||
| + | GO | ||
| + | |||
| + | ALTER TABLE [dbo].[Department] ADD CONSTRAINT [DF_Department_Active] | ||
| + | GO | ||
| + | </ | ||
| + | |||
| + | <code sql> | ||
| + | USE [reskiller_db] | ||
| + | GO | ||
| + | |||
| + | /****** Object: | ||
| + | SET ANSI_NULLS ON | ||
| + | GO | ||
| + | |||
| + | SET QUOTED_IDENTIFIER ON | ||
| + | GO | ||
| + | |||
| + | CREATE TABLE [dbo].[Agent_Team_Department]( | ||
| + | [AgentTeamID] [int] NOT NULL, | ||
| + | [DepartmentID] [int] NOT NULL, | ||
| + | [Active] [char](1) NOT NULL, | ||
| + | | ||
| + | ( | ||
| + | [AgentTeamID] ASC | ||
| + | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] | ||
| + | ) ON [PRIMARY] | ||
| + | GO | ||
| + | |||
| + | ALTER TABLE [dbo].[Agent_Team_Department] ADD CONSTRAINT [DF_Agent_Team_Department_Active] | ||
| + | GO | ||
| + | </ | ||
| + | |||
| + | <code sql> | ||
| + | USE [reskiller_db] | ||
| + | GO | ||
| + | |||
| + | /****** Object: | ||
| + | SET ANSI_NULLS ON | ||
| + | GO | ||
| + | |||
| + | SET QUOTED_IDENTIFIER ON | ||
| + | GO | ||
| + | |||
| + | CREATE TABLE [dbo].[Agent_Team_Skill_Group]( | ||
| + | [AgentTeamID] [int] NOT NULL, | ||
| + | [SkillTargetID] [int] NOT NULL | ||
| + | ) ON [PRIMARY] | ||
| + | GO | ||
| + | </ | ||
| + | |||
| + | <code sql> | ||
| + | USE [reskiller_db] | ||
| + | GO | ||
| + | |||
| + | /****** Object: | ||
| + | SET ANSI_NULLS ON | ||
| + | GO | ||
| + | |||
| + | SET QUOTED_IDENTIFIER ON | ||
| + | GO | ||
| + | |||
| + | CREATE TABLE [dbo].[Log]( | ||
| + | [ID] [int] IDENTITY(1, | ||
| + | [DateTime] [datetime] NOT NULL, | ||
| + | [SevLevel] [int] NOT NULL, | ||
| + | [Data] [nvarchar](max) NOT NULL, | ||
| + | | ||
| + | ( | ||
| + | [ID] ASC | ||
| + | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] | ||
| + | ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] | ||
| + | GO | ||
| + | |||
| + | ALTER TABLE [dbo].[Log] ADD CONSTRAINT [DF_Log_DateTime] | ||
| + | GO | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== Python Scripts ==== | ||
| <code python> | <code python> | ||
| # Author: Gerry O' | # Author: Gerry O' | ||
| - | # June 2021 | + | # June 2023 |
| - | # Version 1.1 | + | |
| - | import array | + | |
| from datetime import datetime | from datetime import datetime | ||
| + | import sys | ||
| import pyodbc | import pyodbc | ||
| - | # | + | import requests |
| - | #import | + | from requests.auth |
| - | + | import xml.etree.ElementTree as ET | |
| - | database_write=0 #disable database writes | + | import urllib3 |
| + | urllib3.disable_warnings() | ||
| - | #Get the Current Time - rounded down to minute. | + | version |
| - | now = datetime.now() | + | cce_api_hostname |
| - | current_datetime | + | debug_level |
| - | print("Current DateTime | + | |
| - | conn = pyodbc.connect(' | + | # Reference: https:// |
| - | ' | + | |
| - | ' | + | |
| - | ' | + | |
| - | + | ||
| - | cursor = conn.cursor() | + | |
| - | # Note this function is not used - and can be deleted | + | # exit codes |
| - | def getApiUserDetails(departmentid): | + | # 0 : Success |
| - | rows = cursor.execute(' | + | # 1 : Argument |
| - | + | # 10 : Error retrieving Team Details | |
| - | for row in list(rows): | + | # 11 : update to retrieve agent details failed |
| - | try: | + | # 12 : Update to Agent Failed |
| - | | + | # 13 : Error retrieving Team Skills |
| - | apiUserName = row[0] | + | # 14 : Error retrieving Team Agents |
| - | global apiPassword | + | |
| - | apiPassword= row[1] | + | |
| - | + | ||
| - | except Exception as e: | + | |
| - | print(" | + | |
| + | # SEV Level (taken from Syslog) only 3-7 should be used | ||
| + | # VALUE SEVERITY | ||
| + | # 0 Emergency | ||
| + | # 1 Alert | ||
| + | # 2 Critical | ||
| + | # 3 Error | ||
| + | # 4 Warning | ||
| + | # 5 Notice | ||
| + | # 6 Informational info | ||
| + | # 7 Debug | ||
| def getTeamDetails(departmentid): | def getTeamDetails(departmentid): | ||
| + | logToDatabase(6, | ||
| + | |||
| rows = cursor.execute( | rows = cursor.execute( | ||
| - | ' | + | ' |
| + | 'Agent_Team_Department] ATD LEFT JOIN Department D ON ATD.DepartmentID = D.DepartmentID WHERE ATD.Active = ' | ||
| + | '\' | ||
| (departmentid)) | (departmentid)) | ||
| Line 308: | Line 419: | ||
| global apiUserName | global apiUserName | ||
| apiUserName = row[1] | apiUserName = row[1] | ||
| + | global apiPassword | ||
| apiPassword = row[2] | apiPassword = row[2] | ||
| + | print(" | ||
| print(" | print(" | ||
| - | print(" | + | print(" |
| + | logToDatabase(6, | ||
| getTeamSkills(teamId) | getTeamSkills(teamId) | ||
| getTeamAgents(teamId) | getTeamAgents(teamId) | ||
| except Exception as e: | except Exception as e: | ||
| - | print(" | + | |
| + | | ||
| + | logToDatabase(3, errorstr) | ||
| + | exit(10) | ||
| def getTeamSkills(teamid): | def getTeamSkills(teamid): | ||
| rows = cursor.execute( | rows = cursor.execute( | ||
| - | ' | + | ' |
| global skills | global skills | ||
| - | n=0 | + | n = 0 |
| for row in list(rows): | for row in list(rows): | ||
| try: | try: | ||
| skillid = row[0] | skillid = row[0] | ||
| - | if (n==0): | + | if (n == 0): |
| n = n + 1 | n = n + 1 | ||
| skills = [skillid] | skills = [skillid] | ||
| Line 336: | Line 453: | ||
| except Exception as e: | except Exception as e: | ||
| - | print(" | + | |
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(13) | ||
| + | |||
| + | | ||
| - | print (" | ||
| def getTeamAgents(teamid): | def getTeamAgents(teamid): | ||
| rows = cursor.execute( | rows = cursor.execute( | ||
| - | ' | + | ' |
| + | 'LEFT JOIN Agent_Team AT ON ATM.AgentTeamID = AT.AgentTeamID WHERE A.Deleted = \' | ||
| + | 'ORDER BY SkillTargetID', | ||
| + | | ||
| global agents | global agents | ||
| - | n=0 | + | n = 0 |
| for row in list(rows): | for row in list(rows): | ||
| try: | try: | ||
| agentid = row[0] | agentid = row[0] | ||
| - | if (n==0): | + | |
| + | # print (' | ||
| + | agentUpdateStatus = updateAgentSkills(apiUserName, | ||
| + | if agentUpdateStatus != 200: | ||
| + | exit(12) | ||
| + | | ||
| n = n + 1 | n = n + 1 | ||
| agents = [agentid] | agents = [agentid] | ||
| Line 358: | Line 487: | ||
| except Exception as e: | except Exception as e: | ||
| - | print(" | + | |
| + | | ||
| + | logToDatabase(3, errorstr) | ||
| + | exit(14) | ||
| - | print (" | + | print(" |
| + | # Check if Web Service API is in service | ||
| - | # | ||
| - | departmentId = 1 | ||
| - | getTeamDetails(departmentId) | ||
| - | #print(" | + | def getApiStatus(): |
| + | api_url = f' | ||
| + | response = requests.get(api_url, verify=False) | ||
| + | status_code = response.status_code | ||
| + | return (status_code) | ||
| - | #input("Press Enter to continue...") | + | |
| + | def getAgentChangeStamp(username, | ||
| + | basic = HTTPBasicAuth(username, | ||
| + | api_url = f' | ||
| + | response = requests.get(api_url, | ||
| + | status_code = response.status_code | ||
| + | if status_code == 200: | ||
| + | response_xml_as_string = response.text | ||
| + | responseXml = ET.fromstring(response_xml_as_string) | ||
| + | | ||
| + | for child in responseXml: | ||
| + | # print(child.tag, | ||
| + | if child.tag == ' | ||
| + | errorstr = f' | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(11) | ||
| + | else: | ||
| + | errorstr = f' | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(11) | ||
| + | |||
| + | |||
| + | def updateAgentSkills(username, | ||
| + | basic = HTTPBasicAuth(username, | ||
| + | api_url = f' | ||
| + | headers = {' | ||
| + | skillRefURL = "" | ||
| + | for skill in (skills): | ||
| + | skillRefURL += f'< | ||
| + | # print(skillRefURL) | ||
| + | agentSkillsXml = f'< | ||
| + | response = requests.put(api_url, | ||
| + | status_code = response.status_code | ||
| + | |||
| + | if debug_level > 1: | ||
| + | debugstr = f' | ||
| + | print(debugstr) | ||
| + | logToDatabase(7, | ||
| + | |||
| + | if status_code != 200: | ||
| + | errorstr = f' | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | print(f' | ||
| + | return (status_code) | ||
| + | |||
| + | |||
| + | def logToDatabase(sev, | ||
| + | sql = ' | ||
| + | val = (int(sev), str(data)) | ||
| + | cursor.execute(sql, | ||
| + | conn.commit() | ||
| + | |||
| + | |||
| + | ################################################################################################# | ||
| + | # This is where we start # | ||
| + | ################################################################################################# | ||
| + | |||
| + | # Check for argument ' | ||
| + | |||
| + | if len(sys.argv) == 3: | ||
| + | if sys.argv[1] == " | ||
| + | print(" | ||
| + | scheduleId = (sys.argv[2]) | ||
| + | elif (sys.argv[1] == " | ||
| + | print(" | ||
| + | departmentId = (sys.argv[2]) | ||
| + | else: | ||
| + | print( | ||
| + | " | ||
| + | " | ||
| + | print(" | ||
| + | exit(1) | ||
| + | else: | ||
| + | print( | ||
| + | " | ||
| + | " | ||
| + | print(" | ||
| + | exit(1) | ||
| + | |||
| + | # Get the Current Time - rounded down to minute. | ||
| + | now = datetime.now() | ||
| + | current_datetime = now.strftime(' | ||
| + | print(" | ||
| + | |||
| + | conn = pyodbc.connect(' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | cursor = conn.cursor() | ||
| + | |||
| + | logToDatabase(6, | ||
| + | |||
| + | # Checking CCE API is in service before starting... | ||
| + | apiStatus = getApiStatus() | ||
| + | if apiStatus != 200: | ||
| + | errorstr = f' | ||
| + | logToDatabase(3, | ||
| + | exit(10) | ||
| + | |||
| + | if (sys.argv[1] == " | ||
| + | getTeamDetails(departmentId) | ||
| + | |||
| + | if (sys.argv[1] == " | ||
| + | logToDatabase(6, | ||
| + | if sys.argv[2].isdigit(): | ||
| + | rows = cursor.execute(" | ||
| + | else: | ||
| + | rows = cursor.execute(" | ||
| + | for row in list(rows): | ||
| + | try: | ||
| + | departmentId = row[0] | ||
| + | getTeamDetails(departmentId) | ||
| + | except Exception as e: | ||
| + | errorstr = e | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(13) | ||
| + | |||
| + | logToDatabase(6, | ||
| + | |||
| + | print(" | ||
| + | now = datetime.now() | ||
| + | current_datetime = now.strftime(' | ||
| + | print(" | ||
| </ | </ | ||
| + | |||
| + | ===== Troubleshooting ===== | ||
| + | |||
| + | If the script works OK as but not when running as a sheduled script - run the script under the same account and see if the issue occur. | ||
| + | |||
| + | {{: | ||
| + | |||