Esempio n. 1
0
    def _getCurrentConfig(self):
        """Return the current system configuration."""
        from DIRAC.ConfigurationSystem.Client.ConfigurationData import gConfigurationData
        gConfig.forceRefresh()

        fullCfg = CFG()
        setup = gConfig.getValue('/DIRAC/Setup', '')
        setupList = gConfig.getSections('/DIRAC/Setups', [])
        if not setupList['OK']:
            return S_ERROR('Could not get /DIRAC/Setups sections')
        setupList = setupList['Value']
        if setup not in setupList:
            return S_ERROR('Setup %s is not in allowed list: %s' %
                           (setup, ', '.join(setupList)))
        serviceSetups = gConfig.getOptionsDict('/DIRAC/Setups/%s' % setup)
        if not serviceSetups['OK']:
            return S_ERROR('Could not get /DIRAC/Setups/%s options' % setup)
        serviceSetups = serviceSetups['Value']  # dict
        for system, setup in serviceSetups.items():
            if self.systems and system not in self.systems:
                continue
            systemCfg = gConfigurationData.remoteCFG.getAsCFG(
                "/Systems/%s/%s" % (system, setup))
            for section in systemCfg.listSections():
                if section not in ('Agents', 'Services', 'Executors'):
                    systemCfg.deleteKey(section)

            fullCfg.createNewSection("/%s" % system, contents=systemCfg)

        return S_OK(fullCfg)
 def export_setupComponent( self, componentType, system, component, componentModule='' ):
   """ Setup the specified component for running with the runsvdir daemon
       It implies installComponent
   """
   result = InstallTools.setupComponent( componentType, system, component, getCSExtensions(), componentModule )
   gConfig.forceRefresh()
   return result
Esempio n. 3
0
 def export_setupComponent( self, componentType, system, component, componentModule = '' ):
   """ Setup the specified component for running with the runsvdir daemon
       It implies installComponent
   """
   result = gComponentInstaller.setupComponent( componentType, system, component, getCSExtensions(), componentModule )
   gConfig.forceRefresh()
   return result
  def _getCurrentConfig(self):
    """Return the current system configuration."""
    from DIRAC.ConfigurationSystem.Client.ConfigurationData import gConfigurationData
    gConfig.forceRefresh()

    fullCfg = CFG()
    setup = gConfig.getValue('/DIRAC/Setup', '')
    setupList = gConfig.getSections('/DIRAC/Setups', [])
    if not setupList['OK']:
      return S_ERROR('Could not get /DIRAC/Setups sections')
    setupList = setupList['Value']
    if setup not in setupList:
      return S_ERROR('Setup %s is not in allowed list: %s' % (setup, ', '.join(setupList)))
    serviceSetups = gConfig.getOptionsDict('/DIRAC/Setups/%s' % setup)
    if not serviceSetups['OK']:
      return S_ERROR('Could not get /DIRAC/Setups/%s options' % setup)
    serviceSetups = serviceSetups['Value']  # dict
    for system, setup in serviceSetups.items():
      if self.systems and system not in self.systems:
        continue
      systemCfg = gConfigurationData.remoteCFG.getAsCFG("/Systems/%s/%s" % (system, setup))
      for section in systemCfg.listSections():
        if section not in ('Agents', 'Services', 'Executors'):
          systemCfg.deleteKey(section)

      fullCfg.createNewSection("/%s" % system, contents=systemCfg)

    return S_OK(fullCfg)
Esempio n. 5
0
  def execute(self):
    """ General agent execution method
    """
    self.voBdiiCEDict = {}

    # Get a "fresh" copy of the CS data
    result = self.csAPI.downloadCSData()
    if not result['OK']:
      self.log.warn("Could not download a fresh copy of the CS data", result['Message'])

    # Refresh the configuration from the master server
    gConfig.forceRefresh(fromMaster=True)

    if self.processCEs:
      self.__lookForNewCEs()
      self.__updateCEs()
    return S_OK()
Esempio n. 6
0
  def execute( self ):
    """ General agent execution method
    """
   
    # Get a "fresh" copy of the CS data
    result = self.csAPI.downloadCSData()
    if not result['OK']:
      self.log.warn( "Could not download a fresh copy of the CS data", result[ 'Message' ] )

    # Refresh the configuration from the master server
    gConfig.forceRefresh( fromMaster = True )

    if self.processCEs:
      self.__lookForNewCEs()
      self.__updateCEs()
    if self.processSEs:  
      self.__lookForNewSEs()
      self.__updateSEs()
    return S_OK()
    def checkURLs(self):
        """Ensure that the running services have their URL in the Config."""
        self.log.info("Checking URLs")
        # get services again, in case they were started/stop in controlComponents
        gConfig.forceRefresh(fromMaster=True)

        # get port used for https based services
        try:
            tornadoSystemInstance = PathFinder.getSystemInstance(
                system="Tornado",
                setup=self.setup,
            )
            self._tornadoPort = gConfig.getValue(
                Path.cfgPath("/System/Tornado/", tornadoSystemInstance,
                             "Port"),
                self._tornadoPort,
            )
        except RuntimeError:
            pass

        self.log.debug("Using Tornado Port:", self._tornadoPort)

        res = self.getRunningInstances(instanceType="Services",
                                       runitStatus="All")
        if not res["OK"]:
            return S_ERROR("Failure to get running services")
        self.services = res["Value"]
        for service, options in sorted(self.services.items()):
            self.log.debug("Checking URL for %s with options %s" %
                           (service, options))
            # ignore SystemAdministrator, does not have URLs
            if "SystemAdministrator" in service:
                continue
            self._checkServiceURL(service, options)

        if self.csAPI.csModified and self.commitURLs:
            self.log.info("Commiting changes to the CS")
            result = self.csAPI.commit()
            if not result["OK"]:
                self.logError("Commit to CS failed", result["Message"])
                return S_ERROR("Failed to commit to CS")
        return S_OK()
Esempio n. 8
0
    def getVOUserData(self, vo, refreshFlag=False):
        """ Get a report for users of a given VO

    :param str vo: VO name
    :return: S_OK/S_ERROR, Value = user description dictionary
    """
        if refreshFlag:
            gConfig.forceRefresh()

        # Get DIRAC users
        diracUsers = getUsersInVO(vo)
        if not diracUsers:
            return S_ERROR("No VO users found for %s" % vo)

        if refreshFlag:
            result = self.csapi.downloadCSData()
            if not result['OK']:
                return result
        result = self.csapi.describeUsers(diracUsers)
        if not result['OK']:
            self.log.error('Could not retrieve CS User description')
        return result
Esempio n. 9
0
  def doOAuthMagic(self):
    """ Magic method

        :return: S_OK()/S_ERROR()
    """
    nAuth = notebookAuth(self.__piParams.diracGroup, voms=self.__piParams.addVOMSExt, proxyPath=self.__piParams.proxyLoc)
    result = nAuth.getToken()
    if not result['OK']:
      return result
    aToken = result['Value'].get('access_token')
    if not aToken:
      return S_ERROR('Access token is absent in resporse.')
    result = nAuth.getProxyWithToken(aToken)
    if not result['OK']:
      return result

    result = Script.enableCS()
    if not result['OK']:
      return S_ERROR("Cannot contact CS to get user list")
    threading.Thread(target=self.checkCAs).start()
    gConfig.forceRefresh(fromMaster=True)
    return S_OK(self.__piParams.proxyLoc)
Esempio n. 10
0
  def getVOUserData( self, vo, refreshFlag = False ):
    """ Get a report for users of a given VO

    :param str vo: VO name
    :return: S_OK/S_ERROR, Value = user description dictionary
    """
    if refreshFlag:
      gConfig.forceRefresh()

    # Get DIRAC users
    diracUsers = getUsersInVO( vo )
    if not diracUsers:
      return S_ERROR( "No VO users found for %s" % vo )

    if refreshFlag:
      result = self.csapi.downloadCSData()
      if not result['OK']:
        return result
    result = self.csapi.describeUsers( diracUsers )
    if not result['OK']:
      self.log.error( 'Could not retrieve CS User description' )
    return result
Esempio n. 11
0
    def getVOUserData(self, refreshFlag=False):
        """Get a report for users of a given VO

        :param bool refreshFlag: flag to indicate that the configuration must be refreshed
                                 before looking up user data
        :return: S_OK/S_ERROR, Value = user description dictionary
        """
        if refreshFlag:
            gConfig.forceRefresh()

        # Get DIRAC users
        diracUsers = getUsersInVO(self.vo)
        if not diracUsers:
            return S_ERROR("No VO users found for %s" % self.vo)

        if refreshFlag:
            result = self.csapi.downloadCSData()
            if not result["OK"]:
                return result
        result = self.csapi.describeUsers(diracUsers)
        if not result["OK"]:
            self.log.error("Could not retrieve CS User description")
        return result
Esempio n. 12
0
  def getVOUserData(self, refreshFlag=False):
    """ Get a report for users of a given VO

    :param bool refreshFlag: flag to indicate that the configuration must be refreshed
                             before looking up user data
    :return: S_OK/S_ERROR, Value = user description dictionary
    """
    if refreshFlag:
      gConfig.forceRefresh()

    # Get DIRAC users
    diracUsers = getUsersInVO(self.vo)
    if not diracUsers:
      return S_ERROR("No VO users found for %s" % self.vo)

    if refreshFlag:
      result = self.csapi.downloadCSData()
      if not result['OK']:
        return result
    result = self.csapi.describeUsers(diracUsers)
    if not result['OK']:
      self.log.error('Could not retrieve CS User description')
    return result
Esempio n. 13
0
  def checkURLs(self):
    """Ensure that the running services have their URL in the Config."""
    self.log.info("Checking URLs")
    # get services again, in case they were started/stop in controlComponents
    gConfig.forceRefresh(fromMaster=True)
    res = self.getRunningInstances(instanceType='Services', runitStatus='All')
    if not res["OK"]:
      return S_ERROR("Failure to get running services")
    self.services = res["Value"]
    for service, options in self.services.iteritems():
      self.log.debug("Checking URL for %s with options %s" % (service, options))
      # ignore SystemAdministrator, does not have URLs
      if 'SystemAdministrator' in service:
        continue
      self._checkServiceURL(service, options)

    if self.csAPI.csModified and self.commitURLs:
      self.log.info("Commiting changes to the CS")
      result = self.csAPI.commit()
      if not result['OK']:
        self.logError('Commit to CS failed', result['Message'])
        return S_ERROR("Failed to commit to CS")
    return S_OK()
Esempio n. 14
0
 def __enableCS(self):
     if not (result := Script.enableCS())["OK"] or not (result := gConfig.forceRefresh())["OK"]:
         return S_ERROR(f"Cannot contact CS: {result['Message']}")
Esempio n. 15
0
def getSiteUpdates( vo, bdiiInfo = None, log = None ):
  """ Get all the necessary updates for the already defined sites and CEs
  """  
  
  def addToChangeSet( entry, changeSet ):
    _section, _option, value, new_value = entry
    if new_value and new_value != value:
      changeSet.add( entry )

  if log is None:
    log = gLogger  
    
  ceBdiiDict = bdiiInfo
  if bdiiInfo is None:
    result = getBdiiCEInfo( vo )    
    if not result['OK']:
      return result
    ceBdiiDict = result['Value']

  changeSet = set()
  gConfig.forceRefresh()

  for site in ceBdiiDict:
    result = getDIRACSiteName( site )
    if not result['OK']:
      continue
    siteNames = result['Value']
    for siteName in siteNames:
      siteSection = cfgPath( '/Resources', 'Sites', siteName.split('.')[0], siteName )
      result = gConfig.getOptionsDict( siteSection )
      if not result['OK']:
        continue
      siteDict = result['Value']
      # Current CS values
      coor = siteDict.get( 'Coordinates', 'Unknown' )
      mail = siteDict.get( 'Mail', 'Unknown' ).replace( ' ','' )
      description = siteDict.get( 'Description', 'Unknown' )
  
      longitude = ceBdiiDict[site].get( 'GlueSiteLongitude', '' ).strip()
      latitude = ceBdiiDict[site].get( 'GlueSiteLatitude', '' ).strip()
  
      # Current BDII value
      newcoor = ''
      if longitude and latitude:
        newcoor = "%s:%s" % ( longitude, latitude )
      newmail = ceBdiiDict[site].get( 'GlueSiteSysAdminContact', '' ).replace( 'mailto:', '' ).strip()
      newdescription = ceBdiiDict[site].get( 'GlueSiteDescription', '' ).strip()
      # Adding site data to the changes list
      addToChangeSet( ( siteSection, 'Coordinates', coor, newcoor ), changeSet )
      addToChangeSet( ( siteSection, 'Mail', mail, newmail ), changeSet )
      addToChangeSet( ( siteSection, 'Description', description, newdescription ), changeSet )
  
      ces = gConfig.getValue( cfgPath( siteSection, 'CE' ), [] )
      for ce in ces:
        ceSection = cfgPath( siteSection, 'CEs', ce )
        ceDict = {}
        result = gConfig.getOptionsDict( ceSection )
        if result['OK']:
          ceDict = result['Value']
        else:
          if ceBdiiDict[site]['CEs'].get( ce, None ):
            log.notice( "Adding new CE %s to site %s/%s" % (ce, siteName, site) )
        ceInfo = ceBdiiDict[site]['CEs'].get( ce, None )
        if ceInfo is None:
          ceType = ceDict.get( 'CEType', '')
          continue
  
        # Current CS CE info
        arch = ceDict.get( 'architecture', 'Unknown' )
        OS = ceDict.get( 'OS', 'Unknown' )
        si00 = ceDict.get( 'SI00', 'Unknown' )
        ceType = ceDict.get( 'CEType', 'Unknown' )
        ram = ceDict.get( 'HostRAM', 'Unknown' )
        submissionMode = ceDict.get( 'SubmissionMode', 'Unknown' )
  
        # Current BDII CE info
        newarch = ceBdiiDict[site]['CEs'][ce].get( 'GlueHostArchitecturePlatformType', '' ).strip()
        systemName = ceInfo.get( 'GlueHostOperatingSystemName', '' ).strip()
        systemVersion = ceInfo.get( 'GlueHostOperatingSystemVersion', '' ).strip()
        systemRelease = ceInfo.get( 'GlueHostOperatingSystemRelease', '' ).strip()
        newOS = ''
        if systemName and systemVersion and systemRelease:
          newOS = '_'.join( ( systemName, systemVersion, systemRelease ) )
        newsi00 = ceInfo.get( 'GlueHostBenchmarkSI00', '' ).strip()
        newCEType = 'Unknown'
        for queue in ceInfo['Queues']:
          queueDict = ceInfo['Queues'][queue]
          newCEType = queueDict.get( 'GlueCEImplementationName', '' ).strip()
          if newCEType:
            break
        if newCEType=='ARC-CE':
          newCEType = 'ARC'

        newSubmissionMode = None
        if newCEType in ['ARC','CREAM']:
          newSubmissionMode = "Direct" 
        newRAM = ceInfo.get( 'GlueHostMainMemoryRAMSize', '' ).strip()
  
        # Adding CE data to the change list
        addToChangeSet( ( ceSection, 'architecture', arch, newarch ), changeSet )
        addToChangeSet( ( ceSection, 'OS', OS, newOS ), changeSet )
        addToChangeSet( ( ceSection, 'SI00', si00, newsi00 ), changeSet )
        addToChangeSet( ( ceSection, 'CEType', ceType, newCEType ), changeSet )
        addToChangeSet( ( ceSection, 'HostRAM', ram, newRAM ), changeSet )
        if submissionMode == "Unknown" and newSubmissionMode:
          addToChangeSet( ( ceSection, 'SubmissionMode', submissionMode, newSubmissionMode ), changeSet )
  
        queues = ceInfo['Queues'].keys()
        for queue in queues:
          queueSection = cfgPath( ceSection, 'Queues', queue )
          queueDict = {}
          result = gConfig.getOptionsDict( queueSection )
          if result['OK']:
            queueDict = result['Value']
          else:
            log.notice( "Adding new queue %s to CE %s" % (queue, ce) )
          queueInfo = ceInfo['Queues'][queue]
          queueStatus = queueInfo['GlueCEStateStatus']
          if queueStatus.lower() != "production":
            continue
  
          # Current CS queue info
          maxCPUTime = queueDict.get( 'maxCPUTime', 'Unknown' )
          si00 = queueDict.get( 'SI00', 'Unknown' )
          maxTotalJobs = queueDict.get( 'MaxTotalJobs', 'Unknown' )
  
          # Current BDII queue info
          newMaxCPUTime = queueInfo.get( 'GlueCEPolicyMaxCPUTime', '' )
          newSI00 = ''
          caps = queueInfo['GlueCECapability']
          if type( caps ) == type( '' ):
            caps = [caps]
          for cap in caps:
            if 'CPUScalingReferenceSI00' in cap:
              newSI00 = cap.split( '=' )[-1]
  
          # Adding queue info to the CS
          addToChangeSet( ( queueSection, 'maxCPUTime', maxCPUTime, newMaxCPUTime ), changeSet )
          addToChangeSet( ( queueSection, 'SI00', si00, newSI00 ), changeSet )
          if maxTotalJobs == "Unknown":
            newTotalJobs =  min( 1000, int( int( queueInfo.get( 'GlueCEInfoTotalCPUs', 0 ) )/2 ) )
            newWaitingJobs =  max( 2, int( newTotalJobs * 0.1 ) )
            newTotalJobs = str( newTotalJobs )
            newWaitingJobs = str( newWaitingJobs )
            addToChangeSet( ( queueSection, 'MaxTotalJobs', '', newTotalJobs ), changeSet )
            addToChangeSet( ( queueSection, 'MaxWaitingJobs', '', newWaitingJobs ), changeSet )
            
          # Updating eligible VO list
          VOs = set()
          if queueDict.get( 'VO', '' ):
            VOs = set( [ q.strip() for q in queueDict.get( 'VO', '' ).split( ',' ) if q ] )
          if not vo in VOs:   
            VOs.add( vo )
            VOs = list( VOs )    
            newVOs = ','.join( VOs )
            addToChangeSet( ( queueSection, 'VO', '', newVOs ), changeSet ) 
    
  return S_OK( changeSet )  
