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:05] – [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 255: | Line 256: | ||
| FROM FROM [ucce-hds-a.example.com].[ucce_awdb].[dbo].[t_Agent_Team_Member] t | FROM FROM [ucce-hds-a.example.com].[ucce_awdb].[dbo].[t_Agent_Team_Member] t | ||
| </ | </ | ||
| + | |||
| + | ==== 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> | ||
| + | # Author: Gerry O' | ||
| + | # June 2023 | ||
| + | |||
| + | from datetime import datetime | ||
| + | import sys | ||
| + | import pyodbc | ||
| + | import requests | ||
| + | from requests.auth import HTTPBasicAuth | ||
| + | import xml.etree.ElementTree as ET | ||
| + | import urllib3 | ||
| + | urllib3.disable_warnings() | ||
| + | |||
| + | version = 1.0 | ||
| + | cce_api_hostname = " | ||
| + | debug_level = 1 # 0 error and high level info, 1 = more info , 2 = include responses from update agents | ||
| + | |||
| + | # Reference: https:// | ||
| + | |||
| + | # exit codes | ||
| + | # 0 : Success | ||
| + | # 1 : Argument not set | ||
| + | # 10 : Error retrieving Team Details | ||
| + | # 11 : update to retrieve agent details failed (need to get changeStamp) or unable to retrieve agent timestamp | ||
| + | # 12 : Update to Agent Failed | ||
| + | # 13 : Error retrieving Team Skills | ||
| + | # 14 : Error retrieving Team Agents | ||
| + | |||
| + | # 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): | ||
| + | logToDatabase(6, | ||
| + | |||
| + | rows = cursor.execute( | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | (departmentid)) | ||
| + | |||
| + | global teamId | ||
| + | global apiPassword | ||
| + | |||
| + | for row in list(rows): | ||
| + | try: | ||
| + | teamId = row[0] | ||
| + | global apiUserName | ||
| + | apiUserName = row[1] | ||
| + | global apiPassword | ||
| + | apiPassword = row[2] | ||
| + | print(" | ||
| + | print(" | ||
| + | print(" | ||
| + | logToDatabase(6, | ||
| + | getTeamSkills(teamId) | ||
| + | getTeamAgents(teamId) | ||
| + | |||
| + | except Exception as e: | ||
| + | errorstr = e | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(10) | ||
| + | |||
| + | |||
| + | def getTeamSkills(teamid): | ||
| + | rows = cursor.execute( | ||
| + | ' | ||
| + | |||
| + | global skills | ||
| + | |||
| + | n = 0 | ||
| + | for row in list(rows): | ||
| + | try: | ||
| + | skillid = row[0] | ||
| + | if (n == 0): | ||
| + | n = n + 1 | ||
| + | skills = [skillid] | ||
| + | else: | ||
| + | n = n + 1 | ||
| + | skills.append(skillid) | ||
| + | |||
| + | except Exception as e: | ||
| + | errorstr = e | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(13) | ||
| + | |||
| + | print(" | ||
| + | |||
| + | |||
| + | def getTeamAgents(teamid): | ||
| + | rows = cursor.execute( | ||
| + | ' | ||
| + | 'LEFT JOIN Agent_Team AT ON ATM.AgentTeamID = AT.AgentTeamID WHERE A.Deleted = \' | ||
| + | 'ORDER BY SkillTargetID', | ||
| + | (teamid)) | ||
| + | |||
| + | global agents | ||
| + | |||
| + | n = 0 | ||
| + | for row in list(rows): | ||
| + | try: | ||
| + | agentid = row[0] | ||
| + | changeStamp = getAgentChangeStamp(apiUserName, | ||
| + | # print (' | ||
| + | agentUpdateStatus = updateAgentSkills(apiUserName, | ||
| + | if agentUpdateStatus != 200: | ||
| + | exit(12) | ||
| + | if (n == 0): | ||
| + | n = n + 1 | ||
| + | agents = [agentid] | ||
| + | else: | ||
| + | n = n + 1 | ||
| + | agents.append(agentid) | ||
| + | |||
| + | except Exception as e: | ||
| + | errorstr = e | ||
| + | print(errorstr) | ||
| + | logToDatabase(3, | ||
| + | exit(14) | ||
| + | |||
| + | print(" | ||
| + | |||
| + | # Check if Web Service API is in service | ||
| + | |||
| + | |||
| + | def getApiStatus(): | ||
| + | api_url = f' | ||
| + | response = requests.get(api_url, | ||
| + | status_code = response.status_code | ||
| + | return (status_code) | ||
| + | |||
| + | |||
| + | 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) | ||
| + | # print (responseXml.tag) | ||
| + | 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. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | |||