示例#1
0
    def _parseConfigTemplate(self, templatePath, cfg=None):
        """Parse the ConfigTemplate.cfg files.

    :param str templatePath: path to the folder containing a ConfigTemplate.cfg file
    :param CFG cfg: cfg to merge with the systems config
    :returns: CFG object
    """
        cfg = CFG() if cfg is None else cfg

        system = os.path.split(templatePath.rstrip("/"))[1]
        if system.lower().endswith('system'):
            system = system[:-len('System')]

        if self.systems and system not in self.systems:
            return S_OK(cfg)

        templatePath = os.path.join(templatePath, 'ConfigTemplate.cfg')
        if not os.path.exists(templatePath):
            return S_ERROR("File not found: %s" % templatePath)

        loadCfg = CFG()
        loadCfg.loadFromFile(templatePath)

        newCfg = CFG()
        newCfg.createNewSection("/%s" % system, contents=loadCfg)

        cfg = cfg.mergeWith(newCfg)

        return S_OK(cfg)
示例#2
0
    def __getCache(self):
        Operations.__cacheLock.acquire()
        try:
            currentVersion = gConfigurationData.getVersion()
            if currentVersion != Operations.__cacheVersion:
                Operations.__cache = {}
                Operations.__cacheVersion = currentVersion

            cacheKey = (self.__vo, self.__setup)
            if cacheKey in Operations.__cache:
                return Operations.__cache[cacheKey]

            mergedCFG = CFG()

            for path in self.__getSearchPaths():
                pathCFG = gConfigurationData.mergedCFG[path]
                if pathCFG:
                    mergedCFG = mergedCFG.mergeWith(pathCFG)

            Operations.__cache[cacheKey] = mergedCFG

            return Operations.__cache[cacheKey]
        finally:
            try:
                Operations.__cacheLock.release()
            except thread.error:
                pass
示例#3
0
    def _loadWebAppCFGFiles(self, extension):
        """
        Load WebApp/web.cfg definitions

        :param str extension: the module name of the extension of WebAppDirac for example: LHCbWebDIRAC
        """
        webCFG = CFG()
        for modName in ["WebAppDIRAC", extension]:
            cfgPath = join(self._destination, modName, "WebApp", "web.cfg")
            if not isfile(cfgPath):
                logging.info(f"Web configuration file {cfgPath} does not exists!")
                continue
            try:
                modCFG = CFG().loadFromFile(cfgPath)
            except Exception as e:
                logging.error(f"Could not load {cfgPath}: {e}")
                continue
            logging.info(f"Loaded {cfgPath}")
            expl = ["/WebApp"]
            while expl:
                current = expl.pop(0)
                if not modCFG.isSection(current):
                    continue
                if modCFG.getOption(f"{current}/AbsoluteDefinition", False):
                    logging.info(f"{modName}:{current} is an absolute definition")
                    try:
                        webCFG.deleteKey(current)
                    except Exception:
                        pass
                    modCFG.deleteKey(f"{current}/AbsoluteDefinition")
                else:
                    expl += [f"{current}/{sec}" for sec in modCFG[current].listSections()]
            # Add the modCFG
            webCFG = webCFG.mergeWith(modCFG)
        return webCFG
示例#4
0
    def updateCompleteDiracCFG(self):
        """Read the dirac.cfg and update the Systems sections from the ConfigTemplate.cfg files."""
        compCfg = CFG()
        mainDiracCfgPath = self.config.cfg_baseFile

        if not os.path.exists(mainDiracCfgPath):
            LOG.error("Failed to find Main Dirac cfg at %r", mainDiracCfgPath)
            return 1

        self.prepareDiracCFG()

        LOG.info("Extracting default configuration from %r", mainDiracCfgPath)
        loadCFG = CFG()
        loadCFG.loadFromFile(mainDiracCfgPath)
        compCfg = loadCFG.mergeWith(compCfg)

        cfg = self.getSystemsCFG()
        compCfg = compCfg.mergeWith(cfg)
        diracCfgOutput = self.config.cfg_targetFile

        LOG.info("Writing output to %r", diracCfgOutput)

        with open(diracCfgOutput, "w") as rst:
            rst.write(
                textwrap.dedent(
                    """
                                .. _full_configuration_example:

                                ==========================
                                Full Configuration Example
                                ==========================

                                .. This file is created by docs/Tools/UpdateDiracCFG.py

                                Below is a complete example configuration with anotations for some sections::

                                """
                )
            )
            # indent the cfg text
            cfgString = "".join("  " + line for line in str(compCfg).splitlines(True))
            # fix the links, add back the # for targets
            # match .html with following character using positive look ahead
            htmlMatch = re.compile(r"\.html(?=[a-zA-Z0-9])")
            cfgString = re.sub(htmlMatch, ".html#", cfgString)
            rst.write(cfgString)
        return self.retVal
