Exemplo n.º 1
0
  def __changeSiteStatus( self, site, comment, statusType, status, printOutput = False ):
    """
      Change the RSS status of the given site
    """
    result = self.__checkSiteIsValid( site )
    if not result['OK']:
      return result

    wmsAdmin = RPCClient( 'WorkloadManagement/WMSAdministrator' )
    result = wmsAdmin.allowSite( site, comment )
    if not result['OK']:
      return result
    
    rsc = ResourceStatusClient()
    proxyInfo = getProxyInfo()
    if not proxyInfo[ 'OK' ]:
      return proxyInfo
    userName = proxyInfo[ 'Value' ][ 'username' ]   
    
    tomorrow = datetime.utcnow().replace( microsecond = 0 ) + timedelta( days = 1 )
  
    result = rsc.modifyStatusElement( 'Site', 'Status', 
                                      name = site, 
                                      statusType = statusType,
                                      status     = status,
                                      reason     = comment,  
                                      tokenOwner = userName, 
                                      tokenExpiration = tomorrow )

    return result
Exemplo n.º 2
0
    def __changeSiteStatus(self,
                           site,
                           comment,
                           statusType,
                           status,
                           printOutput=False):
        """
      Change the RSS status of the given site
    """
        result = self.__checkSiteIsValid(site)
        if not result['OK']:
            return result

        wmsAdmin = RPCClient('WorkloadManagement/WMSAdministrator')
        result = wmsAdmin.allowSite(site, comment)
        if not result['OK']:
            return result

        rsc = ResourceStatusClient()
        proxyInfo = getProxyInfo()
        if not proxyInfo['OK']:
            return proxyInfo
        userName = proxyInfo['Value']['username']

        tomorrow = datetime.utcnow().replace(microsecond=0) + timedelta(days=1)

        result = rsc.modifyStatusElement('Site',
                                         'Status',
                                         name=site,
                                         statusType=statusType,
                                         status=status,
                                         reason=comment,
                                         tokenOwner=userName,
                                         tokenExpiration=tomorrow)

        return result
Exemplo n.º 3
0
class ResourceStatus( object ):
  """
  ResourceStatus helper that connects to CS if RSS flag is not Active. It keeps
  the connection to the db / server as an object member, to avoid creating a new
  one massively.
  """

  __metaclass__ = DIRACSingleton

  def __init__( self ):
    """
    Constructor, initializes the rssClient.
    """

    self.log = gLogger.getSubLogger( self.__class__.__name__ )
    self.rssConfig = RssConfiguration()
    self.__opHelper = Operations()
    self.rssClient = None
    self.infoGetter = InfoGetter()

    # We can set CacheLifetime and CacheHistory from CS, so that we can tune them.
    cacheLifeTime = int( self.rssConfig.getConfigCache() )

    # RSSCache only affects the calls directed to RSS, if using the CS it is not
    # used.
    self.seCache = RSSCache( 'StorageElement', cacheLifeTime, self.__updateSECache )

  def getStorageElementStatus( self, elementName, statusType = None, default = None ):
    """
    Helper with dual access, tries to get information from the RSS for the given
    StorageElement, otherwise, it gets it from the CS.

    example:
      >>> getStorageElementStatus( 'CERN-USER', 'ReadAccess' )
          S_OK( { 'CERN-USER' : { 'ReadAccess': 'Active' } } )
      >>> getStorageElementStatus( 'CERN-USER', 'Write' )
          S_OK( { 'CERN-USER' : {'ReadAccess': 'Active', 'WriteAccess': 'Active',
                                 'CheckAccess': 'Banned', 'RemoveAccess': 'Banned'}} )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType' )
          S_ERROR( xyz.. )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType', 'Unknown' )
          S_OK( 'Unknown' )

    """

    if self.__getMode():
      # We do not apply defaults. If is not on the cache, S_ERROR is returned.
      return self.__getRSSStorageElementStatus( elementName, statusType )
    else:
      return self.__getCSStorageElementStatus( elementName, statusType, default )

  def setStorageElementStatus( self, elementName, statusType, status, reason = None,
                               tokenOwner = None ):

    """
    Helper with dual access, tries set information in RSS and in CS.

    example:
      >>> getStorageElementStatus( 'CERN-USER', 'ReadAccess' )
          S_OK( { 'ReadAccess': 'Active' } )
      >>> getStorageElementStatus( 'CERN-USER', 'Write' )
          S_OK( {'ReadAccess': 'Active', 'WriteAccess': 'Active', 'CheckAccess': 'Banned', 'RemoveAccess': 'Banned'} )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType' )
          S_ERROR( xyz.. )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType', 'Unknown' )
          S_OK( 'Unknown' )
    """

    if self.__getMode():
      return self.__setRSSStorageElementStatus( elementName, statusType, status, reason, tokenOwner )
    else:
      return self.__setCSStorageElementStatus( elementName, statusType, status )

################################################################################

  def __updateSECache( self ):
    """ Method used to update the StorageElementCache.

        It will try 5 times to contact the RSS before giving up
    """

    meta = { 'columns' : [ 'Name', 'StatusType', 'Status' ] }

    for ti in range( 5 ):
      rawCache = self.rssClient.selectStatusElement( 'Resource', 'Status',
                                                     elementType = 'StorageElement',
                                                     meta = meta )
      if rawCache['OK']:
        break
      self.log.warn( "Can't get SE status", rawCache['Message'] + "; trial %d" % ti )
      sleep( math.pow( ti, 2 ) )
      self.rssClient = ResourceStatusClient()

    if not rawCache[ 'OK' ]:
      return rawCache
    return S_OK( getCacheDictFromRawData( rawCache[ 'Value' ] ) )

################################################################################

  def __getRSSStorageElementStatus( self, elementName, statusType ):
    """
    Gets from the cache or the RSS the StorageElements status. The cache is a
    copy of the DB table. If it is not on the cache, most likely is not going
    to be on the DB.

    There is one exception: item just added to the CS, e.g. new StorageElement.
    The period between it is added to the DB and the changes are propagated
    to the cache will be inconsisten, but not dangerous. Just wait <cacheLifeTime>
    minutes.
    """

    cacheMatch = self.seCache.match( elementName, statusType )

    self.log.debug( '__getRSSStorageElementStatus' )
    self.log.debug( cacheMatch )

    return cacheMatch

  def __getCSStorageElementStatus( self, elementName, statusType, default ):
    """
    Gets from the CS the StorageElements status
    """

    cs_path = "/Resources/StorageElements"

    if not isinstance( elementName, list ):
      elementName = [ elementName ]

    statuses = self.rssConfig.getConfigStatusType( 'StorageElement' )

    result = {}
    for element in elementName:

      if statusType is not None:
        # Added Active by default
        res = gConfig.getValue( "%s/%s/%s" % ( cs_path, element, statusType ), 'Active' )
        result[element] = {statusType: res}

      else:
        res = gConfig.getOptionsDict( "%s/%s" % ( cs_path, element ) )
        if res[ 'OK' ] and res[ 'Value' ]:
          elementStatuses = {}
          for elementStatusType, value in res[ 'Value' ].items():
            if elementStatusType in statuses:
              elementStatuses[ elementStatusType ] = value

          # If there is no status defined in the CS, we add by default Read and
          # Write as Active.
          if elementStatuses == {}:
            elementStatuses = { 'ReadAccess' : 'Active', 'WriteAccess' : 'Active' }

          result[ element ] = elementStatuses

    if result:
      return S_OK( result )

    if default is not None:

      # sec check
      if statusType is None:
        statusType = 'none'

      defList = [ [ el, statusType, default ] for el in elementName ]
      return S_OK( getDictFromList( defList ) )

    _msg = "StorageElement '%s', with statusType '%s' is unknown for CS."
    return S_ERROR( _msg % ( elementName, statusType ) )

  def __setRSSStorageElementStatus( self, elementName, statusType, status, reason, tokenOwner ):
    """
    Sets on the RSS the StorageElements status
    """

    expiration = datetime.datetime.utcnow() + datetime.timedelta( days = 1 )

    self.seCache.acquireLock()
    try:
      res = self.rssClient.modifyStatusElement( 'Resource', 'Status', name = elementName,
                                                statusType = statusType, status = status,
                                                reason = reason, tokenOwner = tokenOwner,
                                                tokenExpiration = expiration )
      if res[ 'OK' ]:
        self.seCache.refreshCache()

      if not res[ 'OK' ]:
        _msg = 'Error updating StorageElement (%s,%s,%s)' % ( elementName, statusType, status )
        gLogger.warn( 'RSS: %s' % _msg )

      return res

    finally:
      # Release lock, no matter what.
      self.seCache.releaseLock()

  def __setCSStorageElementStatus( self, elementName, statusType, status ):
    """
    Sets on the CS the StorageElements status
    """

    statuses = self.rssConfig.getConfigStatusType( 'StorageElement' )
    if not statusType in statuses:
      gLogger.error( "%s is not a valid statusType" % statusType )
      return S_ERROR( "%s is not a valid statusType: %s" % ( statusType, statuses ) )

    csAPI = CSAPI()

    cs_path = "/Resources/StorageElements"

    csAPI.setOption( "%s/%s/%s" % ( cs_path, elementName, statusType ), status )

    res = csAPI.commitChanges()
    if not res[ 'OK' ]:
      gLogger.warn( 'CS: %s' % res[ 'Message' ] )

    return res

  def __getMode( self ):
    """
      Get's flag defined ( or not ) on the RSSConfiguration. If defined as 1,
      we use RSS, if not, we use CS.
    """

    res = self.rssConfig.getConfigState()

    if res == 'Active':

      if self.rssClient is None:
        self.rssClient = ResourceStatusClient()
      return True

    self.rssClient = None
    return False
  
  def isStorageElementAlwaysBanned( self, seName, statusType ):
    """ Checks if the AlwaysBanned policy is applied to the SE
        given as parameter

        :param seName : string, name of the SE
        :param statusType : ReadAcces, WriteAccess, RemoveAccess, CheckAccess

        :returns S_OK(True/False)
    """

    res = self.infoGetter.getPoliciesThatApply( {'name' : seName, 'statusType' : statusType} )
    if not res['OK']:
      self.log.error( "isStorageElementAlwaysBanned: unable to get the information", res['Message'] )
      return res

    isAlwaysBanned = 'AlwaysBanned' in [policy['type'] for policy in res['Value']]

    return S_OK( isAlwaysBanned )
Exemplo n.º 4
0
def setToken(user):
  '''
    Function that gets the user token, sets the validity for it. Gets the elements
    in the database for a given name and statusType(s). Then updates the status
    of all them adding a reason and the token.
  '''

  rssClient = ResourceStatusClient()

  # This is a little bit of a nonsense, and certainly needs to be improved.
  # To modify a list of elements, we have to do it one by one. However, the
  # modify method does not discover the StatusTypes ( which in this script is
  # an optional parameter ). So, we get them from the DB and iterate over them.
  elements = rssClient.selectStatusElement(switchDict['element'], 'Status',
                                           name=switchDict['name'],
                                           statusType=switchDict['statusType'],
                                           meta={'columns': ['StatusType', 'TokenOwner']})

  if not elements['OK']:
    return elements
  elements = elements['Value']

  # If there list is empty they do not exist on the DB !
  if not elements:
    subLogger.warn('Nothing found for %s, %s, %s' % (switchDict['element'],
                                                     switchDict['name'],
                                                     switchDict['statusType']))
    return S_OK()

  # If we want to release the token
  if switchDict['releaseToken']:
    tokenExpiration = datetime.max
    newTokenOwner = 'rs_svc'
  else:
    tokenExpiration = datetime.utcnow().replace(microsecond=0) + timedelta(days=int(switchDict['days']))
    newTokenOwner = user

  subLogger.always('New token: %s --- until %s' % (newTokenOwner, tokenExpiration))

  for statusType, tokenOwner in elements:

    # If a user different than the one issuing the command and RSS
    if tokenOwner != user and tokenOwner != 'rs_svc':
      subLogger.info('%s(%s) belongs to the user: %s' % (switchDict['name'], statusType, tokenOwner))

    # does the job
    result = rssClient.modifyStatusElement(switchDict['element'], 'Status',
                                           name=switchDict['name'],
                                           statusType=statusType,
                                           reason=switchDict['reason'],
                                           tokenOwner=newTokenOwner,
                                           tokenExpiration=tokenExpiration)
    if not result['OK']:
      return result

    if tokenOwner == newTokenOwner:
      msg = '(extended)'
    elif newTokenOwner == 'rs_svc':
      msg = '(released)'
    else:
      msg = '(aquired from %s)' % tokenOwner

    subLogger.info('%s:%s %s' % (switchDict['name'], statusType, msg))
  return S_OK()
Exemplo n.º 5
0
def setToken( user ):
  '''
    Function that gets the user token, sets the validity for it. Gets the elements
    in the database for a given name and statusType(s). Then updates the status
    of all them adding a reason and the token.
  '''

  rssClient = ResourceStatusClient()

  # This is a little bit of a nonsense, and certainly needs to be improved.
  # To modify a list of elements, we have to do it one by one. However, the
  # modify method does not discover the StatusTypes ( which in this script is
  # an optional parameter ). So, we get them from the DB and iterate over them.
  elements = rssClient.selectStatusElement( switchDict[ 'element' ], 'Status',
                                            name       = switchDict[ 'name' ],
                                            statusType = switchDict[ 'statusType' ],
                                            meta = { 'columns' : [ 'StatusType', 'TokenOwner' ] } )

  if not elements[ 'OK']:
    return elements
  elements = elements[ 'Value' ]

  # If there list is empty they do not exist on the DB !
  if not elements:
    subLogger.warn( 'Nothing found for %s, %s, %s' % ( switchDict[ 'element' ],
                                                       switchDict[ 'name' ],
                                                       switchDict[ 'statusType' ] ) )
    return S_OK()

  # If we want to release the token
  if switchDict[ 'releaseToken' ] != False:
    tokenExpiration = datetime.max
    newTokenOwner   = 'rs_svc'
  else:
    tokenExpiration = datetime.utcnow().replace( microsecond = 0 ) + timedelta( days = 1 )
    newTokenOwner   = user

  subLogger.info( 'New token : %s until %s' % ( newTokenOwner, tokenExpiration ) )

  for statusType, tokenOwner in elements:

    # If a user different than the one issuing the command and RSS
    if tokenOwner != user and tokenOwner != 'rs_svc':
      subLogger.info( '%s(%s) belongs to the user: %s' % ( switchDict[ 'name' ], statusType, tokenOwner ) )

    # does the job
    result = rssClient.modifyStatusElement( switchDict[ 'element' ], 'Status',
                                            name       = switchDict[ 'name' ],
                                            statusType = statusType,
                                            reason     = switchDict[ 'reason'],
                                            tokenOwner = newTokenOwner,
                                            tokenExpiration = tokenExpiration )
    if not result[ 'OK' ]:
      return result

    if tokenOwner == newTokenOwner:
      msg = '(extended)'
    elif newTokenOwner == 'rs_svc':
      msg = '(released)'
    else:
      msg = '(aquired from %s)' % tokenOwner

    subLogger.info( '%s:%s %s' % ( switchDict[ 'name' ], statusType, msg ) )
  return S_OK()
Exemplo n.º 6
0
def setToken(user):
    """
    Function that gets the user token, sets the validity for it. Gets the elements
    in the database for a given name and statusType(s). Then updates the status
    of all them adding a reason and the token.
    """

    rssClient = ResourceStatusClient()

    # This is a little bit of a nonsense, and certainly needs to be improved.
    # To modify a list of elements, we have to do it one by one. However, the
    # modify method does not discover the StatusTypes ( which in this script is
    # an optional parameter ). So, we get them from the DB and iterate over them.
    elements = rssClient.selectStatusElement(
        switchDict["element"],
        "Status",
        name=switchDict["name"],
        statusType=switchDict["statusType"],
        vO=switchDict["VO"],
        meta={"columns": ["StatusType", "TokenOwner"]},
    )

    if not elements["OK"]:
        return elements
    elements = elements["Value"]

    # If there list is empty they do not exist on the DB !
    if not elements:
        subLogger.warn("Nothing found for %s, %s, %s %s" %
                       (switchDict["element"], switchDict["name"],
                        switchDict["VO"], switchDict["statusType"]))
        return S_OK()

    # If we want to release the token
    if switchDict["releaseToken"]:
        tokenExpiration = datetime.max
        newTokenOwner = "rs_svc"
    else:
        tokenExpiration = datetime.utcnow().replace(microsecond=0) + timedelta(
            days=int(switchDict["days"]))
        newTokenOwner = user

    subLogger.always("New token: %s --- until %s" %
                     (newTokenOwner, tokenExpiration))

    for statusType, tokenOwner in elements:

        # If a user different than the one issuing the command and RSS
        if tokenOwner != user and tokenOwner != "rs_svc":
            subLogger.info("%s(%s) belongs to the user: %s" %
                           (switchDict["name"], statusType, tokenOwner))

        # does the job
        result = rssClient.modifyStatusElement(
            switchDict["element"],
            "Status",
            name=switchDict["name"],
            statusType=statusType,
            reason=switchDict["reason"],
            tokenOwner=newTokenOwner,
            vO=switchDict["VO"],
            tokenExpiration=tokenExpiration,
        )
        if not result["OK"]:
            return result

        if tokenOwner == newTokenOwner:
            msg = "(extended)"
        elif newTokenOwner == "rs_svc":
            msg = "(released)"
        else:
            msg = "(aquired from %s)" % tokenOwner

        subLogger.info("name:%s, VO:%s statusType:%s %s" %
                       (switchDict["name"], switchDict["VO"], statusType, msg))
    return S_OK()
Exemplo n.º 7
0
class SiteStatus(object):
    """
  RSS helper to interact with the 'Site' family on the DB. It provides the most
  demanded functions and a cache to avoid hitting the server too often.

  It provides four methods to interact with the site statuses:
  * getSiteStatuses
  * isUsableSite
  * getUsableSites
  * getSites
  """

    __metaclass__ = DIRACSingleton

    def __init__(self):
        """
    Constructor, initializes the rssClient.
    """

        self.log = gLogger.getSubLogger(self.__class__.__name__)
        self.rssConfig = RssConfiguration()
        self.__opHelper = Operations()
        self.rssFlag = ResourceStatus().rssFlag
        self.rsClient = ResourceStatusClient()

        cacheLifeTime = int(self.rssConfig.getConfigCache())

        # RSSCache only affects the calls directed to RSS, if using the CS it is not used.
        self.rssCache = RSSCache(cacheLifeTime, self.__updateRssCache)

    def __updateRssCache(self):
        """ Method used to update the rssCache.

        It will try 5 times to contact the RSS before giving up
    """

        meta = {'columns': ['Name', 'Status']}

        for ti in xrange(5):
            rawCache = self.rsClient.selectStatusElement('Site',
                                                         'Status',
                                                         meta=meta)
            if rawCache['OK']:
                break
            self.log.warn("Can't get resource's status",
                          rawCache['Message'] + "; trial %d" % ti)
            sleep(math.pow(ti, 2))
            self.rsClient = ResourceStatusClient()

        if not rawCache['OK']:
            return rawCache
        return S_OK(getCacheDictFromRawData(rawCache['Value']))

    def getSiteStatuses(self, siteNames=None):
        """
    Method that queries the database for status of the sites in a given list.
    A single string site name may also be provides as "siteNames"
    If the input is None, it is interpreted as * ( all ).

    If match is positive, the output looks like:
    {
     'test1.test1.org': 'Active',
     'test2.test2.org': 'Banned',
    }

    examples
      >>> siteStatus.getSiteStatuses( ['test1.test1.uk', 'test2.test2.net', 'test3.test3.org'] )
          S_OK( { 'test1.test1.org': 'Active', 'test2.test2.net': 'Banned', 'test3.test3.org': 'Active' }  )
      >>> siteStatus.getSiteStatuses( 'NotExists')
          S_ERROR( ... ))
      >>> siteStatus.getSiteStatuses( None )
          S_OK( { 'test1.test1.org': 'Active',
                  'test2.test2.net': 'Banned', },
                  ...
                }
              )

    :Parameters:
      **siteNames** - `list` or `str`
        name(s) of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

        if self.rssFlag:
            return self.__getRSSSiteStatus(siteNames)
        else:
            siteStatusDict = {}
            wmsAdmin = RPCClient('WorkloadManagement/WMSAdministrator')
            if siteNames:
                if isinstance(siteNames, basestring):
                    siteNames = [siteNames]
                for siteName in siteNames:
                    result = wmsAdmin.getSiteMaskStatus(siteName)
                    if not result['OK']:
                        return result
                    else:
                        siteStatusDict[siteName] = result['Value']
            else:
                result = wmsAdmin.getSiteMaskStatus()
                if not result['OK']:
                    return result
                else:
                    siteStatusDict = result['Value']

            return S_OK(siteStatusDict)

    def __getRSSSiteStatus(self, siteName=None):
        """ Gets from the cache or the RSS the Sites status. The cache is a
        copy of the DB table. If it is not on the cache, most likely is not going
        to be on the DB.

        There is one exception: item just added to the CS, e.g. new Element.
        The period between it is added to the DB and the changes are propagated
        to the cache will be inconsistent, but not dangerous. Just wait <cacheLifeTime>
        minutes.

    :param siteName: name of the site
    :type siteName: str

    :return: dict
    """

        cacheMatch = self.rssCache.match(siteName, '', '')

        self.log.debug('__getRSSSiteStatus')
        self.log.debug(cacheMatch)

        return cacheMatch

    def getUsableSites(self, siteNames=None):
        """
    Returns all sites that are usable if their
    statusType is either Active or Degraded; in a list.

    examples
      >>> siteStatus.getUsableSites( ['test1.test1.uk', 'test2.test2.net', 'test3.test3.org'] )
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getUsableSites( None )
          S_OK( ['test1.test1.uk', 'test3.test3.org', 'test4.test4.org', 'test5.test5.org', ...] )
      >>> siteStatus.getUsableSites( 'NotExists' )
          S_ERROR( ... )

    :Parameters:
      **siteNames** - `List` or `str`
        name(s) of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

        siteStatusDictRes = self.getSiteStatuses(siteNames)
        if not siteStatusDictRes['OK']:
            return siteStatusDictRes
        siteStatusList = [
            x[0] for x in siteStatusDictRes['Value'].iteritems()
            if x[1] in ['Active', 'Degraded']
        ]

        return S_OK(siteStatusList)

    def getSites(self, siteState='Active'):
        """
    By default, it gets the currently active site list

    examples
      >>> siteStatus.getSites()
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getSites( 'Active' )
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getSites( 'Banned' )
          S_OK( ['test0.test0.uk', ... ] )
      >>> siteStatus.getSites( 'All' )
          S_OK( ['test1.test1.uk', 'test3.test3.org', 'test4.test4.org', 'test5.test5.org'...] )
      >>> siteStatus.getSites( None )
          S_ERROR( ... )

    :Parameters:
      **siteState** - `String`
        state of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

        if not siteState:
            return S_ERROR(DErrno.ERESUNK, 'siteState parameter is empty')

        siteStatusDictRes = self.getSiteStatuses()
        if not siteStatusDictRes['OK']:
            return siteStatusDictRes

        if siteState.capitalize() == 'All':
            # if no siteState is set return everything
            siteList = list(siteStatusDictRes['Value'])

        else:
            # fix case sensitive string
            siteState = siteState.capitalize()
            allowedStateList = [
                'Active', 'Banned', 'Degraded', 'Probing', 'Error', 'Unknown'
            ]
            if siteState not in allowedStateList:
                return S_ERROR(errno.EINVAL,
                               'Not a valid status, parameter rejected')

            siteList = [
                x[0] for x in siteStatusDictRes['Value'].iteritems()
                if x[1] == siteState
            ]

        return S_OK(siteList)

    def setSiteStatus(self, site, status, comment='No comment'):
        """
    Set the status of a site in the 'SiteStatus' table of RSS

    examples
      >>> siteStatus.banSite( 'site1.test.test' )
          S_OK()
      >>> siteStatus.banSite( None )
          S_ERROR( ... )

    :Parameters:
      **site** - `String`
        the site that is going to be banned
      **comment** - `String`
        reason for banning

    :return: S_OK() || S_ERROR()
    """

        if not status:
            return S_ERROR(DErrno.ERESUNK, 'status parameter is empty')

        # fix case sensitive string
        status = status.capitalize()
        allowedStateList = [
            'Active', 'Banned', 'Degraded', 'Probing', 'Error', 'Unknown'
        ]

        if status not in allowedStateList:
            return S_ERROR(errno.EINVAL,
                           'Not a valid status, parameter rejected')

        if self.rssFlag:
            result = getProxyInfo()
            if result['OK']:
                tokenOwner = result['Value']['username']
            else:
                return S_ERROR("Unable to get user proxy info %s " %
                               result['Message'])

            tokenExpiration = datetime.utcnow() + timedelta(days=1)

            self.rssCache.acquireLock()
            try:
                result = self.rsClient.modifyStatusElement(
                    'Site',
                    'Status',
                    status=status,
                    name=site,
                    tokenExpiration=tokenExpiration,
                    reason=comment,
                    tokenOwner=tokenOwner)
                if result['OK']:
                    self.rssCache.refreshCache()
                else:
                    _msg = 'Error updating status of site %s to %s' % (site,
                                                                       status)
                    gLogger.warn('RSS: %s' % _msg)

            # Release lock, no matter what.
            finally:
                self.rssCache.releaseLock()

        else:
            if status in ['Active', 'Degraded']:
                result = RPCClient(
                    'WorkloadManagement/WMSAdministrator').allowSite()
            else:
                result = RPCClient(
                    'WorkloadManagement/WMSAdministrator').banSite()

        return result
Exemplo n.º 8
0
class SiteStatus(object):
  """
  RSS helper to interact with the 'Site' family on the DB. It provides the most
  demanded functions and a cache to avoid hitting the server too often.

  It provides four methods to interact with the site statuses:
  * getSiteStatuses
  * isUsableSite
  * getUsableSites
  * getSites
  """

  __metaclass__ = DIRACSingleton

  def __init__(self):
    """
    Constructor, initializes the rssClient.
    """

    self.log = gLogger.getSubLogger(self.__class__.__name__)
    self.rssConfig = RssConfiguration()
    self.__opHelper = Operations()
    self.rssFlag = ResourceStatus().rssFlag
    self.rsClient = ResourceStatusClient()

    # We can set CacheLifetime and CacheHistory from CS, so that we can tune them.
    cacheLifeTime = int(self.rssConfig.getConfigCache())

    # RSSCache only affects the calls directed to RSS, if using the CS it is not used.
    self.rssCache = RSSCache(cacheLifeTime, self.__updateRssCache)

  def __updateRssCache(self):
    """ Method used to update the rssCache.

        It will try 5 times to contact the RSS before giving up
    """

    meta = {'columns': ['Name', 'Status']}

    for ti in xrange(5):
      rawCache = self.rsClient.selectStatusElement('Site', 'Status', meta=meta)
      if rawCache['OK']:
        break
      self.log.warn("Can't get resource's status", rawCache['Message'] + "; trial %d" % ti)
      sleep(math.pow(ti, 2))
      self.rsClient = ResourceStatusClient()

    if not rawCache['OK']:
      return rawCache
    return S_OK(getCacheDictFromRawData(rawCache['Value']))

  def getSiteStatuses(self, siteNames=None):
    """
    Method that queries the database for status of the sites in a given list.
    A single string site name may also be provides as "siteNames"
    If the input is None, it is interpreted as * ( all ).

    If match is positive, the output looks like:
    {
     'test1.test1.org': 'Active',
     'test2.test2.org': 'Banned',
    }

    examples
      >>> siteStatus.getSiteStatuses( ['test1.test1.uk', 'test2.test2.net', 'test3.test3.org'] )
          S_OK( { 'test1.test1.org': 'Active', 'test2.test2.net': 'Banned', 'test3.test3.org': 'Active' }  )
      >>> siteStatus.getSiteStatuses( 'NotExists')
          S_ERROR( ... ))
      >>> siteStatus.getSiteStatuses( None )
          S_OK( { 'test1.test1.org': 'Active',
                  'test2.test2.net': 'Banned', },
                  ...
                }
              )

    :Parameters:
      **siteNames** - `list` or `str`
        name(s) of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

    if self.rssFlag:
      return self.__getRSSSiteStatus(siteNames)
    else:
      siteStatusDict = {}
      wmsAdmin = RPCClient('WorkloadManagement/WMSAdministrator')
      if siteNames:
        if isinstance(siteNames, basestring):
          siteNames = [siteNames]
        for siteName in siteNames:
          result = wmsAdmin.getSiteMaskStatus(siteName)
          if not result['OK']:
            return result
          else:
            siteStatusDict[siteName] = result['Value']
      else:
        result = wmsAdmin.getSiteMaskStatus()
        if not result['OK']:
          return result
        else:
          siteStatusDict = result['Value']

      return S_OK(siteStatusDict)

  def __getRSSSiteStatus(self, siteName=None):
    """ Gets from the cache or the RSS the Sites status. The cache is a
        copy of the DB table. If it is not on the cache, most likely is not going
        to be on the DB.

        There is one exception: item just added to the CS, e.g. new Element.
        The period between it is added to the DB and the changes are propagated
        to the cache will be inconsistent, but not dangerous. Just wait <cacheLifeTime>
        minutes.

    :param siteName: name of the site
    :type siteName: str

    :return: dict
    """

    cacheMatch = self.rssCache.match(siteName, '', '')

    self.log.debug('__getRSSSiteStatus')
    self.log.debug(cacheMatch)

    return cacheMatch

  def getUsableSites(self, siteNames=None):
    """
    Returns all sites that are usable if their
    statusType is either Active or Degraded; in a list.

    examples
      >>> siteStatus.getUsableSites( ['test1.test1.uk', 'test2.test2.net', 'test3.test3.org'] )
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getUsableSites( None )
          S_OK( ['test1.test1.uk', 'test3.test3.org', 'test4.test4.org', 'test5.test5.org', ...] )
      >>> siteStatus.getUsableSites( 'NotExists' )
          S_ERROR( ... )

    :Parameters:
      **siteNames** - `List` or `str`
        name(s) of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

    siteStatusDictRes = self.getSiteStatuses(siteNames)
    if not siteStatusDictRes['OK']:
      return siteStatusDictRes
    siteStatusList = [x[0] for x in siteStatusDictRes['Value'].iteritems() if x[1] in ['Active', 'Degraded']]

    return S_OK(siteStatusList)

  def getSites(self, siteState='Active'):
    """
    By default, it gets the currently active site list

    examples
      >>> siteStatus.getSites()
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getSites( 'Active' )
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getSites( 'Banned' )
          S_OK( ['test0.test0.uk', ... ] )
      >>> siteStatus.getSites( 'All' )
          S_OK( ['test1.test1.uk', 'test3.test3.org', 'test4.test4.org', 'test5.test5.org'...] )
      >>> siteStatus.getSites( None )
          S_ERROR( ... )

    :Parameters:
      **siteState** - `String`
        state of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

    if not siteState:
      return S_ERROR(DErrno.ERESUNK, 'siteState parameter is empty')

    siteStatusDictRes = self.getSiteStatuses()
    if not siteStatusDictRes['OK']:
      return siteStatusDictRes

    if siteState.capitalize() == 'All':
      # if no siteState is set return everything
      siteList = list(siteStatusDictRes['Value'])

    else:
      # fix case sensitive string
      siteState = siteState.capitalize()
      allowedStateList = ['Active', 'Banned', 'Degraded', 'Probing', 'Error', 'Unknown']
      if siteState not in allowedStateList:
        return S_ERROR(errno.EINVAL, 'Not a valid status, parameter rejected')

      siteList = [x[0] for x in siteStatusDictRes['Value'].iteritems() if x[1] == siteState]

    return S_OK(siteList)

  def setSiteStatus(self, site, status, comment='No comment'):
    """
    Set the status of a site in the 'SiteStatus' table of RSS

    examples
      >>> siteStatus.banSite( 'site1.test.test' )
          S_OK()
      >>> siteStatus.banSite( None )
          S_ERROR( ... )

    :Parameters:
      **site** - `String`
        the site that is going to be banned
      **comment** - `String`
        reason for banning

    :return: S_OK() || S_ERROR()
    """

    if not status:
      return S_ERROR(DErrno.ERESUNK, 'status parameter is empty')

    # fix case sensitive string
    status = status.capitalize()
    allowedStateList = ['Active', 'Banned', 'Degraded', 'Probing', 'Error', 'Unknown']

    if status not in allowedStateList:
      return S_ERROR(errno.EINVAL, 'Not a valid status, parameter rejected')

    if self.rssFlag:
      result = getProxyInfo()
      if result['OK']:
        tokenOwner = result['Value']['username']
      else:
        return S_ERROR("Unable to get user proxy info %s " % result['Message'])

      tokenExpiration = datetime.utcnow() + timedelta(days=1)

      self.rssCache.acquireLock()
      try:
        result = self.rsClient.modifyStatusElement('Site', 'Status', status=status, name=site,
                                                   tokenExpiration=tokenExpiration, reason=comment,
                                                   tokenOwner=tokenOwner)
        if result['OK']:
          self.rssCache.refreshCache()
        else:
          _msg = 'Error updating status of site %s to %s' % (site, status)
          gLogger.warn('RSS: %s' % _msg)

      # Release lock, no matter what.
      finally:
        self.rssCache.releaseLock()

    else:
      if status in ['Active', 'Degraded']:
        result = RPCClient('WorkloadManagement/WMSAdministrator').allowSite()
      else:
        result = RPCClient('WorkloadManagement/WMSAdministrator').banSite()

    return result