Esempio n. 16
0
def getSiteUpdates( vo, bdiiInfo = None, log = None ):
  """ Get all the necessary updates for the already defined sites and CEs
  """  
  
  def addToChangeSet( entry, changeSet ):
    _section, _option, value, new_value = entry
    if new_value and new_value != value:
      changeSet.add( entry )

  if log is None:
    log = gLogger  
    
  ceBdiiDict = bdiiInfo
  if bdiiInfo is None:
    result = getBdiiCEInfo( vo )    
    if not result['OK']:
      return result
    ceBdiiDict = result['Value']

  changeSet = set()
  gConfig.forceRefresh()

  for site in ceBdiiDict:
    result = getDIRACSiteName( site )
    if not result['OK']:
      continue
    siteNames = result['Value']
    for siteName in siteNames:
      siteSection = cfgPath( '/Resources', 'Sites', siteName.split('.')[0], siteName )
      result = gConfig.getOptionsDict( siteSection )
      if not result['OK']:
        continue
      siteDict = result['Value']
      # Current CS values
      coor = siteDict.get( 'Coordinates', 'Unknown' )
      mail = siteDict.get( 'Mail', 'Unknown' ).replace( ' ','' )
      description = siteDict.get( 'Description', 'Unknown' )
  
      longitude = ceBdiiDict[site].get( 'GlueSiteLongitude', '' ).strip()
      latitude = ceBdiiDict[site].get( 'GlueSiteLatitude', '' ).strip()
  
      # Current BDII value
      newcoor = ''
      if longitude and latitude:
        newcoor = "%s:%s" % ( longitude, latitude )
      newmail = ceBdiiDict[site].get( 'GlueSiteSysAdminContact', '' ).replace( 'mailto:', '' ).strip()
      newdescription = ceBdiiDict[site].get( 'GlueSiteDescription', '' ).strip()
      # Adding site data to the changes list
      addToChangeSet( ( siteSection, 'Coordinates', coor, newcoor ), changeSet )
      addToChangeSet( ( siteSection, 'Mail', mail, newmail ), changeSet )
      addToChangeSet( ( siteSection, 'Description', description, newdescription ), changeSet )
  
      ces = gConfig.getValue( cfgPath( siteSection, 'CE' ), [] )
      for ce in ces:
        ceSection = cfgPath( siteSection, 'CEs', ce )
        ceDict = {}
        result = gConfig.getOptionsDict( ceSection )
        if result['OK']:
          ceDict = result['Value']
        else:
          if ceBdiiDict[site]['CEs'].get( ce, None ):
            log.notice( "Adding new CE %s to site %s/%s" % (ce, siteName, site) )
        ceInfo = ceBdiiDict[site]['CEs'].get( ce, None )
        if ceInfo is None:
          ceType = ceDict.get( 'CEType', '')
          continue
  
        # Current CS CE info
        arch = ceDict.get( 'architecture', 'Unknown' )
        OS = ceDict.get( 'OS', 'Unknown' )
        si00 = ceDict.get( 'SI00', 'Unknown' )
        ceType = ceDict.get( 'CEType', 'Unknown' )
        ram = ceDict.get( 'HostRAM', 'Unknown' )
        submissionMode = ceDict.get( 'SubmissionMode', 'Unknown' )
  
        # Current BDII CE info
        newarch = ceBdiiDict[site]['CEs'][ce].get( 'GlueHostArchitecturePlatformType', '' ).strip()
        systemName = ceInfo.get( 'GlueHostOperatingSystemName', '' ).strip()
        systemVersion = ceInfo.get( 'GlueHostOperatingSystemVersion', '' ).strip()
        systemRelease = ceInfo.get( 'GlueHostOperatingSystemRelease', '' ).strip()
        newOS = ''
        if systemName and systemVersion and systemRelease:
          newOS = '_'.join( ( systemName, systemVersion, systemRelease ) )
        newsi00 = ceInfo.get( 'GlueHostBenchmarkSI00', '' ).strip()
        newCEType = 'Unknown'
        for queue in ceInfo['Queues']:
          queueDict = ceInfo['Queues'][queue]
          newCEType = queueDict.get( 'GlueCEImplementationName', '' ).strip()
          if newCEType:
            break
        if newCEType=='ARC-CE':
          newCEType = 'ARC'
        if newCEType in ['ARC','CREAM']:
          newSubmissionMode = "Direct" 
        newRAM = ceInfo.get( 'GlueHostMainMemoryRAMSize', '' ).strip()
  
        # Adding CE data to the change list
        addToChangeSet( ( ceSection, 'architecture', arch, newarch ), changeSet )
        addToChangeSet( ( ceSection, 'OS', OS, newOS ), changeSet )
        addToChangeSet( ( ceSection, 'SI00', si00, newsi00 ), changeSet )
        addToChangeSet( ( ceSection, 'CEType', ceType, newCEType ), changeSet )
        addToChangeSet( ( ceSection, 'HostRAM', ram, newRAM ), changeSet )
        if submissionMode == "Unknown":
          addToChangeSet( ( ceSection, 'SubmissionMode', submissionMode, newSubmissionMode ), changeSet )
  
        queues = ceInfo['Queues'].keys()
        for queue in queues:
          queueSection = cfgPath( ceSection, 'Queues', queue )
          queueDict = {}
          result = gConfig.getOptionsDict( queueSection )
          if result['OK']:
            queueDict = result['Value']
          else:
            log.notice( "Adding new queue %s to CE %s" % (queue, ce) )
          queueInfo = ceInfo['Queues'][queue]
          queueStatus = queueInfo['GlueCEStateStatus']
          if queueStatus.lower() != "production":
            continue
  
          # Current CS queue info
          maxCPUTime = queueDict.get( 'maxCPUTime', 'Unknown' )
          si00 = queueDict.get( 'SI00', 'Unknown' )
          maxTotalJobs = queueDict.get( 'MaxTotalJobs', 'Unknown' )
  
          # Current BDII queue info
          newMaxCPUTime = queueInfo.get( 'GlueCEPolicyMaxCPUTime', '' )
          newSI00 = ''
          caps = queueInfo['GlueCECapability']
          if type( caps ) == type( '' ):
            caps = [caps]
          for cap in caps:
            if 'CPUScalingReferenceSI00' in cap:
              newSI00 = cap.split( '=' )[-1]
  
          # Adding queue info to the CS
          addToChangeSet( ( queueSection, 'maxCPUTime', maxCPUTime, newMaxCPUTime ), changeSet )
          addToChangeSet( ( queueSection, 'SI00', si00, newSI00 ), changeSet )
          if maxTotalJobs == "Unknown":
            newTotalJobs =  min( 1000, int( int( queueInfo.get( 'GlueCEInfoTotalCPUs', 0 ) )/2 ) )
            newWaitingJobs =  max( 2, int( newTotalJobs * 0.1 ) )
            newTotalJobs = str( newTotalJobs )
            newWaitingJobs = str( newWaitingJobs )
            addToChangeSet( ( queueSection, 'MaxTotalJobs', '', newTotalJobs ), changeSet )
            addToChangeSet( ( queueSection, 'MaxWaitingJobs', '', newWaitingJobs ), changeSet )
            
          # Updating eligible VO list
          VOs = set()
          if queueDict.get( 'VO', '' ):
            VOs = set( [ q.strip() for q in queueDict.get( 'VO', '' ).split( ',' ) if q ] )
          if not vo in VOs:   
            VOs.add( vo )
            VOs = list( VOs )    
            newVOs = ','.join( VOs )
            addToChangeSet( ( queueSection, 'VO', '', newVOs ), changeSet ) 
    
  return S_OK( changeSet )