""" GOCDBSyncCommand module This command updates the downtime dates from the DowntimeCache table in case they changed after being fetched from GOCDB. In other words, it ensures that all the downtime dates in the database are current. """ from __future__ import absolute_import from __future__ import division from __future__ import print_function __RCSID__ = "c59810311 (2021-10-01 10:44:25 +0200) Chris Burr " import errno import xml.dom.minidom as minidom from DIRAC import S_OK, S_ERROR, gLogger from DIRAC.Core.LCG.GOCDBClient import GOCDBClient from DIRAC.Core.LCG.GOCDBClient import _parseSingleElement from DIRAC.ResourceStatusSystem.Command.Command import Command from DIRAC.ResourceStatusSystem.Client.ResourceManagementClient import ResourceManagementClient class GOCDBSyncCommand(Command): def __init__(self, args=None, clients=None): super(GOCDBSyncCommand, self).__init__(args, clients) if "GOCDBClient" in self.apis: self.gClient = self.apis["GOCDBClient"] else: self.gClient = GOCDBClient() if "ResourceManagementClient" in self.apis: self.rmClient = self.apis["ResourceManagementClient"] else: self.rmClient = ResourceManagementClient() self.seenHostnames = set() def doNew(self, masterParams=None): """ Gets the downtime IDs and dates of a given hostname from the local database and compares the results with the remote database of GOCDB. If the downtime dates have been changed it updates the local database. :param: `masterParams` - string :return: S_OK / S_ERROR """ if masterParams: hostname = masterParams else: return S_ERROR(errno.EINVAL, "masterParams is not provided") result = self.rmClient.selectDowntimeCache(name=hostname) if not result["OK"]: return result for downtimes in result["Value"]: localDBdict = { "DowntimeID": downtimes[3], "FORMATED_START_DATE": downtimes[6].strftime("%Y-%m-%d %H:%M"), "FORMATED_END_DATE": downtimes[7].strftime("%Y-%m-%d %H:%M"), } response = self.gClient.getHostnameDowntime(hostname, ongoing=True) if not response["OK"]: return response doc = minidom.parseString(response["Value"]) downtimeElements = doc.getElementsByTagName("DOWNTIME") for dtElement in downtimeElements: GOCDBdict = _parseSingleElement( dtElement, ["PRIMARY_KEY", "ENDPOINT", "FORMATED_START_DATE", "FORMATED_END_DATE"] ) localDowntimeID = localDBdict["DowntimeID"] GOCDBDowntimeID = GOCDBdict["PRIMARY_KEY"] + " " + GOCDBdict["ENDPOINT"] if localDowntimeID == GOCDBDowntimeID: if localDBdict["FORMATED_START_DATE"] != GOCDBdict["FORMATED_START_DATE"]: result = self.rmClient.addOrModifyDowntimeCache( downtimeID=localDBdict["DowntimeID"], startDate=GOCDBdict["FORMATED_START_DATE"] ) gLogger.verbose("The start date of %s has been changed!" % downtimes[3]) if not result["OK"]: return result if localDBdict["FORMATED_END_DATE"] != GOCDBdict["FORMATED_END_DATE"]: result = self.rmClient.addOrModifyDowntimeCache( downtimeID=localDBdict["DowntimeID"], endDate=GOCDBdict["FORMATED_END_DATE"] ) gLogger.verbose("The end date of %s has been changed!" % downtimes[3]) if not result["OK"]: return result return S_OK() def doCache(self): return S_OK() def doMaster(self): """ This method calls the doNew method for each hostname that exists in the DowntimeCache table of the local database. :return: S_OK / S_ERROR """ # Query DB for all downtimes result = self.rmClient.selectDowntimeCache() if not result["OK"]: return result for data in result["Value"]: # If already processed don't do it again if data[0] in self.seenHostnames: continue # data[0] contains the hostname gLogger.verbose("Checking if the downtime of %s has been changed" % data[0]) result = self.doNew(data[0]) if not result["OK"]: return result self.seenHostnames.add(data[0]) return S_OK()