Exemplo n.º 9
0
def setToken(user):
    """
    Function that gets the user token, sets the validity for it. Gets the elements
    in the database for a given name and statusType(s). Then updates the status
    of all them adding a reason and the token.
  """

    rssClient = ResourceStatusClient()

    # This is a little bit of a nonsense, and certainly needs to be improved.
    # To modify a list of elements, we have to do it one by one. However, the
    # modify method does not discover the StatusTypes ( which in this script is
    # an optional parameter ). So, we get them from the DB and iterate over them.
    elements = rssClient.selectStatusElement(
        switchDict["element"],
        "Status",
        name=switchDict["name"],
        statusType=switchDict["statusType"],
        meta={"columns": ["StatusType", "TokenOwner"]},
    )

    if not elements["OK"]:
        return elements
    elements = elements["Value"]

    # If there list is empty they do not exist on the DB !
    if not elements:
        subLogger.warn(
            "Nothing found for %s, %s, %s" % (switchDict["element"], switchDict["name"], switchDict["statusType"])
        )
        return S_OK()

    # If we want to release the token
    if switchDict["releaseToken"] != False:
        tokenExpiration = datetime.max
        newTokenOwner = "rs_svc"
    else:
        tokenExpiration = datetime.utcnow().replace(microsecond=0) + timedelta(days=1)
        newTokenOwner = user

    subLogger.info("New token : %s until %s" % (newTokenOwner, tokenExpiration))

    for statusType, tokenOwner in elements:

        # If a user different than the one issuing the command and RSS
        if tokenOwner != user and tokenOwner != "rs_svc":
            subLogger.info("%s(%s) belongs to the user: %s" % (switchDict["name"], statusType, tokenOwner))

        # does the job
        result = rssClient.modifyStatusElement(
            switchDict["element"],
            "Status",
            name=switchDict["name"],
            statusType=statusType,
            reason=switchDict["reason"],
            tokenOwner=newTokenOwner,
            tokenExpiration=tokenExpiration,
        )
        if not result["OK"]:
            return result

        if tokenOwner == newTokenOwner:
            msg = "(extended)"
        elif newTokenOwner == "rs_svc":
            msg = "(released)"
        else:
            msg = "(aquired from %s)" % tokenOwner

        subLogger.info("%s:%s %s" % (switchDict["name"], statusType, msg))
    return S_OK()