示例#5
0
 def mergeWithServer(self):
     retVal = self.rpcClient.getCompressedData()
     if retVal["OK"]:
         remoteCFG = CFG()
         data = retVal["Value"]
         if isinstance(data, str):
             data = data.encode(errors="surrogateescape")
         remoteCFG.loadFromBuffer(zlib.decompress(data).decode())
         serverVersion = gConfigurationData.getVersion(remoteCFG)
         self.cfgData = remoteCFG.mergeWith(self.cfgData)
         gConfigurationData.setVersion(serverVersion, self.cfgData)
     return retVal
示例#6
0
class Modificator(object):
    def __init__(self, rpcClient=False, commiterId="unknown"):
        self.commiterTag = "@@-"
        self.commiterId = commiterId
        self.cfgData = CFG()
        self.rpcClient = None
        if rpcClient:
            self.setRPCClient(rpcClient)

    def loadCredentials(self):
        retVal = getProxyInfo()
        if retVal["OK"]:
            credDict = retVal["Value"]
            self.commiterId = "%s@%s - %s" % (
                credDict["username"],
                credDict["group"],
                datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
            )
            return retVal
        return retVal

    def setRPCClient(self, rpcClient):
        self.rpcClient = rpcClient

    def loadFromRemote(self):
        retVal = self.rpcClient.getCompressedData()
        if retVal["OK"]:
            self.cfgData = CFG()
            data = retVal["Value"]
            if isinstance(data, str):
                data = data.encode(errors="surrogateescape")
            self.cfgData.loadFromBuffer(zlib.decompress(data).decode())
        return retVal

    def getCFG(self):
        return self.cfgData

    def getSections(self, sectionPath):
        return gConfigurationData.getSectionsFromCFG(sectionPath, self.cfgData)

    def getComment(self, sectionPath):
        return gConfigurationData.getCommentFromCFG(sectionPath, self.cfgData)

    def getOptions(self, sectionPath):
        return gConfigurationData.getOptionsFromCFG(sectionPath, self.cfgData)

    def getOptionsDict(self, sectionPath):
        """Gives the options of a CS section in a Python dict with values as
        lists"""

        opts = self.getOptions(sectionPath)
        pathDict = dict(
            (o, self.getValue("%s/%s" % (sectionPath, o))) for o in opts)
        return pathDict

    def getDictRootedAt(self, relpath="", root=""):
        """Gives the configuration rooted at path in a Python dict. The
        result is a Python dictionary that reflects the structure of the
        config file."""
        def getDictRootedAt(path):
            retval = {}
            opts = self.getOptionsDict(path)
            secs = self.getSections(path)
            for k in opts:
                retval[k] = opts[k]
            for i in secs:
                retval[i] = getDictRootedAt(path + "/" + i)
            return retval

        return getDictRootedAt(root + "/" + relpath)

    def getValue(self, optionPath):
        return gConfigurationData.extractOptionFromCFG(optionPath,
                                                       self.cfgData)

    def sortAlphabetically(self, path, ascending=True):
        cfg = self.__getParentCFG(path, parentLevel=0)
        if cfg:
            if cfg.sortAlphabetically(ascending):
                self.__setCommiter(path)

    def __getParentCFG(self, path, parentLevel=1):
        sectionList = List.fromChar(path, "/")
        cfg = self.cfgData
        try:
            if parentLevel > 0:
                sectionList = sectionList[:-parentLevel]
            for section in sectionList:
                cfg = cfg[section]
            return cfg
        except Exception:
            return False

    def __setCommiter(self, entryPath, cfg=False):
        if not cfg:
            cfg = self.__getParentCFG(entryPath)
        entry = List.fromChar(entryPath, "/")[-1]
        comment = cfg.getComment(entry)
        filteredComment = [
            line.strip() for line in comment.split("\n")
            if line.find(self.commiterTag) != 0
        ]
        filteredComment.append("%s%s" % (self.commiterTag, self.commiterId))
        cfg.setComment(entry, "\n".join(filteredComment))

    def setOptionValue(self, optionPath, value):
        levelList = [
            level.strip() for level in optionPath.split("/")
            if level.strip() != ""
        ]
        parentPath = "/%s" % "/".join(levelList[:-1])
        optionName = List.fromChar(optionPath, "/")[-1]
        self.createSection(parentPath)
        cfg = self.__getParentCFG(optionPath)
        if not cfg:
            return
        cfg.setOption(optionName, value)
        self.__setCommiter(optionPath, cfg)

    def createSection(self, sectionPath):
        levelList = [
            level.strip() for level in sectionPath.split("/")
            if level.strip() != ""
        ]
        currentPath = ""
        cfg = self.cfgData
        createdSection = False
        for section in levelList:
            currentPath += "/%s" % section
            if section not in cfg.listSections():
                cfg.createNewSection(section)
                self.__setCommiter(currentPath)
                createdSection = True
            cfg = cfg[section]
        return createdSection

    def setComment(self, entryPath, value):
        cfg = self.__getParentCFG(entryPath)
        entry = List.fromChar(entryPath, "/")[-1]
        if cfg.setComment(entry, value):
            self.__setCommiter(entryPath)
            return True
        return False

    def existsSection(self, sectionPath):
        sectionList = List.fromChar(sectionPath, "/")
        cfg = self.cfgData
        try:
            for section in sectionList[:-1]:
                cfg = cfg[section]
            return len(
                sectionList) == 0 or sectionList[-1] in cfg.listSections()
        except Exception:
            return False

    def existsOption(self, optionPath):
        sectionList = List.fromChar(optionPath, "/")
        cfg = self.cfgData
        try:
            for section in sectionList[:-1]:
                cfg = cfg[section]
            return sectionList[-1] in cfg.listOptions()
        except Exception:
            return False

    def renameKey(self, path, newName):
        parentCfg = self.cfgData.getRecursive(path, -1)
        if not parentCfg:
            return False
        pathList = List.fromChar(path, "/")
        oldName = pathList[-1]
        if parentCfg["value"].renameKey(oldName, newName):
            pathList[-1] = newName
            self.__setCommiter("/%s" % "/".join(pathList))
            return True
        else:
            return False

    def copyKey(self, originalKeyPath, newKey):
        parentCfg = self.cfgData.getRecursive(originalKeyPath, -1)
        if not parentCfg:
            return False
        pathList = List.fromChar(originalKeyPath, "/")
        originalKey = pathList[-1]
        if parentCfg["value"].copyKey(originalKey, newKey):
            self.__setCommiter("/%s/%s" % ("/".join(pathList[:-1]), newKey))
            return True
        return False

    def removeOption(self, optionPath):
        if not self.existsOption(optionPath):
            return False
        cfg = self.__getParentCFG(optionPath)
        optionName = List.fromChar(optionPath, "/")[-1]
        return cfg.deleteKey(optionName)

    def removeSection(self, sectionPath):
        if not self.existsSection(sectionPath):
            return False
        cfg = self.__getParentCFG(sectionPath)
        sectionName = List.fromChar(sectionPath, "/")[-1]
        return cfg.deleteKey(sectionName)

    def loadFromBuffer(self, data):
        self.cfgData = CFG()
        self.cfgData.loadFromBuffer(data)

    def loadFromFile(self, filename):
        self.cfgData = CFG()
        self.mergeFromFile(filename)

    def dumpToFile(self, filename):
        with open(filename, "wt") as fd:
            fd.write(str(self.cfgData))

    def mergeFromFile(self, filename):
        cfg = CFG()
        cfg.loadFromFile(filename)
        self.cfgData = self.cfgData.mergeWith(cfg)

    def mergeFromCFG(self, cfg):
        self.cfgData = self.cfgData.mergeWith(cfg)

    def mergeSectionFromCFG(self, sectionPath, cfg):
        parentDict = self.cfgData.getRecursive(sectionPath, -1)
        parentCFG = parentDict["value"]
        secName = [
            lev.strip() for lev in sectionPath.split("/") if lev.strip()
        ][-1]
        secCFG = parentCFG[secName]
        if not secCFG:
            return False
        mergedCFG = secCFG.mergeWith(cfg)
        parentCFG.deleteKey(secName)
        parentCFG.createNewSection(secName, parentDict["comment"], mergedCFG)
        self.__setCommiter(sectionPath)
        return True

    def __str__(self):
        return str(self.cfgData)

    def commit(self):
        compressedData = zlib.compress(str(self.cfgData).encode(), 9)
        return self.rpcClient.commitNewData(compressedData)

    def getHistory(self, limit=0):
        retVal = self.rpcClient.getCommitHistory(limit)
        if retVal["OK"]:
            return retVal["Value"]
        return []

    def showCurrentDiff(self):
        retVal = self.rpcClient.getCompressedData()
        if retVal["OK"]:
            data = retVal["Value"]
            if isinstance(data, str):
                data = data.encode(errors="surrogateescape")
            remoteData = zlib.decompress(data).decode().splitlines()
            localData = str(self.cfgData).splitlines()
            return difflib.ndiff(remoteData, localData)
        return []

    def getVersionDiff(self, fromDate, toDate):
        retVal = self.rpcClient.getVersionContents([fromDate, toDate])
        if retVal["OK"]:
            fromData = retVal["Value"][0]
            if isinstance(fromData, str):
                fromData = fromData.encode(errors="surrogateescape")
            fromData = zlib.decompress(fromData).decode()

            toData = retVal["Value"][1]
            if isinstance(toData, str):
                toData = toData.encode(errors="surrogateescape")
            toData = zlib.decompress(toData).decode()

            return difflib.ndiff(fromData.split("\n"), toData.split("\n"))
        return []

    def mergeWithServer(self):
        retVal = self.rpcClient.getCompressedData()
        if retVal["OK"]:
            remoteCFG = CFG()
            data = retVal["Value"]
            if isinstance(data, str):
                data = data.encode(errors="surrogateescape")
            remoteCFG.loadFromBuffer(zlib.decompress(data).decode())
            serverVersion = gConfigurationData.getVersion(remoteCFG)
            self.cfgData = remoteCFG.mergeWith(self.cfgData)
            gConfigurationData.setVersion(serverVersion, self.cfgData)
        return retVal

    def rollbackToVersion(self, version):
        return self.rpcClient.rollbackToVersion(version)

    def updateGConfigurationData(self):
        gConfigurationData.setRemoteCFG(self.cfgData)
