""" The CS! (Configuration Service) Modified to work with Tornado Encode data in base64 because of JSON limitations In client side you must use a specific client """ from __future__ import absolute_import from __future__ import division from __future__ import print_function __RCSID__ = "45ddde113 (2021-10-01 11:19:55 +0200) Chris Burr " from base64 import b64encode, b64decode from DIRAC import S_OK, S_ERROR, gLogger from DIRAC.ConfigurationSystem.private.ServiceInterfaceTornado import ServiceInterfaceTornado as ServiceInterface from DIRAC.Core.Tornado.Server.TornadoService import TornadoService sLog = gLogger.getSubLogger(__name__) class TornadoConfigurationHandler(TornadoService): """ The CS handler """ ServiceInterface = None PilotSynchronizer = None @classmethod def initializeHandler(cls, serviceInfo): """ Initialize the configuration server Behind it starts thread which refresh configuration """ cls.ServiceInterface = ServiceInterface(serviceInfo["URL"]) return S_OK() def export_getVersion(self): """ Returns the version of the configuration """ return S_OK(self.ServiceInterface.getVersion()) def export_getCompressedData(self): """ Returns the configuration """ sData = self.ServiceInterface.getCompressedConfigurationData() return S_OK(b64encode(sData).decode()) def export_getCompressedDataIfNewer(self, sClientVersion): """ Returns the configuration if a newer configuration exists, if not just returns the version :param sClientVersion: Version used by client """ sVersion = self.ServiceInterface.getVersion() retDict = {"newestVersion": sVersion} if sClientVersion < sVersion: retDict["data"] = b64encode(self.ServiceInterface.getCompressedConfigurationData()).decode() return S_OK(retDict) def export_publishSlaveServer(self, sURL): """ Used by slave server to register as a slave server. :param sURL: The url of the slave server. """ self.ServiceInterface.publishSlaveServer(sURL) return S_OK() def export_commitNewData(self, sData): """ Write the new configuration """ credDict = self.getRemoteCredentials() if "DN" not in credDict or "username" not in credDict: return S_ERROR("You must be authenticated!") sData = b64decode(sData) return self.ServiceInterface.updateConfiguration(sData, credDict["username"]) def export_writeEnabled(self): """ Used to know if we can change the configuration on this server """ return S_OK(self.ServiceInterface.isMaster()) def export_getCommitHistory(self, limit=100): """ Get the history of modifications in the configuration """ if limit > 100: limit = 100 history = self.ServiceInterface.getCommitHistory() if limit: history = history[:limit] return S_OK(history) def export_getVersionContents(self, versionList): """ Get an old version of the configuration, can also be used to get more than one version. :param versionList: List of the version we are trying to get """ contentsList = [] for version in versionList: retVal = self.ServiceInterface.getVersionContents(version) if retVal["OK"]: contentsList.append(retVal["Value"]) else: return S_ERROR("Can't get contents for version %s: %s" % (version, retVal["Message"])) return S_OK(contentsList) def export_rollbackToVersion(self, version): """ Rollback to an older version of the configuration :param version: The version we want to apply """ retVal = self.ServiceInterface.getVersionContents(version) if not retVal["OK"]: return S_ERROR("Can't get contents for version %s: %s" % (version, retVal["Message"])) credDict = self.getRemoteCredentials() if "DN" not in credDict or "username" not in credDict: return S_ERROR("You must be authenticated!") return self.ServiceInterface.updateConfiguration( retVal["Value"], credDict["username"], updateVersionOption=True )