Exemplo n.º 10
0
class SiteStatus(object):
    """
  RSS helper to interact with the 'Site' family on the DB. It provides the most
  demanded functions and a cache to avoid hitting the server too often.

  It provides four methods to interact with the site statuses:
  * getSiteStatuses
  * isUsableSite
  * getUsableSites
  * getSites
  """

    __metaclass__ = DIRACSingleton

    def __init__(self):
        """
    Constructor, initializes the rssClient.
    """

        self.log = gLogger.getSubLogger(self.__class__.__name__)
        self.rssConfig = RssConfiguration()
        self.__opHelper = Operations()
        self.rssFlag = ResourceStatus().rssFlag
        self.rsClient = ResourceStatusClient()

    def getSiteStatuses(self, siteNamesList=None):
        """
    Method that queries the database for status of the sites in a given list.
    If the input is None, it is interpreted as * ( all ).

    If match is positive, the output looks like:
    {
     'test1.test1.org': 'Active',
     'test2.test2.org': 'Banned',
    }

    examples
      >>> siteStatus.getSiteStatuses( ['test1.test1.uk', 'test2.test2.net', 'test3.test3.org'] )
          S_OK( { 'test1.test1.org': 'Active', 'test2.test2.net': 'Banned', 'test3.test3.org': 'Active' }  )
      >>> siteStatus.getSiteStatuses( 'NotExists')
          S_ERROR( ... ))
      >>> siteStatus.getSiteStatuses( None )
          S_OK( { 'test1.test1.org': 'Active',
                  'test2.test2.net': 'Banned', },
                  ...
                }
              )

    :Parameters:
      **siteNamesList** - `list`
        name(s) of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

        if not siteNamesList:

            if self.rssFlag:
                siteStatusDict = self.rsClient.selectStatusElement(
                    'Site', 'Status', meta={'columns': ['Name', 'Status']})
            else:
                siteStatusDict = RPCClient(
                    'WorkloadManagement/WMSAdministrator').getSiteMaskStatus()

            if not siteStatusDict['OK']:
                return siteStatusDict
            else:
                siteStatusDict = siteStatusDict['Value']

            return S_OK(dict(siteStatusDict))

        siteStatusDict = {}

        for siteName in siteNamesList:

            if self.rssFlag:
                result = self.rsClient.selectStatusElement(
                    'Site',
                    'Status',
                    name=siteName,
                    meta={'columns': ['Status']})
            else:
                result = RPCClient('WorkloadManagement/WMSAdministrator'
                                   ).getSiteMaskStatus(siteName)

            if not result['OK']:
                return result
            elif not result['Value']:
                #if one of the listed elements does not exist continue
                continue
            else:
                if self.rssFlag:
                    siteStatusDict[siteName] = result['Value'][0][0]
                else:
                    siteStatusDict[siteName] = result['Value']

        return S_OK(siteStatusDict)

    def isUsableSite(self, siteName):
        """
    Similar method to getSiteStatus. The difference is the output.
    Given a site name, returns a bool if the site is usable:
    status is Active or Degraded outputs True
    anything else outputs False

    examples
      >>> siteStatus.isUsableSite( 'test1.test1.org' )
          True
      >>> siteStatus.isUsableSite( 'test2.test2.org' )
          False # May be banned
      >>> siteStatus.isUsableSite( None )
          False
      >>> siteStatus.isUsableSite( 'NotExists' )
          False

    :Parameters:
      **siteName** - `string`
        name of the site to be matched

    :return: S_OK() || S_ERROR()
    """

        if self.rssFlag:
            siteStatus = self.rsClient.selectStatusElement(
                'Site', 'Status', name=siteName, meta={'columns': ['Status']})
        else:
            siteStatus = RPCClient('WorkloadManagement/WMSAdministrator'
                                   ).getSiteMaskStatus(siteName)

        if not siteStatus['OK']:
            return siteStatus

        if not siteStatus['Value']:
            # Site does not exist, so it is not usable
            return S_OK(False)

        if self.rssFlag:
            status = siteStatus['Value'][0][0]
        else:
            status = siteStatus['Value']

        if status in ('Active', 'Degraded'):
            return S_OK(True)
        else:
            return S_OK(False)

    def getUsableSites(self, siteNamesList=None):
        """
    Returns all sites that are usable if their
    statusType is either Active or Degraded; in a list.

    examples
      >>> siteStatus.getUsableSites( ['test1.test1.uk', 'test2.test2.net', 'test3.test3.org'] )
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getUsableSites( None )
          S_OK( ['test1.test1.uk', 'test3.test3.org', 'test4.test4.org', 'test5.test5.org', ...] )
      >>> siteStatus.getUsableSites( 'NotExists' )
          S_ERROR( ... )

    :Parameters:
      **siteNamesList** - `List`
        name(s) of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

        if not siteNamesList:
            if self.rssFlag:
                result = self.rsClient.selectStatusElement(
                    'Site',
                    'Status',
                    status='Active',
                    meta={'columns': ['Name']})
                if not result['OK']:
                    return result

                activeSites = [x[0] for x in result['Value']]

                result = self.rsClient.selectStatusElement(
                    'Site',
                    'Status',
                    status='Degraded',
                    meta={'columns': ['Name']})
                if not result['OK']:
                    return result

                degradedSites = [x[0] for x in result['Value']]

                return S_OK(activeSites + degradedSites)

            else:
                activeSites = RPCClient(
                    'WorkloadManagement/WMSAdministrator').getSiteMask()
                if not activeSites['OK']:
                    return activeSites

                return S_OK(activeSites['Value'])

        siteStatusList = []

        for siteName in siteNamesList:

            if self.rssFlag:
                siteStatus = self.rsClient.selectStatusElement(
                    'Site',
                    'Status',
                    name=siteName,
                    meta={'columns': ['Status']})
            else:
                siteStatus = RPCClient('WorkloadManagement/WMSAdministrator'
                                       ).getSiteMaskStatus(siteName)

            if not siteStatus['OK']:
                return siteStatus
            elif not siteStatus['Value']:
                #if one of the listed elements does not exist continue
                continue
            else:

                if self.rssFlag:
                    siteStatus = siteStatus['Value'][0][0]
                else:
                    siteStatus = siteStatus['Value']

            if siteStatus in ('Active', 'Degraded'):
                siteStatusList.append(siteName)

        return S_OK(siteStatusList)

    def getSites(self, siteState='Active'):
        """
    By default, it gets the currently active site list

    examples
      >>> siteStatus.getSites()
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getSites( 'Active' )
          S_OK( ['test1.test1.uk', 'test3.test3.org'] )
      >>> siteStatus.getSites( 'Banned' )
          S_OK( ['test0.test0.uk', ... ] )
      >>> siteStatus.getSites( 'All' )
          S_OK( ['test1.test1.uk', 'test3.test3.org', 'test4.test4.org', 'test5.test5.org'...] )
      >>> siteStatus.getSites( None )
          S_ERROR( ... )

    :Parameters:
      **siteState** - `String`
        state of the sites to be matched

    :return: S_OK() || S_ERROR()
    """

        if not siteState:
            return S_ERROR(DErrno.ERESUNK, 'siteState parameter is empty')

        elif siteState.capitalize() == 'All':
            # if no siteState is set return everything
            if self.rssFlag:
                siteStatus = self.rsClient.selectStatusElement(
                    'Site', 'Status', meta={'columns': ['Name']})
            else:
                siteStatus = RPCClient(
                    'WorkloadManagement/WMSAdministrator').getSiteMask('All')

        else:
            # fix case sensitive string
            siteState = siteState.capitalize()
            allowedStateList = [
                'Active', 'Banned', 'Degraded', 'Probing', 'Error', 'Unknown'
            ]
            if siteState not in allowedStateList:
                return S_ERROR(errno.EINVAL,
                               'Not a valid status, parameter rejected')

            if self.rssFlag:
                siteStatus = self.rsClient.selectStatusElement(
                    'Site',
                    'Status',
                    status=siteState,
                    meta={'columns': ['Name']})
            else:
                siteStatus = RPCClient('WorkloadManagement/WMSAdministrator'
                                       ).getSiteMask(siteState)

        if not siteStatus['OK']:
            return siteStatus
        else:

            if not self.rssFlag:
                return S_OK(siteStatus['Value'])

            siteList = []
            for site in siteStatus['Value']:
                siteList.append(site[0])

            return S_OK(siteList)

    def setSiteStatus(self, site, status, comment='No comment'):
        """
    Set the status of a site in the 'SiteStatus' table of RSS

    examples
      >>> siteStatus.banSite( 'site1.test.test' )
          S_OK()
      >>> siteStatus.banSite( None )
          S_ERROR( ... )

    :Parameters:
      **site** - `String`
        the site that is going to be banned
      **comment** - `String`
        reason for banning

    :return: S_OK() || S_ERROR()
    """

        if not status:
            return S_ERROR(DErrno.ERESUNK, 'status parameter is empty')

        # fix case sensitive string
        status = status.capitalize()
        allowedStateList = [
            'Active', 'Banned', 'Degraded', 'Probing', 'Error', 'Unknown'
        ]
        if status not in allowedStateList:
            return S_ERROR(errno.EINVAL,
                           'Not a valid status, parameter rejected')

        result = getProxyInfo()
        if result['OK']:
            tokenOwner = result['Value']['username']
        else:
            return S_ERROR("Unable to get user proxy info %s " %
                           result['Message'])

        tokenExpiration = datetime.utcnow() + timedelta(days=1)

        result = self.rsClient.modifyStatusElement(
            'Site',
            'Status',
            status=status,
            name=site,
            tokenExpiration=tokenExpiration,
            reason=comment,
            tokenOwner=tokenOwner)

        if not result['OK']:
            return result

        return S_OK()