示例#7
0
class ConfigurationData(object):
    def __init__(self, loadDefaultCFG=True):
        envVar = os.environ.get("DIRAC_FEWER_CFG_LOCKS", "no").lower()
        self.__locksEnabled = envVar not in ("y", "yes", "t", "true", "on",
                                             "1")
        if self.__locksEnabled:
            lr = LockRing()
            self.threadingEvent = lr.getEvent()
            self.threadingEvent.set()
            self.threadingLock = lr.getLock()
            self.runningThreadsNumber = 0

        self.__compressedConfigurationData = None
        self.configurationPath = "/DIRAC/Configuration"
        self.backupsDir = os.path.join(DIRAC.rootPath, "etc", "csbackup")
        self._isService = False
        self.localCFG = CFG()
        self.remoteCFG = CFG()
        self.mergedCFG = CFG()
        self.remoteServerList = []
        if loadDefaultCFG:
            defaultCFGFile = os.path.join(DIRAC.rootPath, "etc", "dirac.cfg")
            gLogger.debug("dirac.cfg should be at", "%s" % defaultCFGFile)
            retVal = self.loadFile(defaultCFGFile)
            if not retVal["OK"]:
                gLogger.warn("Can't load %s file" % defaultCFGFile)
        self.sync()

    def getBackupDir(self):
        return self.backupsDir

    def sync(self):
        gLogger.debug("Updating configuration internals")
        self.mergedCFG = self.remoteCFG.mergeWith(self.localCFG)
        self.remoteServerList = []
        localServers = self.extractOptionFromCFG("%s/Servers" %
                                                 self.configurationPath,
                                                 self.localCFG,
                                                 disableDangerZones=True)
        if localServers:
            self.remoteServerList.extend(List.fromChar(localServers, ","))
        remoteServers = self.extractOptionFromCFG("%s/Servers" %
                                                  self.configurationPath,
                                                  self.remoteCFG,
                                                  disableDangerZones=True)
        if remoteServers:
            self.remoteServerList.extend(List.fromChar(remoteServers, ","))
        self.remoteServerList = List.uniqueElements(self.remoteServerList)
        self.__compressedConfigurationData = None

    def loadFile(self, fileName):
        try:
            fileCFG = CFG()
            fileCFG.loadFromFile(fileName)
        except IOError:
            self.localCFG = self.localCFG.mergeWith(fileCFG)
            return S_ERROR("Can't load a cfg file '%s'" % fileName)
        return self.mergeWithLocal(fileCFG)

    def mergeWithLocal(self, extraCFG):
        self.lock()
        try:
            self.localCFG = self.localCFG.mergeWith(extraCFG)
            self.unlock()
            gLogger.debug("CFG merged")
        except Exception as e:
            self.unlock()
            return S_ERROR("Cannot merge with new cfg: %s" % str(e))
        self.sync()
        return S_OK()

    def loadRemoteCFGFromCompressedMem(self, data):
        if six.PY3 and isinstance(data, str):
            data = data.encode(errors="surrogateescape")
        sUncompressedData = zlib.decompress(data).decode()
        self.loadRemoteCFGFromMem(sUncompressedData)

    def loadRemoteCFGFromMem(self, data):
        self.lock()
        self.remoteCFG.loadFromBuffer(data)
        self.unlock()
        self.sync()

    def loadConfigurationData(self, fileName=False):
        name = self.getName()
        self.lock()
        try:
            if not fileName:
                fileName = "%s.cfg" % name
            if fileName[0] != "/":
                fileName = os.path.join(DIRAC.rootPath, "etc", fileName)
            self.remoteCFG.loadFromFile(fileName)
        except Exception as e:
            print(e)
        self.unlock()
        self.sync()

    def getCommentFromCFG(self, path, cfg=False):
        if not cfg:
            cfg = self.mergedCFG
        self.dangerZoneStart()
        try:
            levelList = [
                level.strip() for level in path.split("/")
                if level.strip() != ""
            ]
            for section in levelList[:-1]:
                cfg = cfg[section]
            return self.dangerZoneEnd(cfg.getComment(levelList[-1]))
        except Exception:
            pass
        return self.dangerZoneEnd(None)

    def getSectionsFromCFG(self, path, cfg=False, ordered=False):
        if not cfg:
            cfg = self.mergedCFG
        self.dangerZoneStart()
        try:
            levelList = [
                level.strip() for level in path.split("/")
                if level.strip() != ""
            ]
            for section in levelList:
                cfg = cfg[section]
            return self.dangerZoneEnd(cfg.listSections(ordered))
        except Exception:
            pass
        return self.dangerZoneEnd(None)

    def getOptionsFromCFG(self, path, cfg=False, ordered=False):
        if not cfg:
            cfg = self.mergedCFG
        self.dangerZoneStart()
        try:
            levelList = [
                level.strip() for level in path.split("/")
                if level.strip() != ""
            ]
            for section in levelList:
                cfg = cfg[section]
            return self.dangerZoneEnd(cfg.listOptions(ordered))
        except Exception:
            pass
        return self.dangerZoneEnd(None)

    def extractOptionFromCFG(self, path, cfg=False, disableDangerZones=False):
        if not cfg:
            cfg = self.mergedCFG
        if not disableDangerZones:
            self.dangerZoneStart()
        try:
            levelList = [
                level.strip() for level in path.split("/")
                if level.strip() != ""
            ]
            for section in levelList[:-1]:
                cfg = cfg[section]
            if levelList[-1] in cfg.listOptions():
                return self.dangerZoneEnd(cfg[levelList[-1]])
        except Exception:
            pass
        if not disableDangerZones:
            self.dangerZoneEnd()

    def setOptionInCFG(self, path, value, cfg=False, disableDangerZones=False):
        if not cfg:
            cfg = self.localCFG
        if not disableDangerZones:
            self.dangerZoneStart()
        try:
            levelList = [
                level.strip() for level in path.split("/")
                if level.strip() != ""
            ]
            for section in levelList[:-1]:
                if section not in cfg.listSections():
                    cfg.createNewSection(section)
                cfg = cfg[section]
            cfg.setOption(levelList[-1], value)
        finally:
            if not disableDangerZones:
                self.dangerZoneEnd()
        self.sync()

    def deleteOptionInCFG(self, path, cfg=False):
        if not cfg:
            cfg = self.localCFG
        self.dangerZoneStart()
        try:
            levelList = [
                level.strip() for level in path.split("/")
                if level.strip() != ""
            ]
            for section in levelList[:-1]:
                if section not in cfg.listSections():
                    return
                cfg = cfg[section]
            cfg.deleteKey(levelList[-1])
        finally:
            self.dangerZoneEnd()
        self.sync()

    def generateNewVersion(self):
        self.setVersion(Time.toString())
        self.sync()
        gLogger.info("Generated new version %s" % self.getVersion())

    def setVersion(self, version, cfg=False):
        if not cfg:
            cfg = self.remoteCFG
        self.setOptionInCFG("%s/Version" % self.configurationPath, version,
                            cfg)

    def getVersion(self, cfg=False):
        if not cfg:
            cfg = self.remoteCFG
        value = self.extractOptionFromCFG(
            "%s/Version" % self.configurationPath, cfg)
        if value:
            return value
        return "0"

    def getName(self):
        return self.extractOptionFromCFG("%s/Name" % self.configurationPath,
                                         self.mergedCFG)

    def exportName(self):
        return self.setOptionInCFG("%s/Name" % self.configurationPath,
                                   self.getName(), self.remoteCFG)

    def getRefreshTime(self):
        try:
            return int(
                self.extractOptionFromCFG(
                    "%s/RefreshTime" % self.configurationPath, self.mergedCFG))
        except Exception:
            return 300

    def getPropagationTime(self):
        try:
            return int(
                self.extractOptionFromCFG(
                    "%s/PropagationTime" % self.configurationPath,
                    self.mergedCFG))
        except Exception:
            return 300

    def getSlavesGraceTime(self):
        try:
            return int(
                self.extractOptionFromCFG(
                    "%s/SlavesGraceTime" % self.configurationPath,
                    self.mergedCFG))
        except Exception:
            return 600

    def mergingEnabled(self):
        try:
            val = self.extractOptionFromCFG(
                "%s/EnableAutoMerge" % self.configurationPath, self.mergedCFG)
            return val.lower() in ("yes", "true", "y")
        except Exception:
            return False

    def getAutoPublish(self):
        value = self.extractOptionFromCFG(
            "%s/AutoPublish" % self.configurationPath, self.localCFG)
        if value and value.lower() in ("no", "false", "n"):
            return False
        else:
            return True

    def getAutoSlaveSync(self):
        value = self.extractOptionFromCFG(
            "%s/AutoSlaveSync" % self.configurationPath, self.localCFG)
        if value and value.lower() in ("no", "false", "n"):
            return False
        else:
            return True

    def getServers(self):
        return list(self.remoteServerList)

    def getConfigurationGateway(self):
        return self.extractOptionFromCFG("/DIRAC/Gateway", self.localCFG)

    def setServers(self, sServers):
        self.setOptionInCFG("%s/Servers" % self.configurationPath, sServers,
                            self.remoteCFG)
        self.sync()

    def deleteLocalOption(self, optionPath):
        self.deleteOptionInCFG(optionPath, self.localCFG)

    def getMasterServer(self):
        return self.extractOptionFromCFG(
            "%s/MasterServer" % self.configurationPath, self.remoteCFG)

    def setMasterServer(self, sURL):
        self.setOptionInCFG("%s/MasterServer" % self.configurationPath, sURL,
                            self.remoteCFG)
        self.sync()

    def getCompressedData(self):
        if self.__compressedConfigurationData is None:
            self.__compressedConfigurationData = zlib.compress(
                str(self.remoteCFG).encode(), 9)
        return self.__compressedConfigurationData

    def isMaster(self):
        value = self.extractOptionFromCFG("%s/Master" % self.configurationPath,
                                          self.localCFG)
        if value and value.lower() in ("yes", "true", "y"):
            return True
        else:
            return False

    def getServicesPath(self):
        return "/Services"

    def setAsService(self):
        self._isService = True

    def isService(self):
        return self._isService

    def useServerCertificate(self):
        value = self.extractOptionFromCFG(
            "/DIRAC/Security/UseServerCertificate")
        if value and value.lower() in ("y", "yes", "true"):
            return True
        return False

    def skipCACheck(self):
        value = self.extractOptionFromCFG("/DIRAC/Security/SkipCAChecks")
        if value and value.lower() in ("y", "yes", "true"):
            return True
        return False

    def dumpLocalCFGToFile(self, fileName):
        try:
            with open(fileName, "w") as fd:
                fd.write(str(self.localCFG))
            gLogger.verbose("Configuration file dumped", "'%s'" % fileName)
        except IOError:
            gLogger.error("Can't dump cfg file", "'%s'" % fileName)
            return S_ERROR("Can't dump cfg file '%s'" % fileName)
        return S_OK()

    def getRemoteCFG(self):
        return self.remoteCFG

    def getMergedCFGAsString(self):
        return str(self.mergedCFG)

    def dumpRemoteCFGToFile(self, fileName):
        with open(fileName, "w") as fd:
            fd.write(str(self.remoteCFG))

    def __backupCurrentConfiguration(self, backupName):
        configurationFilename = "%s.cfg" % self.getName()
        configurationFile = os.path.join(DIRAC.rootPath, "etc",
                                         configurationFilename)
        today = Time.date()
        backupPath = os.path.join(self.getBackupDir(), str(today.year),
                                  "%02d" % today.month)
        mkDir(backupPath)
        backupFile = os.path.join(
            backupPath,
            configurationFilename.replace(".cfg", ".%s.zip" % backupName))
        if os.path.isfile(configurationFile):
            gLogger.info("Making a backup of configuration in %s" % backupFile)
            try:
                with zipfile.ZipFile(backupFile, "w",
                                     zipfile.ZIP_DEFLATED) as zf:
                    zf.write(
                        configurationFile, "%s.backup.%s" %
                        (os.path.split(configurationFile)[1], backupName))
            except Exception:
                gLogger.exception()
                gLogger.error("Cannot backup configuration data file",
                              "file %s" % backupFile)
        else:
            gLogger.warn("CS data file does not exist", configurationFile)

    def writeRemoteConfigurationToDisk(self, backupName=False):
        configurationFile = os.path.join(DIRAC.rootPath, "etc",
                                         "%s.cfg" % self.getName())
        try:
            with open(configurationFile, "w") as fd:
                fd.write(str(self.remoteCFG))
        except Exception as e:
            gLogger.fatal(
                "Cannot write new configuration to disk!",
                "file %s exception %s" % (configurationFile, repr(e)))
            return S_ERROR("Can't write cs file %s!: %s" %
                           (configurationFile, repr(e).replace(",)", ")")))
        if backupName:
            self.__backupCurrentConfiguration(backupName)
        return S_OK()

    def setRemoteCFG(self, cfg, disableSync=False):
        self.remoteCFG = cfg.clone()
        if not disableSync:
            self.sync()

    def lock(self):
        """
        Locks Event to prevent further threads from reading.
        Stops current thread until no other thread is accessing.
        PRIVATE USE
        """
        if not self.__locksEnabled:
            return
        self.threadingEvent.clear()
        while self.runningThreadsNumber > 0:
            time.sleep(0.1)

    def unlock(self):
        """
        Unlocks Event.
        PRIVATE USE
        """
        if not self.__locksEnabled:
            return
        self.threadingEvent.set()

    def dangerZoneStart(self):
        """
        Start of danger zone. This danger zone may be or may not be a mutual exclusion zone.
        Counter is maintained to know how many threads are inside and be able to enable and disable mutual exclusion.
        PRIVATE USE
        """
        if not self.__locksEnabled:
            return
        self.threadingEvent.wait()
        self.threadingLock.acquire()
        self.runningThreadsNumber += 1
        try:
            self.threadingLock.release()
        except thread.error:
            pass

    def dangerZoneEnd(self, returnValue=None):
        """
        End of danger zone.
        PRIVATE USE
        """
        if not self.__locksEnabled:
            return returnValue
        self.threadingLock.acquire()
        self.runningThreadsNumber -= 1
        try:
            self.threadingLock.release()
        except thread.error:
            pass
        return returnValue