Exemplo n.º 11
0
class ResourceStatus(object):
    """
  ResourceStatus helper that connects to CS if RSS flag is not Active. It keeps
  the connection to the db / server as an object member, to avoid creating a new
  one massively.
  """

    __metaclass__ = DIRACSingleton

    def __init__(self):
        """
    Constructor, initializes the rssClient.
    """

        self.log = gLogger.getSubLogger(self.__class__.__name__)
        self.rssConfig = RssConfiguration()
        self.__opHelper = Operations()
        self.rssClient = None
        self.infoGetter = InfoGetter()

        # We can set CacheLifetime and CacheHistory from CS, so that we can tune them.
        cacheLifeTime = int(self.rssConfig.getConfigCache())

        # RSSCache only affects the calls directed to RSS, if using the CS it is not
        # used.
        self.seCache = RSSCache('StorageElement', cacheLifeTime,
                                self.__updateSECache)

    def getStorageElementStatus(self,
                                elementName,
                                statusType=None,
                                default=None):
        """
    Helper with dual access, tries to get information from the RSS for the given
    StorageElement, otherwise, it gets it from the CS.

    example:
      >>> getStorageElementStatus( 'CERN-USER', 'ReadAccess' )
          S_OK( { 'CERN-USER' : { 'ReadAccess': 'Active' } } )
      >>> getStorageElementStatus( 'CERN-USER', 'Write' )
          S_OK( { 'CERN-USER' : {'ReadAccess': 'Active', 'WriteAccess': 'Active',
                                 'CheckAccess': 'Banned', 'RemoveAccess': 'Banned'}} )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType' )
          S_ERROR( xyz.. )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType', 'Unknown' )
          S_OK( 'Unknown' )

    """

        if self.__getMode():
            # We do not apply defaults. If is not on the cache, S_ERROR is returned.
            return self.__getRSSStorageElementStatus(elementName, statusType)
        else:
            return self.__getCSStorageElementStatus(elementName, statusType,
                                                    default)

    def setStorageElementStatus(self,
                                elementName,
                                statusType,
                                status,
                                reason=None,
                                tokenOwner=None):
        """
    Helper with dual access, tries set information in RSS and in CS.

    example:
      >>> getStorageElementStatus( 'CERN-USER', 'ReadAccess' )
          S_OK( { 'ReadAccess': 'Active' } )
      >>> getStorageElementStatus( 'CERN-USER', 'Write' )
          S_OK( {'ReadAccess': 'Active', 'WriteAccess': 'Active', 'CheckAccess': 'Banned', 'RemoveAccess': 'Banned'} )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType' )
          S_ERROR( xyz.. )
      >>> getStorageElementStatus( 'CERN-USER', 'ThisIsAWrongStatusType', 'Unknown' )
          S_OK( 'Unknown' )
    """

        if self.__getMode():
            return self.__setRSSStorageElementStatus(elementName, statusType,
                                                     status, reason,
                                                     tokenOwner)
        else:
            return self.__setCSStorageElementStatus(elementName, statusType,
                                                    status)

################################################################################

    def __updateSECache(self):
        """ Method used to update the StorageElementCache.

        It will try 5 times to contact the RSS before giving up
    """

        meta = {'columns': ['Name', 'StatusType', 'Status']}

        for ti in range(5):
            rawCache = self.rssClient.selectStatusElement(
                'Resource', 'Status', elementType='StorageElement', meta=meta)
            if rawCache['OK']:
                break
            self.log.warn("Can't get SE status",
                          rawCache['Message'] + "; trial %d" % ti)
            sleep(math.pow(ti, 2))
            self.rssClient = ResourceStatusClient()

        if not rawCache['OK']:
            return rawCache
        return S_OK(getCacheDictFromRawData(rawCache['Value']))

################################################################################

    def __getRSSStorageElementStatus(self, elementName, statusType):
        """
    Gets from the cache or the RSS the StorageElements status. The cache is a
    copy of the DB table. If it is not on the cache, most likely is not going
    to be on the DB.

    There is one exception: item just added to the CS, e.g. new StorageElement.
    The period between it is added to the DB and the changes are propagated
    to the cache will be inconsisten, but not dangerous. Just wait <cacheLifeTime>
    minutes.
    """

        cacheMatch = self.seCache.match(elementName, statusType)

        self.log.debug('__getRSSStorageElementStatus')
        self.log.debug(cacheMatch)

        return cacheMatch

    def __getCSStorageElementStatus(self, elementName, statusType, default):
        """
    Gets from the CS the StorageElements status
    """

        cs_path = "/Resources/StorageElements"

        if not isinstance(elementName, list):
            elementName = [elementName]

        statuses = self.rssConfig.getConfigStatusType('StorageElement')

        result = {}
        for element in elementName:

            if statusType is not None:
                # Added Active by default
                res = gConfig.getValue(
                    "%s/%s/%s" % (cs_path, element, statusType), 'Active')
                result[element] = {statusType: res}

            else:
                res = gConfig.getOptionsDict("%s/%s" % (cs_path, element))
                if res['OK'] and res['Value']:
                    elementStatuses = {}
                    for elementStatusType, value in res['Value'].items():
                        if elementStatusType in statuses:
                            elementStatuses[elementStatusType] = value

                    # If there is no status defined in the CS, we add by default Read and
                    # Write as Active.
                    if elementStatuses == {}:
                        elementStatuses = {
                            'ReadAccess': 'Active',
                            'WriteAccess': 'Active'
                        }

                    result[element] = elementStatuses

        if result:
            return S_OK(result)

        if default is not None:

            # sec check
            if statusType is None:
                statusType = 'none'

            defList = [[el, statusType, default] for el in elementName]
            return S_OK(getDictFromList(defList))

        _msg = "StorageElement '%s', with statusType '%s' is unknown for CS."
        return S_ERROR(_msg % (elementName, statusType))

    def __setRSSStorageElementStatus(self, elementName, statusType, status,
                                     reason, tokenOwner):
        """
    Sets on the RSS the StorageElements status
    """

        expiration = datetime.datetime.utcnow() + datetime.timedelta(days=1)

        self.seCache.acquireLock()
        try:
            res = self.rssClient.modifyStatusElement(
                'Resource',
                'Status',
                name=elementName,
                statusType=statusType,
                status=status,
                reason=reason,
                tokenOwner=tokenOwner,
                tokenExpiration=expiration)
            if res['OK']:
                self.seCache.refreshCache()

            if not res['OK']:
                _msg = 'Error updating StorageElement (%s,%s,%s)' % (
                    elementName, statusType, status)
                gLogger.warn('RSS: %s' % _msg)

            return res

        finally:
            # Release lock, no matter what.
            self.seCache.releaseLock()

    def __setCSStorageElementStatus(self, elementName, statusType, status):
        """
    Sets on the CS the StorageElements status
    """

        statuses = self.rssConfig.getConfigStatusType('StorageElement')
        if not statusType in statuses:
            gLogger.error("%s is not a valid statusType" % statusType)
            return S_ERROR("%s is not a valid statusType: %s" %
                           (statusType, statuses))

        csAPI = CSAPI()

        cs_path = "/Resources/StorageElements"

        csAPI.setOption("%s/%s/%s" % (cs_path, elementName, statusType),
                        status)

        res = csAPI.commitChanges()
        if not res['OK']:
            gLogger.warn('CS: %s' % res['Message'])

        return res

    def __getMode(self):
        """
      Get's flag defined ( or not ) on the RSSConfiguration. If defined as 1,
      we use RSS, if not, we use CS.
    """

        res = self.rssConfig.getConfigState()

        if res == 'Active':

            if self.rssClient is None:
                self.rssClient = ResourceStatusClient()
            return True

        self.rssClient = None
        return False

    def isStorageElementAlwaysBanned(self, seName, statusType):
        """ Checks if the AlwaysBanned policy is applied to the SE
        given as parameter

        :param seName : string, name of the SE
        :param statusType : ReadAcces, WriteAccess, RemoveAccess, CheckAccess

        :returns: S_OK(True/False)
    """

        res = self.infoGetter.getPoliciesThatApply({
            'name': seName,
            'statusType': statusType
        })
        if not res['OK']:
            self.log.error(
                "isStorageElementAlwaysBanned: unable to get the information",
                res['Message'])
            return res

        isAlwaysBanned = 'AlwaysBanned' in [
            policy['type'] for policy in res['Value']
        ]

        return S_OK(isAlwaysBanned)