예제 #1
0
 def _query( self, cmd, conn=False ):
   start = time.time()
   ret = DB._query( self, cmd, conn )
   if DEBUG:
     print >> debugFile, time.time() - start, cmd.replace('\n','')
     debugFile.flush()
   return ret
예제 #2
0
 def _query(self, cmd, conn=False):
     start = time.time()
     ret = DB._query(self, cmd, conn)
     if DEBUG:
         print >> debugFile, time.time() - start, cmd.replace('\n', '')
         debugFile.flush()
     return ret
예제 #3
0
 def _query( self, cmd, conn=False ):
   """ Make queries to MPIJob DB
   """
   print "DB3"
   start = Time.time()
   ret = DB._query( self, cmd, conn )
   if DEBUG:
     print >> debugFile, Time.time() - start, cmd.replace('\n','')
     debugFile.flush()
   print ret
   return ret
예제 #4
0
파일: MPIJobDB.py 프로젝트: hamar/EELADIRAC
 def _query(self, cmd, conn=False):
     """ Make queries to MPIJob DB
 """
     print "DB3"
     start = Time.time()
     ret = DB._query(self, cmd, conn)
     if DEBUG:
         print >> debugFile, Time.time() - start, cmd.replace('\n', '')
         debugFile.flush()
     print ret
     return ret
예제 #5
0
class ResourceManagementDB( object ):
  '''
    Class that defines the tables for the ResourceManagementDB on a python dictionary.
  '''

  # Written PrimaryKey as list on purpose !!
  _tablesDB = {}
  _tablesDB[ 'AccountingCache' ] = { 'Fields' : 
                     {
                       #'AccountingCacheID' : 'INT UNSIGNED AUTO_INCREMENT NOT NULL',
                       'Name'          : 'VARCHAR(64) NOT NULL',
                       'PlotType'      : 'VARCHAR(16) NOT NULL',
                       'PlotName'      : 'VARCHAR(64) NOT NULL',                     
                       'Result'        : 'TEXT NOT NULL',
                       'DateEffective' : 'DATETIME NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'
                      },
                      'PrimaryKey' : [ 'Name', 'PlotType', 'PlotName' ]                                            
                                }

  _tablesDB[ 'DowntimeCache' ] = { 'Fields' :
                      {
                       'DowntimeID'    : 'VARCHAR(64) NOT NULL',
                       'Element'       : 'VARCHAR(32) NOT NULL',
                       'Name'          : 'VARCHAR(64) NOT NULL',
                       'StartDate'     : 'DATETIME NOT NULL',
                       'EndDate'       : 'DATETIME NOT NULL',
                       'Severity'      : 'VARCHAR(32) NOT NULL',
                       'Description'   : 'VARCHAR(512) NOT NULL',
                       'Link'          : 'VARCHAR(255) NOT NULL',       
                       'DateEffective' : 'DATETIME NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'     
                      },
                      'PrimaryKey' : [ 'DowntimeID' ]
                                }

  _tablesDB[ 'GGUSTicketsCache' ] = { 'Fields' :
                      {
                       'GocSite'       : 'VARCHAR(64) NOT NULL',
                       'Link'          : 'VARCHAR(1024) NOT NULL',    
                       'OpenTickets'   : 'INTEGER NOT NULL DEFAULT 0',
                       'Tickets'       : 'VARCHAR(1024) NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'                       
                      },
                      'PrimaryKey' : [ 'GocSite' ]
                                }

  _tablesDB[ 'JobCache' ] = { 'Fields' :
                      {
                       'Site'          : 'VARCHAR(64) NOT NULL',
                       'MaskStatus'    : 'VARCHAR(32) NOT NULL',    
                       'Efficiency'    : 'DOUBLE NOT NULL DEFAULT 0',
                       'Status'        : 'VARCHAR(16) NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'                       
                      },
                      'PrimaryKey' : [ 'Site' ]
                                }

  _tablesDB[ 'PilotCache' ] = { 'Fields' :
                      {
                       'Site'          : 'VARCHAR(64) NOT NULL',
                       'CE'            : 'VARCHAR(64) NOT NULL',
                       'PilotsPerJob'  : 'DOUBLE NOT NULL DEFAULT 0',
                       'PilotJobEff'   : 'DOUBLE NOT NULL DEFAULT 0',   
                       'Status'        : 'VARCHAR(16) NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'                                    
                      },
                      'PrimaryKey' : [ 'Site', 'CE' ]
                                }

  _tablesDB[ 'PolicyResult' ] = { 'Fields' : 
                      {
                       'Element'       : 'VARCHAR(32) NOT NULL',
                       'Name'          : 'VARCHAR(64) NOT NULL',
                       'PolicyName'    : 'VARCHAR(64) NOT NULL',
                       'StatusType'    : 'VARCHAR(16) NOT NULL DEFAULT ""',
                       'Status'        : 'VARCHAR(16) NOT NULL',
                       'Reason'        : 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
                       'DateEffective' : 'DATETIME NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'
                      },
                      'PrimaryKey' : [ 'Element', 'Name', 'StatusType', 'PolicyName' ] 
                                }
  
  _tablesDB[ 'PolicyResultLog' ] = { 'Fields' : 
                      {
                       'PolicyResultLogID' : 'INT UNSIGNED AUTO_INCREMENT NOT NULL',
                       'Element'           : 'VARCHAR(32) NOT NULL',
                       'Name'              : 'VARCHAR(64) NOT NULL',
                       'PolicyName'        : 'VARCHAR(64) NOT NULL',
                       'StatusType'        : 'VARCHAR(16) NOT NULL DEFAULT ""',
                       'Status'            : 'VARCHAR(8) NOT NULL',
                       'Reason'            : 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
                       'DateEffective'     : 'DATETIME NOT NULL',                       
                       'LastCheckTime'     : 'DATETIME NOT NULL'                                   
                      },
                      'PrimaryKey' : [ 'PolicyResultLogID' ]
                                }

  _tablesDB[ 'SpaceTokenOccupancyCache' ] = { 'Fields' :
                      {
                       'Endpoint'       : 'VARCHAR( 64 ) NOT NULL',
                       'Token'          : 'VARCHAR( 64 ) NOT NULL',
                       'Total'          : 'INTEGER NOT NULL DEFAULT 0',                      
                       'Guaranteed'     : 'INTEGER NOT NULL DEFAULT 0',
                       'Free'           : 'INTEGER NOT NULL DEFAULT 0',                     
                       'LastCheckTime'  : 'DATETIME NOT NULL' 
                      },
                      'PrimaryKey' : [ 'Endpoint', 'Token' ]                                             
                                } 

  _tablesDB[ 'TransferCache' ] = { 'Fields' :
                      {
                       'SourceName'      : 'VARCHAR( 64 ) NOT NULL',
                       'DestinationName' : 'VARCHAR( 64 ) NOT NULL',
                       'Metric'          : 'VARCHAR( 16 ) NOT NULL',
                       'Value'           : 'DOUBLE NOT NULL DEFAULT 0',                     
                       'LastCheckTime'   : 'DATETIME NOT NULL' 
                      },
                      'PrimaryKey' : [ 'SourceName', 'DestinationName', 'Metric' ]                                             
                                } 
 
  _tablesDB[ 'UserRegistryCache' ] = { 'Fields' : 
                      {
                       'Login'         : 'VARCHAR(16)',
                       'Name'          : 'VARCHAR(64) NOT NULL',
                       'Email'         : 'VARCHAR(64) NOT NULL',
                       'LastCheckTime' : 'DATETIME NOT NULL'  
                      },
                      'PrimaryKey' : [ 'Login' ]           
                                }   

  _tablesDB[ 'VOBOXCache' ] = { 'Fields' :
                      {
                       'Site'          : 'VARCHAR( 64 ) NOT NULL',
                       'System'        : 'VARCHAR( 64 ) NOT NULL',
                       'ServiceUp'     : 'INTEGER NOT NULL DEFAULT 0',
                       'MachineUp'     : 'INTEGER NOT NULL DEFAULT 0',
                       'LastCheckTime' : 'DATETIME NOT NULL'                                            
                      },        
                      'PrimaryKey' : [ 'Site', 'System' ]        
                                }
  
  _tablesLike  = {}
  _likeToTable = {}
  
  def __init__( self, maxQueueSize = 10, mySQL = None ):
    '''
      Constructor, accepts any DB or mySQL connection, mostly used for testing
      purposes.
    '''
    self._tableDict = self.__generateTables()
    
    if mySQL is not None:
      self.database = mySQL
    else:
      self.database = DB( 'ResourceManagementDB', 
                          'ResourceStatus/ResourceManagementDB', maxQueueSize )

  ## SQL Methods ############################################################### 
      
  def insert( self, params, meta ):
    '''
    Inserts args in the DB making use of kwargs where parameters such as
    the 'table' are specified ( filled automatically by the Client). Typically you 
    will not pass kwargs to this function, unless you know what are you doing 
    and you have a very special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

    utcnow = datetime.utcnow().replace( microsecond = 0 )

    # We force lastCheckTime to utcnow if it is not present on the params
    #if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
    if 'lastCheckTime' in params and params[ 'lastCheckTime' ] is None:  
      params[ 'lastCheckTime' ] = utcnow  

    if 'dateEffective' in params and params[ 'dateEffective' ] is None:
      params[ 'dateEffective' ] = utcnow
    
    return MySQLWrapper.insert( self, params, meta )

  def update( self, params, meta ):
    '''
    Updates row with values given on args. The row selection is done using the
    default of MySQLMonkey ( column.primary or column.keyColumn ). It can be
    modified using kwargs. The 'table' keyword argument is mandatory, and 
    filled automatically by the Client. Typically you will not pass kwargs to 
    this function, unless you know what are you doing and you have a very 
    special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
    
    # We force lastCheckTime to utcnow if it is not present on the params
    #if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
    if 'lastCheckTime' in params and params[ 'lastCheckTime' ] is None:      
      params[ 'lastCheckTime' ] = datetime.utcnow().replace( microsecond = 0 ) 
    
    return MySQLWrapper.update( self, params, meta )

  def select( self, params, meta ):
    '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
    return MySQLWrapper.select( self, params, meta )

  def delete( self, params, meta ):
    '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query. 
    There is only one forbidden query, with all parameters None ( this would 
    mean a query of the type `DELETE * from TableName` ). The usage of kwargs 
    is the same as in the get function.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
    return MySQLWrapper.delete( self, params, meta )

  ## Extended SQL methods ######################################################
  
  def addOrModify( self, params, meta ):
    '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        
    selectQuery = self.select( params, meta )
    if not selectQuery[ 'OK' ]:
      return selectQuery 
              
    if selectQuery[ 'Value' ]:      
      
      # Pseudo - code
      # for all column not being PrimaryKey and not a time column: 
      #   if one or more column different than params if not None:
      #     we update dateTime as well
      
      columns = selectQuery[ 'Columns' ]
      values  = selectQuery[ 'Value' ]
      
      if len( values ) != 1:
        return S_ERROR( 'More than one value returned on addOrModify, please report !!' )

      selectDict = dict( zip( columns, values[ 0 ] ) )
      
      newDateEffective = None
      
      for key, value in params.items():
        if key in ( 'lastCheckTime', 'dateEffective' ):
          continue
        
        if value is None:
          continue
        
        if value != selectDict[ key[0].upper() + key[1:] ]:
          newDateEffective = datetime.utcnow().replace( microsecond = 0 )   
          break
      
      if 'dateEffective' in params:
        params[ 'dateEffective' ] = newDateEffective              
      
      userQuery  = self.update( params, meta )

    else:      

      userQuery = self.insert( params, meta )
    
#    if self.recordLogs:
#      
#      if 'table' in meta and meta[ 'table' ].endswith( 'Status' ):
#        
#        if isUpdate:
#          updateRes = self.select( params, meta )
#          if not updateRes[ 'OK' ]:
#            return updateRes
#          
#          # If we are updating more that one result at a time, this is most likely
#          # going to be a mess. All queries must be one at a time, if need to do
#          if len( updateRes[ 'Value' ] ) != 1:
#            return S_ERROR( ' PLEASE REPORT to developers !!: %s, %s' % ( params, meta ) )
#          if len( updateRes[ 'Value' ][ 0 ] ) != len( updateRes[ 'Columns' ] ):
#            # Uyyy, something went seriously wrong !!
#            return S_ERROR( ' PLEASE REPORT to developers !!: %s' % updateRes )
#                    
#          params = dict( zip( updateRes['Columns'], updateRes[ 'Value' ][0] )) 
#                
#        meta[ 'tableName' ] = meta[ 'tableName' ].replace( 'Status', 'Log' )
#
#        logRes = self.insert( params, meta )
#        if not logRes[ 'OK' ]:
#          return logRes
#    
    return userQuery      

  def addIfNotThere( self, params, meta ):
    '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is not there, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        
    selectQuery = self.select( params, meta )
    if not selectQuery[ 'OK' ]:
      return selectQuery 
       
    if selectQuery[ 'Value' ]:      
      return selectQuery
    
    return self.insert( params, meta )   

  ## Auxiliar methods ##########################################################

  def getTable( self, tableName ):
    '''
      Returns a table dictionary description given its name 
    '''
    if tableName in self._tableDict:
      return S_OK( self._tableDict[ tableName ] )
    
    return S_ERROR( '%s is not on the schema' % tableName )
    
  def getTablesList( self ):
    '''
      Returns a list of the table names in the schema.
    '''
    return S_OK( self._tableDict.keys() )

  ## Protected methods #########################################################

  def _checkTable( self ):
    '''
      Method used by database tools to write the schema
    '''  
    return self.__createTables()

  ## Private methods ###########################################################

  def __createTables( self, tableName = None ):
    '''
      Writes the schema in the database. If no tableName is given, all tables
      are written in the database. If a table is already in the schema, it is
      skipped to avoid problems trying to create a table that already exists.
    '''

    # Horrible SQL here !!
    tablesCreatedRes = self.database._query( "show tables" )
    if not tablesCreatedRes[ 'OK' ]:
      return tablesCreatedRes
    tablesCreated = [ tableCreated[0] for tableCreated in tablesCreatedRes[ 'Value' ] ]

    tables = {}
    if tableName is None:
      tables.update( self._tableDict )
    
    elif tableName in self._tableDict:
      tables = { tableName : self._tableDict[ tableName ] }
    
    else:
      return S_ERROR( '"%s" is not a known table' % tableName )    
      
    for tableName in tablesCreated:
      if tableName in tables:
        del tables[ tableName ]  
              
    res = self.database._createTables( tables )
    if not res[ 'OK' ]:
      return res
    
    # Human readable S_OK message
    if res[ 'Value' ] == 0:
      res[ 'Value' ] = 'No tables created'
    else:
      res[ 'Value' ] = 'Tables created: %s' % ( ','.join( tables.keys() ) )
    return res      
  
  def __generateTables( self ):
    '''
      Method used to transform the class variables into instance variables,
      for safety reasons.
    '''
  
    # Avoids copying object.
    tables = {}
    tables.update( self._tablesDB )
    
    for tableName, tableLike in self._likeToTable.items():
      
      tables[ tableName ] = self._tablesLike[ tableLike ]
       
    return tables

################################################################################
#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF
예제 #6
0
class ResourceStatusDB( object ):
  '''
    Class that defines the tables for the ResourceStatusDB on a python dictionary.
  '''

  # Written PrimaryKey as list on purpose !!
  _tablesDB = {}

  _tablesLike = {}
  _tablesLike[ 'ElementStatus' ]    = { 'Fields' :{'Name'            : 'VARCHAR(64) NOT NULL',
                                                   'StatusType'      : 'VARCHAR(128) NOT NULL DEFAULT "all"',
                                                   'Status'          : 'VARCHAR(8) NOT NULL DEFAULT ""',
                                                   'ElementType'     : 'VARCHAR(32) NOT NULL DEFAULT ""',
                                                   'Reason'          : 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
                                                   'DateEffective'   : 'DATETIME NOT NULL',
                                                   'LastCheckTime'   : 'DATETIME NOT NULL DEFAULT "1000-01-01 00:00:00"',
                                                   'TokenOwner'      : 'VARCHAR(16) NOT NULL DEFAULT "rs_svc"',
                                                   'TokenExpiration' : 'DATETIME NOT NULL DEFAULT "9999-12-31 23:59:59"'
                                                  },

                                       'PrimaryKey' : [ 'Name', 'StatusType' ]#, 'ElementType' ] #FIXME: elementType is needed to be part of the key ??
                                      }

  _tablesLike[ 'ElementWithID' ]       = { 'Fields' : {'ID'              : 'BIGINT UNSIGNED AUTO_INCREMENT NOT NULL',
                                                       'Name'            : 'VARCHAR(64) NOT NULL',
                                                       'StatusType'      : 'VARCHAR(128) NOT NULL DEFAULT "all"',
                                                       'Status'          : 'VARCHAR(8) NOT NULL DEFAULT ""',
                                                       'ElementType'     : 'VARCHAR(32) NOT NULL DEFAULT ""',
                                                       'Reason'          : 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
                                                       'DateEffective'   : 'DATETIME NOT NULL',
                                                       'LastCheckTime'   : 'DATETIME NOT NULL DEFAULT "1000-01-01 00:00:00"',
                                                       'TokenOwner'      : 'VARCHAR(16) NOT NULL DEFAULT "rs_svc"',
                                                       'TokenExpiration' : 'DATETIME NOT NULL DEFAULT "9999-12-31 23:59:59"'
                                                      },
                                           'PrimaryKey' : [ 'ID' ]
                                         }

  _likeToTable = {  'SiteStatus'        : 'ElementStatus',
                    'SiteLog'           : 'ElementWithID',
                    'SiteHistory'       : 'ElementWithID',
                    'ResourceStatus'    : 'ElementStatus',
                    'ResourceLog'       : 'ElementWithID',
                    'ResourceHistory'   : 'ElementWithID',
                    'NodeStatus'        : 'ElementStatus',
                    'NodeLog'           : 'ElementWithID',
                    'NodeHistory'       : 'ElementWithID',
                    'ComponentStatus'   : 'ElementStatus',
                    'ComponentLog'      : 'ElementWithID',
                    'ComponentHistory'  : 'ElementWithID',
                 }

  def __init__( self, mySQL = None ):
    '''
      Constructor, accepts any DB or mySQL connection, mostly used for testing
      purposes.
    '''

    self._tableDict = self.__generateTables()

    if mySQL is not None:
      self.database = mySQL
    else:
      self.database = DB( 'ResourceStatusDB',
                          'ResourceStatus/ResourceStatusDB' )

  ## SQL Methods ###############################################################

  def insert( self, params, meta ):
    '''
    Inserts args in the DB making use of kwargs where parameters such as
    the 'table' are specified ( filled automatically by the Client). Typically you
    will not pass kwargs to this function, unless you know what are you doing
    and you have a very special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''


    utcnow = datetime.utcnow().replace( microsecond = 0 )
    # We force lastCheckTime to utcnow if it is not present on the params
    #if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
    if 'lastCheckTime' in params and params[ 'lastCheckTime' ] is None:
      params[ 'lastCheckTime' ] = utcnow

    # If it is a XStatus table, we force dateEffective to now.
    if 'table' in meta and meta[ 'table' ].endswith( 'Status' ):
      if 'dateEffective' in params and params[ 'dateEffective' ] is None:
        params[ 'dateEffective' ] = utcnow

    return MySQLWrapper.insert( self, params, meta )

  def update( self, params, meta ):
    '''
    Updates row with values given on args. The row selection is done using the
    default of MySQLMonkey ( column.primary or column.keyColumn ). It can be
    modified using kwargs. The 'table' keyword argument is mandatory, and
    filled automatically by the Client. Typically you will not pass kwargs to
    this function, unless you know what are you doing and you have a very
    special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
    # We force lastCheckTime to utcnow if it is not present on the params
    if not( 'lastCheckTime' in params and not params[ 'lastCheckTime' ] is None ):
      params[ 'lastCheckTime' ] = datetime.utcnow().replace( microsecond = 0 )

    return MySQLWrapper.update( self, params, meta )

  def select( self, params, meta ):
    '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
    return MySQLWrapper.select( self, params, meta )

  def delete( self, params, meta ):
    '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query.
    There is only one forbidden query, with all parameters None ( this would
    mean a query of the type DELETE * from TableName ). The usage of kwargs
    is the same as in the get function.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
    return MySQLWrapper.delete( self, params, meta )

  ## Extended SQL methods ######################################################

  def addOrModify( self, params, meta ):
    '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it is inserted as a new entry.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

    selectQuery = self.select( params, meta )
    if not selectQuery[ 'OK' ]:
      return selectQuery

    isUpdate = False

    if selectQuery[ 'Value' ]:

      columns = selectQuery[ 'Columns' ]
      values  = selectQuery[ 'Value' ]

      if len( values ) != 1:
        return S_ERROR( 'More than one value returned on addOrModify, please report !!' )

      selectDict = dict( zip( columns, values[ 0 ] ) )

      newDateEffective = None

      for key, value in params.items():
        if key in ( 'lastCheckTime', 'dateEffective' ):
          continue

        if value is None:
          continue

        if value != selectDict[ key[0].upper() + key[1:] ]:
          newDateEffective = datetime.utcnow().replace( microsecond = 0 )
          break

      if 'dateEffective' in params:
        params[ 'dateEffective' ] = newDateEffective

      userQuery  = self.update( params, meta )
      isUpdate   = True
    else:
      userQuery = self.insert( params, meta )

    logResult = self._logRecord( params, meta, isUpdate )
    if not logResult[ 'OK' ]:
      return logResult

    return userQuery

  def modify( self, params, meta ):
    '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it does nothing.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

    selectQuery = self.select( params, meta )
    if not selectQuery[ 'OK' ]:
      return selectQuery

    if not selectQuery[ 'Value' ]:
      return S_ERROR( 'Nothing to update for %s' % str( params ) )

    columns = selectQuery[ 'Columns' ]
    values  = selectQuery[ 'Value' ]

    if len( values ) != 1:
      return S_ERROR( 'More than one value returned on addOrModify, please report !!' )

    selectDict = dict( zip( columns, values[ 0 ] ) )

    newDateEffective = None

    for key, value in params.items():
      if key in ( 'lastCheckTime', 'dateEffective' ):
        continue

      if value is None:
        continue

      if value != selectDict[ key[0].upper() + key[1:] ]:
        newDateEffective = datetime.utcnow().replace( microsecond = 0 )
        break

    if 'dateEffective' in params:
      params[ 'dateEffective' ] = newDateEffective

    userQuery = self.update( params, meta )

    logResult = self._logRecord( params, meta, True )
    if not logResult[ 'OK' ]:
      return logResult

    return userQuery

  def addIfNotThere( self, params, meta ):
    '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is not there, it is inserted as a new entry.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

    selectQuery = self.select( params, meta )
    if not selectQuery[ 'OK' ]:
      return selectQuery

    if selectQuery[ 'Value' ]:
      return selectQuery

    insertQuery = self.insert( params, meta )

    # Record logs
    if 'table' in meta and meta[ 'table' ].endswith( 'Status' ):

      meta[ 'table' ] = meta[ 'table' ].replace( 'Status', 'Log' )

      logRes = self.insert( params, meta )
      if not logRes[ 'OK' ]:
        return logRes

    return insertQuery

  ## Auxiliar methods ##########################################################

  def getTable( self, tableName ):
    '''
      Returns a table dictionary description given its name
    '''
    if tableName in self._tableDict:
      return S_OK( self._tableDict[ tableName ] )

    return S_ERROR( '%s is not on the schema' % tableName )

  def getTablesList( self ):
    '''
      Returns a list of the table names in the schema.
    '''
    return S_OK( self._tableDict.keys() )

  ## Protected methods #########################################################

  def _checkTable( self ):
    '''
      Method used by database tools to write the schema
    '''
    return self.__createTables()

  def _logRecord( self, params, meta, isUpdate ):
    '''
      Method that records every change on a LogTable, if activated on the CS.
    '''

    if not ( 'table' in meta and meta[ 'table' ].endswith( 'Status' ) ):
      return S_OK()

    if isUpdate:
      updateRes = self.select( params, meta )
      if not updateRes[ 'OK' ]:
        return updateRes

      # If we are updating more that one result at a time, this is most likely
      # going to be a mess. All queries must be one at a time, if need to do
      if len( updateRes[ 'Value' ] ) != 1:
        return S_ERROR( ' PLEASE REPORT to developers !!: %s, %s' % ( params, meta ) )
      if len( updateRes[ 'Value' ][ 0 ] ) != len( updateRes[ 'Columns' ] ):
        # Uyyy, something went seriously wrong !!
        return S_ERROR( ' PLEASE REPORT to developers !!: %s' % updateRes )

      params = dict( zip( updateRes['Columns'], updateRes[ 'Value' ][0] ))

    meta[ 'table' ] = meta[ 'table' ].replace( 'Status', 'Log' )

    logRes = self.insert( params, meta )

    return logRes

  ## Private methods ###########################################################

  def __createTables( self, tableName = None ):
    '''
      Writes the schema in the database. If no tableName is given, all tables
      are written in the database. If a table is already in the schema, it is
      skipped to avoid problems trying to create a table that already exists.
    '''

    # Horrible SQL here !!
    tablesCreatedRes = self.database._query( "show tables" )
    if not tablesCreatedRes[ 'OK' ]:
      return tablesCreatedRes
    tablesCreated = [ tableCreated[0] for tableCreated in tablesCreatedRes[ 'Value' ] ]

    tables = {}
    if tableName is None:
      tables.update( self._tableDict )

    elif tableName in self._tableDict:
      tables = { tableName : self._tableDict[ tableName ] }

    else:
      return S_ERROR( '"%s" is not a known table' % tableName )

    for tableName in tablesCreated:
      if tableName in tables:
        del tables[ tableName ]

    res = self.database._createTables( tables )
    if not res[ 'OK' ]:
      return res

    # Human readable S_OK message
    if res[ 'Value' ] == 0:
      res[ 'Value' ] = 'No tables created'
    else:
      res[ 'Value' ] = 'Tables created: %s' % ( ','.join( tables.keys() ) )
    return res

  def __generateTables( self ):
    '''
      Method used to transform the class variables into instance variables,
      for safety reasons.
    '''

    # Avoids copying object.
    tables = {}
    tables.update( self._tablesDB )

    for tableName, tableLike in self._likeToTable.items():

      tables[ tableName ] = self._tablesLike[ tableLike ]

    return tables
예제 #7
0
class ResourceStatusDB(object):
    '''
    Class that defines the tables for the ResourceStatusDB on a python dictionary.
  '''

    # Written PrimaryKey as list on purpose !!
    _tablesDB = {}

    _tablesLike = {}
    _tablesLike['ElementStatus'] = {
        'Fields': {
            'Name': 'VARCHAR(64) NOT NULL',
            'StatusType': 'VARCHAR(128) NOT NULL DEFAULT "all"',
            'Status': 'VARCHAR(8) NOT NULL DEFAULT ""',
            'ElementType': 'VARCHAR(32) NOT NULL DEFAULT ""',
            'Reason': 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
            'DateEffective': 'DATETIME NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL DEFAULT "1000-01-01 00:00:00"',
            'TokenOwner': 'VARCHAR(16) NOT NULL DEFAULT "rs_svc"',
            'TokenExpiration':
            'DATETIME NOT NULL DEFAULT "9999-12-31 23:59:59"'
        },
        #FIXME: elementType is needed to be part of the key ??
        'PrimaryKey': ['Name', 'StatusType']  #, 'ElementType' ]              
    }

    _tablesLike['ElementWithID'] = {
        'Fields': {
            'ID': 'BIGINT UNSIGNED AUTO_INCREMENT NOT NULL',
            'Name': 'VARCHAR(64) NOT NULL',
            'StatusType': 'VARCHAR(128) NOT NULL DEFAULT "all"',
            'Status': 'VARCHAR(8) NOT NULL DEFAULT ""',
            'ElementType': 'VARCHAR(32) NOT NULL DEFAULT ""',
            'Reason': 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
            'DateEffective': 'DATETIME NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL DEFAULT "1000-01-01 00:00:00"',
            'TokenOwner': 'VARCHAR(16) NOT NULL DEFAULT "rs_svc"',
            'TokenExpiration':
            'DATETIME NOT NULL DEFAULT "9999-12-31 23:59:59"'
        },
        'PrimaryKey': ['ID']
    }

    _likeToTable = {
        'SiteStatus': 'ElementStatus',
        'SiteLog': 'ElementWithID',
        'SiteHistory': 'ElementWithID',
        'ResourceStatus': 'ElementStatus',
        'ResourceLog': 'ElementWithID',
        'ResourceHistory': 'ElementWithID',
        'NodeStatus': 'ElementStatus',
        'NodeLog': 'ElementWithID',
        'NodeHistory': 'ElementWithID',
        'ComponentStatus': 'ElementStatus',
        'ComponentLog': 'ElementWithID',
        'ComponentHistory': 'ElementWithID',
    }

    def __init__(self, mySQL=None):
        '''
      Constructor, accepts any DB or mySQL connection, mostly used for testing
      purposes.
    '''

        self._tableDict = self.__generateTables()

        if mySQL is not None:
            self.database = mySQL
        else:
            self.database = DB('ResourceStatusDB',
                               'ResourceStatus/ResourceStatusDB')

    ## SQL Methods ###############################################################

    def insert(self, params, meta):
        '''
    Inserts args in the DB making use of kwargs where parameters such as
    the 'table' are specified ( filled automatically by the Client). Typically you 
    will not pass kwargs to this function, unless you know what are you doing 
    and you have a very special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        utcnow = datetime.utcnow().replace(microsecond=0)
        # We force lastCheckTime to utcnow if it is not present on the params
        #if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
        if 'lastCheckTime' in params and params['lastCheckTime'] is None:
            params['lastCheckTime'] = utcnow

        # If it is a XStatus table, we force dateEffective to now.
        if 'table' in meta and meta['table'].endswith('Status'):
            if 'dateEffective' in params and params['dateEffective'] is None:
                params['dateEffective'] = utcnow

        return MySQLWrapper.insert(self, params, meta)

    def update(self, params, meta):
        '''
    Updates row with values given on args. The row selection is done using the
    default of MySQLMonkey ( column.primary or column.keyColumn ). It can be
    modified using kwargs. The 'table' keyword argument is mandatory, and 
    filled automatically by the Client. Typically you will not pass kwargs to 
    this function, unless you know what are you doing and you have a very 
    special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        # We force lastCheckTime to utcnow if it is not present on the params
        if not ('lastCheckTime' in params
                and not (params['lastCheckTime'] is None)):
            params['lastCheckTime'] = datetime.utcnow().replace(microsecond=0)

        return MySQLWrapper.update(self, params, meta)

    def select(self, params, meta):
        '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        return MySQLWrapper.select(self, params, meta)

    def delete(self, params, meta):
        '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query. 
    There is only one forbidden query, with all parameters None ( this would 
    mean a query of the type `DELETE * from TableName` ). The usage of kwargs 
    is the same as in the get function.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        return MySQLWrapper.delete(self, params, meta)

    ## Extended SQL methods ######################################################

    def addOrModify(self, params, meta):
        '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        selectQuery = self.select(params, meta)
        if not selectQuery['OK']:
            return selectQuery

        isUpdate = False

        if selectQuery['Value']:

            columns = selectQuery['Columns']
            values = selectQuery['Value']

            if len(values) != 1:
                return S_ERROR(
                    'More than one value returned on addOrModify, please report !!'
                )

            selectDict = dict(zip(columns, values[0]))

            newDateEffective = None

            for key, value in params.items():
                if key in ('lastCheckTime', 'dateEffective'):
                    continue

                if value is None:
                    continue

                if value != selectDict[key[0].upper() + key[1:]]:
                    newDateEffective = datetime.utcnow().replace(microsecond=0)
                    break

            if 'dateEffective' in params:
                params['dateEffective'] = newDateEffective

            userQuery = self.update(params, meta)
            isUpdate = True
        else:
            userQuery = self.insert(params, meta)

        logResult = self._logRecord(params, meta, isUpdate)
        if not logResult['OK']:
            return logResult

        return userQuery

    def modify(self, params, meta):
        '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it does nothing. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        selectQuery = self.select(params, meta)
        if not selectQuery['OK']:
            return selectQuery

        if not selectQuery['Value']:
            return S_ERROR('Nothing to update for %s' % str(params))

        columns = selectQuery['Columns']
        values = selectQuery['Value']

        if len(values) != 1:
            return S_ERROR(
                'More than one value returned on addOrModify, please report !!'
            )

        selectDict = dict(zip(columns, values[0]))

        newDateEffective = None

        for key, value in params.items():
            if key in ('lastCheckTime', 'dateEffective'):
                continue

            if value is None:
                continue

            if value != selectDict[key[0].upper() + key[1:]]:
                newDateEffective = datetime.utcnow().replace(microsecond=0)
                break

        if 'dateEffective' in params:
            params['dateEffective'] = newDateEffective

        userQuery = self.update(params, meta)

        logResult = self._logRecord(params, meta, True)
        if not logResult['OK']:
            return logResult

        return userQuery

    def addIfNotThere(self, params, meta):
        '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is not there, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        selectQuery = self.select(params, meta)
        if not selectQuery['OK']:
            return selectQuery

        if selectQuery['Value']:
            return selectQuery

        insertQuery = self.insert(params, meta)

        # Record logs
        if 'table' in meta and meta['table'].endswith('Status'):

            meta['table'] = meta['table'].replace('Status', 'Log')

            logRes = self.insert(params, meta)
            if not logRes['OK']:
                return logRes

        return insertQuery

    ## Auxiliar methods ##########################################################

    def getTable(self, tableName):
        '''
      Returns a table dictionary description given its name 
    '''
        if tableName in self._tableDict:
            return S_OK(self._tableDict[tableName])

        return S_ERROR('%s is not on the schema' % tableName)

    def getTablesList(self):
        '''
      Returns a list of the table names in the schema.
    '''
        return S_OK(self._tableDict.keys())

    ## Protected methods #########################################################

    def _checkTable(self):
        '''
      Method used by database tools to write the schema
    '''
        return self.__createTables()

    def _logRecord(self, params, meta, isUpdate):
        '''
      Method that records every change on a LogTable, if activated on the CS.
    '''

        if not ('table' in meta and meta['table'].endswith('Status')):
            return S_OK()

        if isUpdate:
            updateRes = self.select(params, meta)
            if not updateRes['OK']:
                return updateRes

            # If we are updating more that one result at a time, this is most likely
            # going to be a mess. All queries must be one at a time, if need to do
            if len(updateRes['Value']) != 1:
                return S_ERROR(' PLEASE REPORT to developers !!: %s, %s' %
                               (params, meta))
            if len(updateRes['Value'][0]) != len(updateRes['Columns']):
                # Uyyy, something went seriously wrong !!
                return S_ERROR(' PLEASE REPORT to developers !!: %s' %
                               updateRes)

            params = dict(zip(updateRes['Columns'], updateRes['Value'][0]))

        meta['table'] = meta['table'].replace('Status', 'Log')

        logRes = self.insert(params, meta)

        return logRes

    ## Private methods ###########################################################

    def __createTables(self, tableName=None):
        '''
      Writes the schema in the database. If no tableName is given, all tables
      are written in the database. If a table is already in the schema, it is
      skipped to avoid problems trying to create a table that already exists.
    '''

        # Horrible SQL here !!
        tablesCreatedRes = self.database._query("show tables")
        if not tablesCreatedRes['OK']:
            return tablesCreatedRes
        tablesCreated = [
            tableCreated[0] for tableCreated in tablesCreatedRes['Value']
        ]

        tables = {}
        if tableName is None:
            tables.update(self._tableDict)

        elif tableName in self._tableDict:
            tables = {tableName: self._tableDict[tableName]}

        else:
            return S_ERROR('"%s" is not a known table' % tableName)

        for tableName in tablesCreated:
            if tableName in tables:
                del tables[tableName]

        res = self.database._createTables(tables)
        if not res['OK']:
            return res

        # Human readable S_OK message
        if res['Value'] == 0:
            res['Value'] = 'No tables created'
        else:
            res['Value'] = 'Tables created: %s' % (','.join(tables.keys()))
        return res

    def __generateTables(self):
        '''
      Method used to transform the class variables into instance variables,
      for safety reasons.
    '''

        # Avoids copying object.
        tables = {}
        tables.update(self._tablesDB)

        for tableName, tableLike in self._likeToTable.items():

            tables[tableName] = self._tablesLike[tableLike]

        return tables


################################################################################
#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF
예제 #8
0
class ResourceManagementDB:
  """ 
  The ResourceManagementDB class is a front-end to the Resource Management Database.
  
  The simplest way to instantiate an object of type :class:`ResourceManagementDB` 
  is simply by calling 

   >>> rpDB = ResourceManagementDB()

  This way, it will use the standard :mod:`DIRAC.Core.Base.DB`. 
  But there's the possibility to use other DB classes. 
  For example, we could pass custom DB instantiations to it, 
  provided the interface is the same exposed by :mod:`DIRAC.Core.Base.DB`.

   >>> AnotherDB = AnotherDBClass()
   >>> rmDB = ResourceManagementDB(DBin = AnotherDB)

  Alternatively, for testing purposes, you could do:

   >>> from DIRAC.ResourceStatusSystem.Utilities.mock import Mock
   >>> mockDB = Mock()
   >>> rmDB = ResourceManagementDB(DBin = mockDB)

  Or, if you want to work with a local DB, providing it's mySQL:

   >>> rmDB = ResourceManagementDB(DBin = ['UserName', 'Password'])

  """

  
  def __init__(self, *args, **kwargs):

    if len(args) == 1:
      if isinstance(args[0], str):
#        systemInstance=args[0]
        maxQueueSize=10
      if isinstance(args[0], int):
        maxQueueSize=args[0]
#        systemInstance='Default'
    elif len(args) == 2:
#      systemInstance=args[0]
      maxQueueSize=args[1]
    elif len(args) == 0:
#      systemInstance='Default'
      maxQueueSize=10
    
    if 'DBin' in kwargs.keys():
      DBin = kwargs['DBin']
      if isinstance(DBin, list):
        from DIRAC.Core.Utilities.MySQL import MySQL
        self.db = MySQL('localhost', DBin[0], DBin[1], 'ResourceManagementDB')
      else:
        self.db = DBin
    else:
      from DIRAC.Core.Base.DB import DB
      self.db = DB('ResourceManagementDB','ResourceStatus/ResourceManagementDB',maxQueueSize) 
#      self.db = DB('ResourceStatusDB','ResourceStatus/ResourceStatusDB',maxQueueSize)


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

#############################################################################
# Policy functions
#############################################################################

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

  def addOrModifyPolicyRes(self, granularity, name, policyName, 
                           status, reason, dateEffective = None):
    """
    Add or modify a Policy Result to the PolicyRes table.
    
    :params:
      :attr:`granularity`: string - a ValidRes
      see :mod:`DIRAC.ResourceStatusSystem.Utilities.Utils`
    
      :attr:`name`: string - name of the ValidRes
      
      :attr:`policyName`: string - the policy name
    
      :attr:`status`: string - a ValidStatus: 
      see :mod:`DIRAC.ResourceStatusSystem.Utilities.Utils`
      
      :attr:`reason`: string - free
      
      :attr:`dateEffective`: datetime.datetime - 
      date from which the result is effective
    """
    
    now = datetime.datetime.utcnow().replace(microsecond = 0).isoformat(' ')
    
    if dateEffective is None:
      dateEffective = now
    
    req = "SELECT Granularity, Name, PolicyName, Status, Reason FROM PolicyRes "
    req = req + "WHERE Granularity = '%s' AND Name = '%s' AND " %(granularity, name)
    req = req + "PolicyName = '%s'" %(policyName)
    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.addOrModifyPolicyRes) + resQuery['Message']

    if resQuery['Value']: 
      req = "UPDATE PolicyRes SET "
      if resQuery['Value'][0][3] != status:
        req = req + "Status = '%s', Reason = '%s', DateEffective = '%s', " %(status, reason, dateEffective)
      elif resQuery['Value'][0][4] != reason:
        req = req + "Reason = '%s', " %(reason)
      req = req + "LastCheckTime = '%s' WHERE Granularity = '%s' " %(now, granularity)
      req = req + "AND Name = '%s' AND PolicyName = '%s'" %(name, policyName)
      
      resUpdate = self.db._update(req)
      if not resUpdate['OK']:
        raise RSSManagementDBException, where(self, self.addOrModifyPolicyRes) + resUpdate['Message']
    else:
      req = "INSERT INTO PolicyRes (Granularity, Name, PolicyName, Status, Reason, DateEffective, "
      req = req + "LastCheckTime) VALUES ('%s', '%s', '%s', " %(granularity, name, policyName)
      req = req + "'%s', '%s', '%s', '%s')" %(status, reason, dateEffective, now)
      resUpdate = self.db._update(req)
      if not resUpdate['OK']:
        raise RSSManagementDBException, where(self, self.addOrModifyPolicyRes) + resUpdate['Message']
    
#############################################################################

  def getPolicyRes(self, name, policyName, lastCheckTime = False):
    """ 
    Get a Policy Result from the PolicyRes table.
    
    :params:
      :attr:`name`: string - name of the ValidRes
      
      :attr:`policyName`: string - the policy name
      
      :attr:`lastCheckTime`: optional - if TRUE, it will get also the 
      LastCheckTime 
    """
    
    req = "SELECT Status, Reason"
    if lastCheckTime:
      req = req + ", LastCheckTime"  
    req = req + " FROM PolicyRes WHERE"
    req = req + " Name = '%s' AND PolicyName = '%s'" %(name, policyName)

    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.getPolicyRes) + resQuery['Message']
    if not resQuery['Value']:
      return []
    
    return resQuery['Value'][0]
    
#############################################################################

#############################################################################
# ClientsCache functions
#############################################################################
  
#############################################################################
  
  def addOrModifyClientsCacheRes(self, name, commandName, value, result, 
                                 opt_ID = None, dateEffective = None):
    """
    Add or modify a Client Result to the ClientCache table.
    
    :params:
      :attr:`name`: string - name of the ValidRes
      
      :attr:`commandName`: string - the command name
    
      :attr:`value`: string - the value
    
      :attr:`result`: string - command result
      
      :attr:`opt_ID`: string or integer - optional ID (e.g. used for downtimes)
      
      :attr:`dateEffective`: datetime.datetime - 
      date from which the result is effective
    """
    
    now = datetime.datetime.utcnow().replace(microsecond = 0).isoformat(' ')
    
    if dateEffective is None:
      dateEffective = now
    
    if opt_ID is not None:
      if isinstance(opt_ID, int):
        opt_ID = str(opt_ID)
    
    req = "SELECT Name, CommandName, "
    if opt_ID is not None:
      req = req + "Opt_ID, "
    req = req + "Value, Result FROM ClientsCache WHERE "
    req = req + "Name = '%s' AND CommandName = '%s' " %(name, commandName)
    if opt_ID is not None:
      req = req + "AND Opt_ID = '%s' " %opt_ID
    req = req + "AND Value = '%s' " %value
    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.addOrModifyClientsCacheRes) + resQuery['Message']

    if resQuery['Value']: 
      req = "UPDATE ClientsCache SET "
      if resQuery['Value'][0][3] != result:
        req = req + "Result = '%s', DateEffective = '%s', " %(result, dateEffective)
      req = req + "LastCheckTime = '%s' WHERE " %(now)
      req = req + "Name = '%s' AND CommandName = '%s' AND Value = '%s'" %(name, commandName, value)
      if opt_ID is not None:
        req = req + "AND Opt_ID = '%s' " %opt_ID
      
      resUpdate = self.db._update(req)
      if not resUpdate['OK']:
        raise RSSManagementDBException, where(self, self.addOrModifyClientsCacheRes) + resUpdate['Message']
    else:
      req = "INSERT INTO ClientsCache (Name, CommandName, "
      if opt_ID is not None:
        req = req + "Opt_ID, "
      req = req + "Value, Result, DateEffective, "
      req = req + "LastCheckTime) VALUES ('%s', '%s', " %(name, commandName)
      if opt_ID is not None:
        req = req + "'%s', " %opt_ID
      req = req + "'%s', '%s', '%s', '%s')" %(value, result, dateEffective, now)
      
      resUpdate = self.db._update(req)
      if not resUpdate['OK']:
        raise RSSManagementDBException, where(self, self.addOrModifyClientsCacheRes) + resUpdate['Message']
    
#############################################################################

  def getClientsCacheStuff(self, paramsList = None, ccID = None, name = None, commandName = None,
                           opt_ID = None, value = None, result = None, dateEffective = None, 
                           lastCheckTime = None):
    """
    Generic function to get values from the ClientsCache table.
    
    :params:
      :attr:`paramsList` - string or list of strings
    
      :attr:`ccID` - string or list of strings
    
      :attr:`name` - string or list of strings
    
      :attr:`commandName` - string or list of strings
    
      :attr:`opt_ID` - string or list of strings
    
      :attr:`value` - string or list of strings
    
      :attr:`result` - string or list of strings
    
      :attr:`dateEffective` - string or list of strings
    
      :attr:`lastCheckTime` - string or list of strings
    """
    
    if (paramsList == None or paramsList == []):
      params = "ccID, Name, CommandName, Opt_ID, Value, Result, DateEffective "
    else:
      if type(paramsList) is not type([]):
        paramsList = [paramsList]
      params = ','.join([x.strip()+' ' for x in paramsList])
      
    req = "SELECT " + params + "FROM ClientsCache "
    
    if not (ccID == name == commandName == opt_ID == value == 
            result == dateEffective == lastCheckTime == None):
      req = req + "WHERE "
    
    if ccID is not None:
      if type(ccID) is not type([]):
        ccID = [ccID]
      req = req + "ccID IN (" + ','.join([str(x).strip() + ' ' for x in ccID]) + ")"
    
    if name is not None:
      if ccID is not None:
        req = req + " AND "
      if type(name) is not type([]):
        name = [name]
      req = req + "Name IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in name]) + ")"
    
    if commandName is not None:
      if ccID is not None or name is not None:
        req = req + " AND "
      if type(commandName) is not type([]):
        commandName = [commandName]
      req = req + "CommandName IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in commandName]) + ")"
    
    if opt_ID is not None:
      if ccID is not None or name is not None or commandName is not None:
        req = req + " AND "
      if type(opt_ID) is not type([]):
        opt_ID = [opt_ID]
      req = req + "Opt_ID IN (" + ','.join(['"' + str(x).strip() + '"' + ' ' for x in opt_ID]) + ")"
    
    if value is not None:
      if ccID is not None or name is not None or commandName is not None or opt_ID is not None:
        req = req + " AND "
      if type(value) is not type([]):
        value = [value]
      req = req + "Value IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in value]) + ")"
    
    if result is not None:
      if (ccID is not None or name is not None or commandName is not None or opt_ID is not None or value is not None):
        req = req + " AND "
      if type(result) is not type([]):
        result = [result]
      req = req + "result IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in result]) + ")"
    
    if dateEffective is not None:
      if (ccID is not None or name is not None or commandName is not None or opt_ID is not None or value is not None or result is not None):
        req = req + " AND "
      if type(dateEffective) is not type([]):
        dateEffective = [dateEffective]
      req = req + "dateEffective IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in dateEffective]) + ")"
    
    if lastCheckTime is not None:
      if (ccID is not None or name is not None or commandName is not None or opt_ID is not None or value is not None or result is not None or dateEffective is not None):
        req = req + " AND "
      if type(lastCheckTime) is not type([]):
        lastCheckTime = [lastCheckTime]
      req = req + "lastCheckTime IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in lastCheckTime]) + ")"
    
    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.getClientsCacheStuff) + resQuery['Message']
    if not resQuery['Value']:
      return []
    
    return resQuery['Value']

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

#############################################################################
# AccountingCache functions
#############################################################################

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

  def addOrModifyAccountingCacheRes(self, name, plotType, plotName, result, dateEffective = None):
    """
    Add or modify an Accounting Result to the AccountingCache table.
    
    :params:
      :attr:`name`: string - name of the ValidRes
      
      :attr:`plotType`: string - the plotType name (e.g. 'Pilot')
    
      :attr:`plotName`: string - the plot name
    
      :attr:`result`: string - command result
      
      :attr:`dateEffective`: datetime.datetime - 
      date from which the result is effective
    """
    
    now = datetime.datetime.utcnow().replace(microsecond = 0).isoformat(' ')
    
    if dateEffective is None:
      dateEffective = now
    
    req = "SELECT Name, PlotType, PlotName, Result FROM AccountingCache WHERE "
    req = req + "Name = '%s' AND PlotType = '%s' AND PlotName = '%s' " %(name, plotType, plotName)
    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.addOrModifyAccountingCacheRes) + resQuery['Message']

    if resQuery['Value']: 
      req = "UPDATE AccountingCache SET "
      if resQuery['Value'][0][3] != result:
        req = req + "Result = \"%s\", DateEffective = '%s', " %(result, dateEffective)
      req = req + "LastCheckTime = '%s' WHERE " %(now)
      req = req + "Name = '%s' AND PlotType = '%s' AND PlotName = '%s'" %(name, plotType, plotName)
      
      resUpdate = self.db._update(req)
      if not resUpdate['OK']:
        raise RSSManagementDBException, where(self, self.addOrModifyAccountingCacheRes) + resUpdate['Message']
    else:
      req = "INSERT INTO AccountingCache (Name, PlotType, PlotName, Result, DateEffective, "
      req = req + "LastCheckTime) VALUES ('%s', '%s', '%s', " %(name, plotType, plotName)
      req = req + "\"%s\", '%s', '%s')" %(result, dateEffective, now)
      
      resUpdate = self.db._update(req)
      if not resUpdate['OK']:
        raise RSSManagementDBException, where(self, self.addOrModifyAccountingCacheRes) + resUpdate['Message']
    
#############################################################################

  def getAccountingCacheStuff(self, paramsList = None, acID = None, name = None, plotType = None, 
                              plotName = None, result = None, dateEffective = None, 
                              lastCheckTime = None):
    """
    Generic function to get values from the AccountingCache table.
    
    :params:
      :attr:`paramsList` - string or list of strings
    
      :attr:`acID` - string or list of strings
    
      :attr:`name` - string or list of strings
    
      :attr:`plotName` - string or list of strings
    
      :attr:`result` - string or list of strings
    
      :attr:`dateEffective` - string or list of strings
    
      :attr:`lastCheckTime` - string or list of strings
    """
    if (paramsList == None or paramsList == []):
      params = "acID, Name, PlotType, PlotName, Result, DateEffective "
    else:
      if type(paramsList) != type([]):
        paramsList = [paramsList]
      params = ','.join([x.strip()+' ' for x in paramsList])
      
    req = "SELECT " + params + "FROM AccountingCache "
    
    if not (acID == name == plotType == plotName == result == dateEffective == lastCheckTime == None):
      req = req + "WHERE "
    
    if acID is not None:
      if type(acID) is not type([]):
        acID = [acID]
      req = req + "acID IN (" + ','.join([str(x).strip() + ' ' for x in acID]) + ")"
    
    if name is not None:
      if acID is not None:
        req = req + " AND "
      if type(name) is not type([]):
        name = [name]
      req = req + "Name IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in name]) + ")"
    
    if plotName is not None:
      if acID is not None or name is not None:
        req = req + " AND "
      if type(plotName) is not type([]):
        plotName = [plotName]
      req = req + "PlotName IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in plotName]) + ")"
    
    if plotType is not None:
      if acID is not None or name is not None or plotName is not None:
        req = req + " AND "
      if type(plotType) is not type([]):
        plotType = [plotType]
      req = req + "PlotType IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in plotType]) + ")"
    
    if result is not None:
      if (acID is not None or name is not None or plotName is not None or plotType is not None):
        req = req + " AND "
      if type(result) is not type([]):
        result = [result]
      req = req + "Result IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in result]) + ")"
    
    if dateEffective is not None:
      if (acID is not None or name is not None or plotName is not None or plotType is not None or result is not None):
        req = req + " AND "
      if type(dateEffective) is not type([]):
        dateEffective = [dateEffective]
      req = req + "DateEffective IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in dateEffective]) + ")"
    
    if lastCheckTime is not None:
      if (acID is not None or name is not None or plotName is not None or plotType is not None or result is not None or dateEffective is not None):
        req = req + " AND "
      if type(lastCheckTime) is not type([]):
        lastCheckTime = [lastCheckTime]
      req = req + "LastCheckTime IN (" + ','.join(['"' + x.strip() + '"' + ' ' for x in lastCheckTime]) + ")"
    
    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.getAccountingCacheStuff) + resQuery['Message']
    if not resQuery['Value']:
      return []
    
    return resQuery['Value']

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

#############################################################################
# Status functions
#############################################################################

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

  #usata solo nell'handler
  def addStatus(self, status, description=''):
    """ 
    Add a status.
    
    :params:
      :attr:`status`: string - a new status
      
      :attr:`description`: string - optional description
    """

    req = "INSERT INTO Status (Status, Description)"
    req = req + "VALUES ('%s', '%s');" % (status, description)

    resUpdate = self.db._update(req)
    if not resUpdate['OK']:
      raise RSSManagementDBException, where(self, self.addStatus) + resUpdate['Message']

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

  #usata solo nell'handler
  def removeStatus(self, status):
    """ 
    Remove a status from the Status table.
    
    :params:
      :attr:`status`: string - status
    """

    req = "DELETE from Status WHERE Status = '%s';" % (status)
    resDel = self.db._update(req)
    if not resDel['OK']:
      raise RSSManagementDBException, where(self, self.removeStatus) + resDel['Message']

#############################################################################
  
  def getStatusList(self):
    """ 
    Get list of status with no descriptions.
    """

    req = "SELECT Status from Status"

    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, where(self, self.getStatusList) + resQuery['Message']
    if not resQuery['Value']:
      return []
    l = [ x[0] for x in resQuery['Value']]
    return l
      
#############################################################################      
# Web functions      
#############################################################################
      
#############################################################################

  def getDownTimesWeb(self, selectDict, sortList = [], startItem = 0, maxItems = 1000):
    """
    Get downtimes registered in the RSS DB (with a web layout)

    :params:
      :attr:`selectDict`: { 'Granularity':['Site', 'Resource'], 'Severity': ['OUTAGE', 'AT_RISK']}
            
      :attr:`sortList` 
      
      :attr:`startItem` 
      
      :attr:`maxItems`
    """
    
    granularity = selectDict['Granularity']
    severity = selectDict['Severity']
    
    if not isinstance(granularity, list):
      granularity = [granularity]
    if not isinstance(severity, list):
      severity = [severity]
    
    paramNames = ['Granularity', 'Name', 'Severity', 'When']
    
    req = "SELECT Granularity, Name, Reason FROM PolicyRes WHERE "
    req = req + "PolicyName LIKE 'DT_%' AND Reason LIKE \'%found%\' "
    req = req + "AND Granularity in (%s)" %(','.join(['"'+x.strip()+'"' for x in granularity]))
    resQuery = self.db._query(req)
    if not resQuery['OK']:
      raise RSSManagementDBException, resQuery['Message']
    if not resQuery['Value']:
      records = []
    else:
      resQuery = resQuery['Value']
      records = []
      for tuple in resQuery:
        sev = tuple[2].split()[2]
        if sev not in severity: 
          continue
        when = tuple[2].split(sev)[1][1:]
        if when == '':
          when = 'Ongoing'
        records.append([tuple[0], tuple[1], sev, when])
    
    finalDict = {}
    finalDict['TotalRecords'] = len(records)
    finalDict['ParameterNames'] = paramNames

    # Return all the records if maxItems == 0 or the specified number otherwise
    if maxItems:
      finalDict['Records'] = records[startItem:startItem+maxItems]
    else:
      finalDict['Records'] = records

    finalDict['Extras'] = None
 
    return finalDict
 
#############################################################################
예제 #9
0
class ResourceManagementDB(object):
    '''
    Class that defines the tables for the ResourceManagementDB on a python dictionary.
  '''

    # Written PrimaryKey as list on purpose !!
    _tablesDB = {}
    _tablesDB['AccountingCache'] = {
        'Fields': {
            #'AccountingCacheID' : 'INT UNSIGNED AUTO_INCREMENT NOT NULL',
            'Name': 'VARCHAR(64) NOT NULL',
            'PlotType': 'VARCHAR(16) NOT NULL',
            'PlotName': 'VARCHAR(64) NOT NULL',
            'Result': 'TEXT NOT NULL',
            'DateEffective': 'DATETIME NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['Name', 'PlotType', 'PlotName']
    }

    _tablesDB['DowntimeCache'] = {
        'Fields': {
            'DowntimeID': 'VARCHAR(64) NOT NULL',
            'Element': 'VARCHAR(32) NOT NULL',
            'Name': 'VARCHAR(64) NOT NULL',
            'StartDate': 'DATETIME NOT NULL',
            'EndDate': 'DATETIME NOT NULL',
            'Severity': 'VARCHAR(32) NOT NULL',
            'Description': 'VARCHAR(512) NOT NULL',
            'Link': 'VARCHAR(255) NOT NULL',
            'DateEffective': 'DATETIME NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['DowntimeID']
    }

    _tablesDB['GGUSTicketsCache'] = {
        'Fields': {
            'GocSite': 'VARCHAR(64) NOT NULL',
            'Link': 'VARCHAR(1024) NOT NULL',
            'OpenTickets': 'INTEGER NOT NULL DEFAULT 0',
            'Tickets': 'VARCHAR(1024) NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['GocSite']
    }

    _tablesDB['JobCache'] = {
        'Fields': {
            'Site': 'VARCHAR(64) NOT NULL',
            'Timespan': 'INTEGER NOT NULL',
            'Checking': 'INTEGER NOT NULL DEFAULT 0',
            'Completed': 'INTEGER NOT NULL DEFAULT 0',
            'Done': 'INTEGER NOT NULL DEFAULT 0',
            'Failed': 'INTEGER NOT NULL DEFAULT 0',
            'Killed': 'INTEGER NOT NULL DEFAULT 0',
            'Matched': 'INTEGER NOT NULL DEFAULT 0',
            'Received': 'INTEGER NOT NULL DEFAULT 0',
            'Running': 'INTEGER NOT NULL DEFAULT 0',
            'Staging': 'INTEGER NOT NULL DEFAULT 0',
            'Stalled': 'INTEGER NOT NULL DEFAULT 0',
            'Waiting': 'INTEGER NOT NULL DEFAULT 0',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['Site', 'Timespan']
    }

    _tablesDB['PilotCache'] = {
        'Fields': {
            'CE': 'VARCHAR(64) NOT NULL',
            'Timespan': 'INTEGER NOT NULL',
            'Scheduled': 'INTEGER NOT NULL DEFAULT 0',
            'Waiting': 'INTEGER NOT NULL DEFAULT 0',
            'Submitted': 'INTEGER NOT NULL DEFAULT 0',
            'Running': 'INTEGER NOT NULL DEFAULT 0',
            'Done': 'INTEGER NOT NULL DEFAULT 0',
            'Aborted': 'INTEGER NOT NULL DEFAULT 0',
            'Cancelled': 'INTEGER NOT NULL DEFAULT 0',
            'Deleted': 'INTEGER NOT NULL DEFAULT 0',
            'Failed': 'INTEGER NOT NULL DEFAULT 0',
            'Held': 'INTEGER NOT NULL DEFAULT 0',
            'Killed': 'INTEGER NOT NULL DEFAULT 0',
            'Stalled': 'INTEGER NOT NULL DEFAULT 0',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['CE', 'Timespan']
    }

    _tablesDB['PolicyResult'] = {
        'Fields': {
            'Element': 'VARCHAR(32) NOT NULL',
            'Name': 'VARCHAR(64) NOT NULL',
            'PolicyName': 'VARCHAR(64) NOT NULL',
            'StatusType': 'VARCHAR(16) NOT NULL DEFAULT ""',
            'Status': 'VARCHAR(16) NOT NULL',
            'Reason': 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
            'DateEffective': 'DATETIME NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['Element', 'Name', 'StatusType', 'PolicyName']
    }

    _tablesDB['SpaceTokenOccupancyCache'] = {
        'Fields': {
            'Endpoint': 'VARCHAR( 64 ) NOT NULL',
            'Token': 'VARCHAR( 64 ) NOT NULL',
            'Total': 'DOUBLE NOT NULL DEFAULT 0',
            'Guaranteed': 'DOUBLE NOT NULL DEFAULT 0',
            'Free': 'DOUBLE NOT NULL DEFAULT 0',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['Endpoint', 'Token']
    }

    _tablesDB['TransferCache'] = {
        'Fields': {
            'SourceName': 'VARCHAR( 64 ) NOT NULL',
            'DestinationName': 'VARCHAR( 64 ) NOT NULL',
            'Metric': 'VARCHAR( 16 ) NOT NULL',
            'Value': 'DOUBLE NOT NULL DEFAULT 0',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['SourceName', 'DestinationName', 'Metric']
    }

    _tablesDB['UserRegistryCache'] = {
        'Fields': {
            'Login': '******',
            'Name': 'VARCHAR(64) NOT NULL',
            'Email': 'VARCHAR(64) NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['Login']
    }

    _tablesDB['VOBOXCache'] = {
        'Fields': {
            'Site': 'VARCHAR( 64 ) NOT NULL',
            'System': 'VARCHAR( 64 ) NOT NULL',
            'ServiceUp': 'INTEGER NOT NULL DEFAULT 0',
            'MachineUp': 'INTEGER NOT NULL DEFAULT 0',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['Site', 'System']
    }

    _tablesDB['ErrorReportBuffer'] = {
        'Fields': {
            'ID': 'INT UNSIGNED AUTO_INCREMENT NOT NULL',
            'Name': 'VARCHAR(64) NOT NULL',
            'ElementType': 'VARCHAR(32) NOT NULL',
            'Reporter': 'VARCHAR(64) NOT NULL',
            'ErrorMessage': 'VARCHAR(512) NOT NULL',
            'Operation': 'VARCHAR(64) NOT NULL',
            'Arguments': 'VARCHAR(512) NOT NULL DEFAULT ""',
            'DateEffective': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['ID']
    }

    _tablesLike = {}
    _tablesLike['PolicyResultWithID'] = {
        'Fields': {
            'ID': 'INT UNSIGNED AUTO_INCREMENT NOT NULL',
            'Element': 'VARCHAR(32) NOT NULL',
            'Name': 'VARCHAR(64) NOT NULL',
            'PolicyName': 'VARCHAR(64) NOT NULL',
            'StatusType': 'VARCHAR(16) NOT NULL DEFAULT ""',
            'Status': 'VARCHAR(8) NOT NULL',
            'Reason': 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
            'DateEffective': 'DATETIME NOT NULL',
            'LastCheckTime': 'DATETIME NOT NULL'
        },
        'PrimaryKey': ['ID']
    }
    _likeToTable = {
        'PolicyResultLog': 'PolicyResultWithID',
        'PolicyResultHistory': 'PolicyResultWithID',
    }

    def __init__(self, maxQueueSize=10, mySQL=None):
        '''
      Constructor, accepts any DB or mySQL connection, mostly used for testing
      purposes.
    '''
        self._tableDict = self.__generateTables()

        if mySQL is not None:
            self.database = mySQL
        else:
            self.database = DB('ResourceManagementDB',
                               'ResourceStatus/ResourceManagementDB',
                               maxQueueSize)

    ## SQL Methods ###############################################################

    def insert(self, params, meta):
        '''
    Inserts args in the DB making use of kwargs where parameters such as
    the 'table' are specified ( filled automatically by the Client). Typically you 
    will not pass kwargs to this function, unless you know what are you doing 
    and you have a very special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        utcnow = datetime.utcnow().replace(microsecond=0)

        # We force lastCheckTime to utcnow if it is not present on the params
        #if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
        if 'lastCheckTime' in params and params['lastCheckTime'] is None:
            params['lastCheckTime'] = utcnow

        if 'dateEffective' in params and params['dateEffective'] is None:
            params['dateEffective'] = utcnow

        return MySQLWrapper.insert(self, params, meta)

    def update(self, params, meta):
        '''
    Updates row with values given on args. The row selection is done using the
    default of MySQLMonkey ( column.primary or column.keyColumn ). It can be
    modified using kwargs. The 'table' keyword argument is mandatory, and 
    filled automatically by the Client. Typically you will not pass kwargs to 
    this function, unless you know what are you doing and you have a very 
    special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        # We force lastCheckTime to utcnow if it is not present on the params
        #if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
        if 'lastCheckTime' in params and params['lastCheckTime'] is None:
            params['lastCheckTime'] = datetime.utcnow().replace(microsecond=0)

        return MySQLWrapper.update(self, params, meta)

    def select(self, params, meta):
        '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        return MySQLWrapper.select(self, params, meta)

    def delete(self, params, meta):
        '''
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query. 
    There is only one forbidden query, with all parameters None ( this would 
    mean a query of the type `DELETE * from TableName` ). The usage of kwargs 
    is the same as in the get function.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''
        return MySQLWrapper.delete(self, params, meta)

    ## Extended SQL methods ######################################################

    def addOrModify(self, params, meta):
        '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        selectQuery = self.select(params, meta)
        if not selectQuery['OK']:
            return selectQuery

        isUpdate = False

        if selectQuery['Value']:

            # Pseudo - code
            # for all column not being PrimaryKey and not a time column:
            #   if one or more column different than params if not None:
            #     we update dateTime as well

            columns = selectQuery['Columns']
            values = selectQuery['Value']

            if len(values) != 1:
                return S_ERROR(
                    'More than one value returned on addOrModify, please report !!'
                )

            selectDict = dict(zip(columns, values[0]))

            newDateEffective = None

            for key, value in params.items():
                if key in ('lastCheckTime', 'dateEffective'):
                    continue

                if value is None:
                    continue

                if value != selectDict[key[0].upper() + key[1:]]:
                    newDateEffective = datetime.utcnow().replace(microsecond=0)
                    break

            if 'dateEffective' in params:
                params['dateEffective'] = newDateEffective

            userQuery = self.update(params, meta)
            isUpdate = True

        else:
            userQuery = self.insert(params, meta)

        # This part only applies to PolicyResult table
        logResult = self._logRecord(params, meta, isUpdate)
        if not logResult['OK']:
            return logResult

        return userQuery

    # FIXME: this method looks unused. Maybe can be removed from the code.
    def addIfNotThere(self, params, meta):
        '''
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is not there, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    '''

        selectQuery = self.select(params, meta)
        if not selectQuery['OK']:
            return selectQuery

        if selectQuery['Value']:
            return selectQuery

        return self.insert(params, meta)

    ## Auxiliar methods ##########################################################

    def getTable(self, tableName):
        '''
      Returns a table dictionary description given its name 
    '''
        if tableName in self._tableDict:
            return S_OK(self._tableDict[tableName])

        return S_ERROR('%s is not on the schema' % tableName)

    def getTablesList(self):
        '''
      Returns a list of the table names in the schema.
    '''
        return S_OK(self._tableDict.keys())

    ## Protected methods #########################################################

    def _checkTable(self):
        '''
      Method used by database tools to write the schema
    '''
        return self.__createTables()

    def _logRecord(self, params, meta, isUpdate):
        '''
      Method that records every change on a LogTable.
    '''

        if not ('table' in meta and meta['table'] == 'PolicyResult'):
            return S_OK()

        if isUpdate:

            # This looks little bit like a non-sense. If we were updating, we may have
            # not passed a complete set of parameters, so we have to get all them from the
            # database :/. It costs us one more query.
            updateRes = self.select(params, meta)
            if not updateRes['OK']:
                return updateRes

            params = dict(zip(updateRes['Columns'], updateRes['Value'][0]))

        # Writes to PolicyResult"Log"
        meta['table'] += 'Log'

        logRes = self.insert(params, meta)

        return logRes

    ## Private methods ###########################################################

    def __createTables(self, tableName=None):
        '''
      Writes the schema in the database. If no tableName is given, all tables
      are written in the database. If a table is already in the schema, it is
      skipped to avoid problems trying to create a table that already exists.
    '''

        # Horrible SQL here !!
        tablesCreatedRes = self.database._query("show tables")
        if not tablesCreatedRes['OK']:
            return tablesCreatedRes
        tablesCreated = [
            tableCreated[0] for tableCreated in tablesCreatedRes['Value']
        ]

        tables = {}
        if tableName is None:
            tables.update(self._tableDict)

        elif tableName in self._tableDict:
            tables = {tableName: self._tableDict[tableName]}

        else:
            return S_ERROR('"%s" is not a known table' % tableName)

        for tableName in tablesCreated:
            if tableName in tables:
                del tables[tableName]

        res = self.database._createTables(tables)
        if not res['OK']:
            return res

        # Human readable S_OK message
        if res['Value'] == 0:
            res['Value'] = 'No tables created'
        else:
            res['Value'] = 'Tables created: %s' % (','.join(tables.keys()))
        return res

    def __generateTables(self):
        '''
      Method used to transform the class variables into instance variables,
      for safety reasons.
    '''

        # Avoids copying object.
        tables = {}
        tables.update(self._tablesDB)

        for tableName, tableLike in self._likeToTable.items():

            tables[tableName] = self._tablesLike[tableLike]

        return tables


################################################################################
#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF
예제 #10
0
class ResourceManagementDB(object):
    """
    Class that defines the tables for the ResourceManagementDB on a python dictionary.
  """

    # Written PrimaryKey as list on purpose !!
    _tablesDB = {}
    _tablesDB["AccountingCache"] = {
        "Fields": {
            #'AccountingCacheID' : 'INT UNSIGNED AUTO_INCREMENT NOT NULL',
            "Name": "VARCHAR(64) NOT NULL",
            "PlotType": "VARCHAR(16) NOT NULL",
            "PlotName": "VARCHAR(64) NOT NULL",
            "Result": "TEXT NOT NULL",
            "DateEffective": "DATETIME NOT NULL",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["Name", "PlotType", "PlotName"],
    }

    _tablesDB["DowntimeCache"] = {
        "Fields": {
            "DowntimeID": "VARCHAR(64) NOT NULL",
            "Element": "VARCHAR(32) NOT NULL",
            "Name": "VARCHAR(64) NOT NULL",
            "StartDate": "DATETIME NOT NULL",
            "EndDate": "DATETIME NOT NULL",
            "Severity": "VARCHAR(32) NOT NULL",
            "Description": "VARCHAR(512) NOT NULL",
            "Link": "VARCHAR(255) NOT NULL",
            "DateEffective": "DATETIME NOT NULL",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["DowntimeID"],
    }

    _tablesDB["GGUSTicketsCache"] = {
        "Fields": {
            "GocSite": "VARCHAR(64) NOT NULL",
            "Link": "VARCHAR(1024) NOT NULL",
            "OpenTickets": "INTEGER NOT NULL DEFAULT 0",
            "Tickets": "VARCHAR(1024) NOT NULL",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["GocSite"],
    }

    _tablesDB["JobCache"] = {
        "Fields": {
            "Site": "VARCHAR(64) NOT NULL",
            "Timespan": "INTEGER NOT NULL",
            "Checking": "INTEGER NOT NULL DEFAULT 0",
            "Completed": "INTEGER NOT NULL DEFAULT 0",
            "Done": "INTEGER NOT NULL DEFAULT 0",
            "Failed": "INTEGER NOT NULL DEFAULT 0",
            "Killed": "INTEGER NOT NULL DEFAULT 0",
            "Matched": "INTEGER NOT NULL DEFAULT 0",
            "Received": "INTEGER NOT NULL DEFAULT 0",
            "Running": "INTEGER NOT NULL DEFAULT 0",
            "Staging": "INTEGER NOT NULL DEFAULT 0",
            "Stalled": "INTEGER NOT NULL DEFAULT 0",
            "Waiting": "INTEGER NOT NULL DEFAULT 0",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["Site", "Timespan"],
    }

    _tablesDB["PilotCache"] = {
        "Fields": {
            "CE": "VARCHAR(64) NOT NULL",
            "Timespan": "INTEGER NOT NULL",
            "Scheduled": "INTEGER NOT NULL DEFAULT 0",
            "Waiting": "INTEGER NOT NULL DEFAULT 0",
            "Submitted": "INTEGER NOT NULL DEFAULT 0",
            "Running": "INTEGER NOT NULL DEFAULT 0",
            "Done": "INTEGER NOT NULL DEFAULT 0",
            "Aborted": "INTEGER NOT NULL DEFAULT 0",
            "Cancelled": "INTEGER NOT NULL DEFAULT 0",
            "Deleted": "INTEGER NOT NULL DEFAULT 0",
            "Failed": "INTEGER NOT NULL DEFAULT 0",
            "Held": "INTEGER NOT NULL DEFAULT 0",
            "Killed": "INTEGER NOT NULL DEFAULT 0",
            "Stalled": "INTEGER NOT NULL DEFAULT 0",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["CE", "Timespan"],
    }

    _tablesDB["PolicyResult"] = {
        "Fields": {
            "Element": "VARCHAR(32) NOT NULL",
            "Name": "VARCHAR(64) NOT NULL",
            "PolicyName": "VARCHAR(64) NOT NULL",
            "StatusType": 'VARCHAR(16) NOT NULL DEFAULT ""',
            "Status": "VARCHAR(16) NOT NULL",
            "Reason": 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
            "DateEffective": "DATETIME NOT NULL",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["Element", "Name", "StatusType", "PolicyName"],
    }

    _tablesDB["SpaceTokenOccupancyCache"] = {
        "Fields": {
            "Endpoint": "VARCHAR( 64 ) NOT NULL",
            "Token": "VARCHAR( 64 ) NOT NULL",
            "Total": "DOUBLE NOT NULL DEFAULT 0",
            "Guaranteed": "DOUBLE NOT NULL DEFAULT 0",
            "Free": "DOUBLE NOT NULL DEFAULT 0",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["Endpoint", "Token"],
    }

    _tablesDB["TransferCache"] = {
        "Fields": {
            "SourceName": "VARCHAR( 64 ) NOT NULL",
            "DestinationName": "VARCHAR( 64 ) NOT NULL",
            "Metric": "VARCHAR( 16 ) NOT NULL",
            "Value": "DOUBLE NOT NULL DEFAULT 0",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["SourceName", "DestinationName", "Metric"],
    }

    _tablesDB["UserRegistryCache"] = {
        "Fields": {
            "Login": "******",
            "Name": "VARCHAR(64) NOT NULL",
            "Email": "VARCHAR(64) NOT NULL",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["Login"],
    }

    _tablesDB["VOBOXCache"] = {
        "Fields": {
            "Site": "VARCHAR( 64 ) NOT NULL",
            "System": "VARCHAR( 64 ) NOT NULL",
            "ServiceUp": "INTEGER NOT NULL DEFAULT 0",
            "MachineUp": "INTEGER NOT NULL DEFAULT 0",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["Site", "System"],
    }

    _tablesDB["ErrorReportBuffer"] = {
        "Fields": {
            "ID": "INT UNSIGNED AUTO_INCREMENT NOT NULL",
            "Name": "VARCHAR(64) NOT NULL",
            "ElementType": "VARCHAR(32) NOT NULL",
            "Reporter": "VARCHAR(64) NOT NULL",
            "ErrorMessage": "VARCHAR(512) NOT NULL",
            "Operation": "VARCHAR(64) NOT NULL",
            "Arguments": 'VARCHAR(512) NOT NULL DEFAULT ""',
            "DateEffective": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["ID"],
    }

    _tablesLike = {}
    _tablesLike["PolicyResultWithID"] = {
        "Fields": {
            "ID": "INT UNSIGNED AUTO_INCREMENT NOT NULL",
            "Element": "VARCHAR(32) NOT NULL",
            "Name": "VARCHAR(64) NOT NULL",
            "PolicyName": "VARCHAR(64) NOT NULL",
            "StatusType": 'VARCHAR(16) NOT NULL DEFAULT ""',
            "Status": "VARCHAR(8) NOT NULL",
            "Reason": 'VARCHAR(512) NOT NULL DEFAULT "Unspecified"',
            "DateEffective": "DATETIME NOT NULL",
            "LastCheckTime": "DATETIME NOT NULL",
        },
        "PrimaryKey": ["ID"],
    }
    _likeToTable = {"PolicyResultLog": "PolicyResultWithID", "PolicyResultHistory": "PolicyResultWithID"}

    def __init__(self, maxQueueSize=10, mySQL=None):
        """
      Constructor, accepts any DB or mySQL connection, mostly used for testing
      purposes.
    """
        self._tableDict = self.__generateTables()

        if mySQL is not None:
            self.database = mySQL
        else:
            self.database = DB("ResourceManagementDB", "ResourceStatus/ResourceManagementDB", maxQueueSize)

    ## SQL Methods ###############################################################

    def insert(self, params, meta):
        """
    Inserts args in the DB making use of kwargs where parameters such as
    the 'table' are specified ( filled automatically by the Client). Typically you 
    will not pass kwargs to this function, unless you know what are you doing 
    and you have a very special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

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

        utcnow = datetime.utcnow().replace(microsecond=0)

        # We force lastCheckTime to utcnow if it is not present on the params
        # if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
        if "lastCheckTime" in params and params["lastCheckTime"] is None:
            params["lastCheckTime"] = utcnow

        if "dateEffective" in params and params["dateEffective"] is None:
            params["dateEffective"] = utcnow

        return MySQLWrapper.insert(self, params, meta)

    def update(self, params, meta):
        """
    Updates row with values given on args. The row selection is done using the
    default of MySQLMonkey ( column.primary or column.keyColumn ). It can be
    modified using kwargs. The 'table' keyword argument is mandatory, and 
    filled automatically by the Client. Typically you will not pass kwargs to 
    this function, unless you know what are you doing and you have a very 
    special use case.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

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

        # We force lastCheckTime to utcnow if it is not present on the params
        # if not( 'lastCheckTime' in params and not( params[ 'lastCheckTime' ] is None ) ):
        if "lastCheckTime" in params and params["lastCheckTime"] is None:
            params["lastCheckTime"] = datetime.utcnow().replace(microsecond=0)

        return MySQLWrapper.update(self, params, meta)

    def select(self, params, meta):
        """
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    """
        return MySQLWrapper.select(self, params, meta)

    def delete(self, params, meta):
        """
    Uses arguments to build conditional SQL statement ( WHERE ... ). If the
    sql statement desired is more complex, you can use kwargs to interact with
    the MySQL buildCondition parser and generate a more sophisticated query. 
    There is only one forbidden query, with all parameters None ( this would 
    mean a query of the type `DELETE * from TableName` ). The usage of kwargs 
    is the same as in the get function.

    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

    :return: S_OK() || S_ERROR()
    """
        return MySQLWrapper.delete(self, params, meta)

    ## Extended SQL methods ######################################################

    def addOrModify(self, params, meta):
        """
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is there, it is updated, if not, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

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

        selectQuery = self.select(params, meta)
        if not selectQuery["OK"]:
            return selectQuery

        isUpdate = False

        if selectQuery["Value"]:

            # Pseudo - code
            # for all column not being PrimaryKey and not a time column:
            #   if one or more column different than params if not None:
            #     we update dateTime as well

            columns = selectQuery["Columns"]
            values = selectQuery["Value"]

            if len(values) != 1:
                return S_ERROR("More than one value returned on addOrModify, please report !!")

            selectDict = dict(zip(columns, values[0]))

            newDateEffective = None

            for key, value in params.items():
                if key in ("lastCheckTime", "dateEffective"):
                    continue

                if value is None:
                    continue

                if value != selectDict[key[0].upper() + key[1:]]:
                    newDateEffective = datetime.utcnow().replace(microsecond=0)
                    break

            if "dateEffective" in params:
                params["dateEffective"] = newDateEffective

            userQuery = self.update(params, meta)
            isUpdate = True

        else:
            userQuery = self.insert(params, meta)

        # This part only applies to PolicyResult table
        logResult = self._logRecord(params, meta, isUpdate)
        if not logResult["OK"]:
            return logResult

        return userQuery

    # FIXME: this method looks unused. Maybe can be removed from the code.
    def addIfNotThere(self, params, meta):
        """
    Using the PrimaryKeys of the table, it looks for the record in the database.
    If it is not there, it is inserted as a new entry. 
    
    :Parameters:
      **params** - `dict`
        arguments for the mysql query ( must match table columns ! ).

      **meta** - `dict`
        metadata for the mysql query. It must contain, at least, `table` key
        with the proper table name.

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

        selectQuery = self.select(params, meta)
        if not selectQuery["OK"]:
            return selectQuery

        if selectQuery["Value"]:
            return selectQuery

        return self.insert(params, meta)

    ## Auxiliar methods ##########################################################

    def getTable(self, tableName):
        """
      Returns a table dictionary description given its name 
    """
        if tableName in self._tableDict:
            return S_OK(self._tableDict[tableName])

        return S_ERROR("%s is not on the schema" % tableName)

    def getTablesList(self):
        """
      Returns a list of the table names in the schema.
    """
        return S_OK(self._tableDict.keys())

    ## Protected methods #########################################################

    def _checkTable(self):
        """
      Method used by database tools to write the schema
    """
        return self.__createTables()

    def _logRecord(self, params, meta, isUpdate):
        """
      Method that records every change on a LogTable.
    """

        if not ("table" in meta and meta["table"] == "PolicyResult"):
            return S_OK()

        if isUpdate:

            # This looks little bit like a non-sense. If we were updating, we may have
            # not passed a complete set of parameters, so we have to get all them from the
            # database :/. It costs us one more query.
            updateRes = self.select(params, meta)
            if not updateRes["OK"]:
                return updateRes

            params = dict(zip(updateRes["Columns"], updateRes["Value"][0]))

        # Writes to PolicyResult"Log"
        meta["table"] += "Log"

        logRes = self.insert(params, meta)

        return logRes

    ## Private methods ###########################################################

    def __createTables(self, tableName=None):
        """
      Writes the schema in the database. If no tableName is given, all tables
      are written in the database. If a table is already in the schema, it is
      skipped to avoid problems trying to create a table that already exists.
    """

        # Horrible SQL here !!
        tablesCreatedRes = self.database._query("show tables")
        if not tablesCreatedRes["OK"]:
            return tablesCreatedRes
        tablesCreated = [tableCreated[0] for tableCreated in tablesCreatedRes["Value"]]

        tables = {}
        if tableName is None:
            tables.update(self._tableDict)

        elif tableName in self._tableDict:
            tables = {tableName: self._tableDict[tableName]}

        else:
            return S_ERROR('"%s" is not a known table' % tableName)

        for tableName in tablesCreated:
            if tableName in tables:
                del tables[tableName]

        res = self.database._createTables(tables)
        if not res["OK"]:
            return res

        # Human readable S_OK message
        if res["Value"] == 0:
            res["Value"] = "No tables created"
        else:
            res["Value"] = "Tables created: %s" % (",".join(tables.keys()))
        return res

    def __generateTables(self):
        """
      Method used to transform the class variables into instance variables,
      for safety reasons.
    """

        # Avoids copying object.
        tables = {}
        tables.update(self._tablesDB)

        for tableName, tableLike in self._likeToTable.items():

            tables[tableName] = self._tablesLike[tableLike]

        return tables
예제 #11
0
class ResourceManagementDB:
    """ 
  The ResourceManagementDB class is a front-end to the Resource Management Database.
  
  The simplest way to instantiate an object of type :class:`ResourceManagementDB` 
  is simply by calling 

   >>> rpDB = ResourceManagementDB()

  This way, it will use the standard :mod:`DIRAC.Core.Base.DB`. 
  But there's the possibility to use other DB classes. 
  For example, we could pass custom DB instantiations to it, 
  provided the interface is the same exposed by :mod:`DIRAC.Core.Base.DB`.

   >>> AnotherDB = AnotherDBClass()
   >>> rmDB = ResourceManagementDB(DBin = AnotherDB)

  Alternatively, for testing purposes, you could do:

   >>> from DIRAC.ResourceStatusSystem.Utilities.mock import Mock
   >>> mockDB = Mock()
   >>> rmDB = ResourceManagementDB(DBin = mockDB)

  Or, if you want to work with a local DB, providing it's mySQL:

   >>> rmDB = ResourceManagementDB(DBin = ['UserName', 'Password'])

  """
    def __init__(self, *args, **kwargs):

        if len(args) == 1:
            if isinstance(args[0], str):
                #        systemInstance=args[0]
                maxQueueSize = 10
            if isinstance(args[0], int):
                maxQueueSize = args[0]
#        systemInstance='Default'
        elif len(args) == 2:
            #      systemInstance=args[0]
            maxQueueSize = args[1]
        elif len(args) == 0:
            #      systemInstance='Default'
            maxQueueSize = 10

        if 'DBin' in kwargs.keys():
            DBin = kwargs['DBin']
            if isinstance(DBin, list):
                from DIRAC.Core.Utilities.MySQL import MySQL
                self.db = MySQL('localhost', DBin[0], DBin[1],
                                'ResourceManagementDB')
            else:
                self.db = DBin
        else:
            from DIRAC.Core.Base.DB import DB
            self.db = DB('ResourceManagementDB',
                         'ResourceStatus/ResourceManagementDB', maxQueueSize)
#      self.db = DB('ResourceStatusDB','ResourceStatus/ResourceStatusDB',maxQueueSize)

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

#############################################################################
# Policy functions
#############################################################################

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

    def addOrModifyPolicyRes(self,
                             granularity,
                             name,
                             policyName,
                             status,
                             reason,
                             dateEffective=None):
        """
    Add or modify a Policy Result to the PolicyRes table.
    
    :params:
      :attr:`granularity`: string - a ValidRes
      see :mod:`DIRAC.ResourceStatusSystem.Utilities.Utils`
    
      :attr:`name`: string - name of the ValidRes
      
      :attr:`policyName`: string - the policy name
    
      :attr:`status`: string - a ValidStatus: 
      see :mod:`DIRAC.ResourceStatusSystem.Utilities.Utils`
      
      :attr:`reason`: string - free
      
      :attr:`dateEffective`: datetime.datetime - 
      date from which the result is effective
    """

        now = datetime.datetime.utcnow().replace(microsecond=0).isoformat(' ')

        if dateEffective is None:
            dateEffective = now

        req = "SELECT Granularity, Name, PolicyName, Status, Reason FROM PolicyRes "
        req = req + "WHERE Granularity = '%s' AND Name = '%s' AND " % (
            granularity, name)
        req = req + "PolicyName = '%s'" % (policyName)
        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.addOrModifyPolicyRes) + resQuery['Message']

        if resQuery['Value']:
            req = "UPDATE PolicyRes SET "
            if resQuery['Value'][0][3] != status:
                req = req + "Status = '%s', Reason = '%s', DateEffective = '%s', " % (
                    status, reason, dateEffective)
            elif resQuery['Value'][0][4] != reason:
                req = req + "Reason = '%s', " % (reason)
            req = req + "LastCheckTime = '%s' WHERE Granularity = '%s' " % (
                now, granularity)
            req = req + "AND Name = '%s' AND PolicyName = '%s'" % (name,
                                                                   policyName)

            resUpdate = self.db._update(req)
            if not resUpdate['OK']:
                raise RSSManagementDBException, where(
                    self, self.addOrModifyPolicyRes) + resUpdate['Message']
        else:
            req = "INSERT INTO PolicyRes (Granularity, Name, PolicyName, Status, Reason, DateEffective, "
            req = req + "LastCheckTime) VALUES ('%s', '%s', '%s', " % (
                granularity, name, policyName)
            req = req + "'%s', '%s', '%s', '%s')" % (status, reason,
                                                     dateEffective, now)
            resUpdate = self.db._update(req)
            if not resUpdate['OK']:
                raise RSSManagementDBException, where(
                    self, self.addOrModifyPolicyRes) + resUpdate['Message']

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

    def getPolicyRes(self, name, policyName, lastCheckTime=False):
        """ 
    Get a Policy Result from the PolicyRes table.
    
    :params:
      :attr:`name`: string - name of the ValidRes
      
      :attr:`policyName`: string - the policy name
      
      :attr:`lastCheckTime`: optional - if TRUE, it will get also the 
      LastCheckTime 
    """

        req = "SELECT Status, Reason"
        if lastCheckTime:
            req = req + ", LastCheckTime"
        req = req + " FROM PolicyRes WHERE"
        req = req + " Name = '%s' AND PolicyName = '%s'" % (name, policyName)

        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.getPolicyRes) + resQuery['Message']
        if not resQuery['Value']:
            return []

        return resQuery['Value'][0]

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

#############################################################################
# ClientsCache functions
#############################################################################

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

    def addOrModifyClientsCacheRes(self,
                                   name,
                                   commandName,
                                   value,
                                   result,
                                   opt_ID=None,
                                   dateEffective=None):
        """
    Add or modify a Client Result to the ClientCache table.
    
    :params:
      :attr:`name`: string - name of the ValidRes
      
      :attr:`commandName`: string - the command name
    
      :attr:`value`: string - the value
    
      :attr:`result`: string - command result
      
      :attr:`opt_ID`: string or integer - optional ID (e.g. used for downtimes)
      
      :attr:`dateEffective`: datetime.datetime - 
      date from which the result is effective
    """

        now = datetime.datetime.utcnow().replace(microsecond=0).isoformat(' ')

        if dateEffective is None:
            dateEffective = now

        if opt_ID is not None:
            if isinstance(opt_ID, int):
                opt_ID = str(opt_ID)

        req = "SELECT Name, CommandName, "
        if opt_ID is not None:
            req = req + "Opt_ID, "
        req = req + "Value, Result FROM ClientsCache WHERE "
        req = req + "Name = '%s' AND CommandName = '%s' " % (name, commandName)
        if opt_ID is not None:
            req = req + "AND Opt_ID = '%s' " % opt_ID
        req = req + "AND Value = '%s' " % value
        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.addOrModifyClientsCacheRes) + resQuery['Message']

        if resQuery['Value']:
            req = "UPDATE ClientsCache SET "
            if resQuery['Value'][0][3] != result:
                req = req + "Result = '%s', DateEffective = '%s', " % (
                    result, dateEffective)
            req = req + "LastCheckTime = '%s' WHERE " % (now)
            req = req + "Name = '%s' AND CommandName = '%s' AND Value = '%s'" % (
                name, commandName, value)
            if opt_ID is not None:
                req = req + "AND Opt_ID = '%s' " % opt_ID

            resUpdate = self.db._update(req)
            if not resUpdate['OK']:
                raise RSSManagementDBException, where(
                    self,
                    self.addOrModifyClientsCacheRes) + resUpdate['Message']
        else:
            req = "INSERT INTO ClientsCache (Name, CommandName, "
            if opt_ID is not None:
                req = req + "Opt_ID, "
            req = req + "Value, Result, DateEffective, "
            req = req + "LastCheckTime) VALUES ('%s', '%s', " % (name,
                                                                 commandName)
            if opt_ID is not None:
                req = req + "'%s', " % opt_ID
            req = req + "'%s', '%s', '%s', '%s')" % (value, result,
                                                     dateEffective, now)

            resUpdate = self.db._update(req)
            if not resUpdate['OK']:
                raise RSSManagementDBException, where(
                    self,
                    self.addOrModifyClientsCacheRes) + resUpdate['Message']

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

    def getClientsCacheStuff(self,
                             paramsList=None,
                             ccID=None,
                             name=None,
                             commandName=None,
                             opt_ID=None,
                             value=None,
                             result=None,
                             dateEffective=None,
                             lastCheckTime=None):
        """
    Generic function to get values from the ClientsCache table.
    
    :params:
      :attr:`paramsList` - string or list of strings
    
      :attr:`ccID` - string or list of strings
    
      :attr:`name` - string or list of strings
    
      :attr:`commandName` - string or list of strings
    
      :attr:`opt_ID` - string or list of strings
    
      :attr:`value` - string or list of strings
    
      :attr:`result` - string or list of strings
    
      :attr:`dateEffective` - string or list of strings
    
      :attr:`lastCheckTime` - string or list of strings
    """

        if (paramsList == None or paramsList == []):
            params = "ccID, Name, CommandName, Opt_ID, Value, Result, DateEffective "
        else:
            if type(paramsList) is not type([]):
                paramsList = [paramsList]
            params = ','.join([x.strip() + ' ' for x in paramsList])

        req = "SELECT " + params + "FROM ClientsCache "

        if not (ccID == name == commandName == opt_ID == value == result ==
                dateEffective == lastCheckTime == None):
            req = req + "WHERE "

        if ccID is not None:
            if type(ccID) is not type([]):
                ccID = [ccID]
            req = req + "ccID IN (" + ','.join(
                [str(x).strip() + ' ' for x in ccID]) + ")"

        if name is not None:
            if ccID is not None:
                req = req + " AND "
            if type(name) is not type([]):
                name = [name]
            req = req + "Name IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in name]) + ")"

        if commandName is not None:
            if ccID is not None or name is not None:
                req = req + " AND "
            if type(commandName) is not type([]):
                commandName = [commandName]
            req = req + "CommandName IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in commandName]) + ")"

        if opt_ID is not None:
            if ccID is not None or name is not None or commandName is not None:
                req = req + " AND "
            if type(opt_ID) is not type([]):
                opt_ID = [opt_ID]
            req = req + "Opt_ID IN (" + ','.join(
                ['"' + str(x).strip() + '"' + ' ' for x in opt_ID]) + ")"

        if value is not None:
            if ccID is not None or name is not None or commandName is not None or opt_ID is not None:
                req = req + " AND "
            if type(value) is not type([]):
                value = [value]
            req = req + "Value IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in value]) + ")"

        if result is not None:
            if (ccID is not None or name is not None or commandName is not None
                    or opt_ID is not None or value is not None):
                req = req + " AND "
            if type(result) is not type([]):
                result = [result]
            req = req + "result IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in result]) + ")"

        if dateEffective is not None:
            if (ccID is not None or name is not None or commandName is not None
                    or opt_ID is not None or value is not None
                    or result is not None):
                req = req + " AND "
            if type(dateEffective) is not type([]):
                dateEffective = [dateEffective]
            req = req + "dateEffective IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in dateEffective]) + ")"

        if lastCheckTime is not None:
            if (ccID is not None or name is not None or commandName is not None
                    or opt_ID is not None or value is not None
                    or result is not None or dateEffective is not None):
                req = req + " AND "
            if type(lastCheckTime) is not type([]):
                lastCheckTime = [lastCheckTime]
            req = req + "lastCheckTime IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in lastCheckTime]) + ")"

        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.getClientsCacheStuff) + resQuery['Message']
        if not resQuery['Value']:
            return []

        return resQuery['Value']

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

#############################################################################
# AccountingCache functions
#############################################################################

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

    def addOrModifyAccountingCacheRes(self,
                                      name,
                                      plotType,
                                      plotName,
                                      result,
                                      dateEffective=None):
        """
    Add or modify an Accounting Result to the AccountingCache table.
    
    :params:
      :attr:`name`: string - name of the ValidRes
      
      :attr:`plotType`: string - the plotType name (e.g. 'Pilot')
    
      :attr:`plotName`: string - the plot name
    
      :attr:`result`: string - command result
      
      :attr:`dateEffective`: datetime.datetime - 
      date from which the result is effective
    """

        now = datetime.datetime.utcnow().replace(microsecond=0).isoformat(' ')

        if dateEffective is None:
            dateEffective = now

        req = "SELECT Name, PlotType, PlotName, Result FROM AccountingCache WHERE "
        req = req + "Name = '%s' AND PlotType = '%s' AND PlotName = '%s' " % (
            name, plotType, plotName)
        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.addOrModifyAccountingCacheRes) + resQuery['Message']

        if resQuery['Value']:
            req = "UPDATE AccountingCache SET "
            if resQuery['Value'][0][3] != result:
                req = req + "Result = \"%s\", DateEffective = '%s', " % (
                    result, dateEffective)
            req = req + "LastCheckTime = '%s' WHERE " % (now)
            req = req + "Name = '%s' AND PlotType = '%s' AND PlotName = '%s'" % (
                name, plotType, plotName)

            resUpdate = self.db._update(req)
            if not resUpdate['OK']:
                raise RSSManagementDBException, where(
                    self,
                    self.addOrModifyAccountingCacheRes) + resUpdate['Message']
        else:
            req = "INSERT INTO AccountingCache (Name, PlotType, PlotName, Result, DateEffective, "
            req = req + "LastCheckTime) VALUES ('%s', '%s', '%s', " % (
                name, plotType, plotName)
            req = req + "\"%s\", '%s', '%s')" % (result, dateEffective, now)

            resUpdate = self.db._update(req)
            if not resUpdate['OK']:
                raise RSSManagementDBException, where(
                    self,
                    self.addOrModifyAccountingCacheRes) + resUpdate['Message']

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

    def getAccountingCacheStuff(self,
                                paramsList=None,
                                acID=None,
                                name=None,
                                plotType=None,
                                plotName=None,
                                result=None,
                                dateEffective=None,
                                lastCheckTime=None):
        """
    Generic function to get values from the AccountingCache table.
    
    :params:
      :attr:`paramsList` - string or list of strings
    
      :attr:`acID` - string or list of strings
    
      :attr:`name` - string or list of strings
    
      :attr:`plotName` - string or list of strings
    
      :attr:`result` - string or list of strings
    
      :attr:`dateEffective` - string or list of strings
    
      :attr:`lastCheckTime` - string or list of strings
    """
        if (paramsList == None or paramsList == []):
            params = "acID, Name, PlotType, PlotName, Result, DateEffective "
        else:
            if type(paramsList) != type([]):
                paramsList = [paramsList]
            params = ','.join([x.strip() + ' ' for x in paramsList])

        req = "SELECT " + params + "FROM AccountingCache "

        if not (acID == name == plotType == plotName == result == dateEffective
                == lastCheckTime == None):
            req = req + "WHERE "

        if acID is not None:
            if type(acID) is not type([]):
                acID = [acID]
            req = req + "acID IN (" + ','.join(
                [str(x).strip() + ' ' for x in acID]) + ")"

        if name is not None:
            if acID is not None:
                req = req + " AND "
            if type(name) is not type([]):
                name = [name]
            req = req + "Name IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in name]) + ")"

        if plotName is not None:
            if acID is not None or name is not None:
                req = req + " AND "
            if type(plotName) is not type([]):
                plotName = [plotName]
            req = req + "PlotName IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in plotName]) + ")"

        if plotType is not None:
            if acID is not None or name is not None or plotName is not None:
                req = req + " AND "
            if type(plotType) is not type([]):
                plotType = [plotType]
            req = req + "PlotType IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in plotType]) + ")"

        if result is not None:
            if (acID is not None or name is not None or plotName is not None
                    or plotType is not None):
                req = req + " AND "
            if type(result) is not type([]):
                result = [result]
            req = req + "Result IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in result]) + ")"

        if dateEffective is not None:
            if (acID is not None or name is not None or plotName is not None
                    or plotType is not None or result is not None):
                req = req + " AND "
            if type(dateEffective) is not type([]):
                dateEffective = [dateEffective]
            req = req + "DateEffective IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in dateEffective]) + ")"

        if lastCheckTime is not None:
            if (acID is not None or name is not None or plotName is not None
                    or plotType is not None or result is not None
                    or dateEffective is not None):
                req = req + " AND "
            if type(lastCheckTime) is not type([]):
                lastCheckTime = [lastCheckTime]
            req = req + "LastCheckTime IN (" + ','.join(
                ['"' + x.strip() + '"' + ' ' for x in lastCheckTime]) + ")"

        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.getAccountingCacheStuff) + resQuery['Message']
        if not resQuery['Value']:
            return []

        return resQuery['Value']

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

#############################################################################
# Status functions
#############################################################################

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

#usata solo nell'handler

    def addStatus(self, status, description=''):
        """ 
    Add a status.
    
    :params:
      :attr:`status`: string - a new status
      
      :attr:`description`: string - optional description
    """

        req = "INSERT INTO Status (Status, Description)"
        req = req + "VALUES ('%s', '%s');" % (status, description)

        resUpdate = self.db._update(req)
        if not resUpdate['OK']:
            raise RSSManagementDBException, where(
                self, self.addStatus) + resUpdate['Message']

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

#usata solo nell'handler

    def removeStatus(self, status):
        """ 
    Remove a status from the Status table.
    
    :params:
      :attr:`status`: string - status
    """

        req = "DELETE from Status WHERE Status = '%s';" % (status)
        resDel = self.db._update(req)
        if not resDel['OK']:
            raise RSSManagementDBException, where(
                self, self.removeStatus) + resDel['Message']

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

    def getStatusList(self):
        """ 
    Get list of status with no descriptions.
    """

        req = "SELECT Status from Status"

        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, where(
                self, self.getStatusList) + resQuery['Message']
        if not resQuery['Value']:
            return []
        l = [x[0] for x in resQuery['Value']]
        return l

#############################################################################
# Web functions
#############################################################################

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

    def getDownTimesWeb(self,
                        selectDict,
                        sortList=[],
                        startItem=0,
                        maxItems=1000):
        """
    Get downtimes registered in the RSS DB (with a web layout)

    :params:
      :attr:`selectDict`: { 'Granularity':['Site', 'Resource'], 'Severity': ['OUTAGE', 'AT_RISK']}
            
      :attr:`sortList` 
      
      :attr:`startItem` 
      
      :attr:`maxItems`
    """

        granularity = selectDict['Granularity']
        severity = selectDict['Severity']

        if not isinstance(granularity, list):
            granularity = [granularity]
        if not isinstance(severity, list):
            severity = [severity]

        paramNames = ['Granularity', 'Name', 'Severity', 'When']

        req = "SELECT Granularity, Name, Reason FROM PolicyRes WHERE "
        req = req + "PolicyName LIKE 'DT_%' AND Reason LIKE \'%found%\' "
        req = req + "AND Granularity in (%s)" % (','.join(
            ['"' + x.strip() + '"' for x in granularity]))
        resQuery = self.db._query(req)
        if not resQuery['OK']:
            raise RSSManagementDBException, resQuery['Message']
        if not resQuery['Value']:
            records = []
        else:
            resQuery = resQuery['Value']
            records = []
            for tuple in resQuery:
                sev = tuple[2].split()[2]
                if sev not in severity:
                    continue
                when = tuple[2].split(sev)[1][1:]
                if when == '':
                    when = 'Ongoing'
                records.append([tuple[0], tuple[1], sev, when])

        finalDict = {}
        finalDict['TotalRecords'] = len(records)
        finalDict['ParameterNames'] = paramNames

        # Return all the records if maxItems == 0 or the specified number otherwise
        if maxItems:
            finalDict['Records'] = records[startItem:startItem + maxItems]
        else:
            finalDict['Records'] = records

        finalDict['Extras'] = None

        return finalDict


#############################################################################
예제 #12
0
class RSSConfigurationDB(object):

  def __init__(self, DBin = None, maxQueueSize = 10):
    if DBin: self.db = DBin
    else:
      from DIRAC.Core.Base.DB import DB
      self.db = DB('RSSConfigurationDB',
                   'ResourceStatus/RSSConfigurationDB', maxQueueSize)

  def _delete(self, tableName, inFields, inValues):
    # FIXME: Should go in DIRAC.Core.Utilities.MySQL
    zipped = zip(inFields, inValues)
    where_clause = ''
    for i,(l,v) in enumerate(zipped):
      if i == 0:
        where_clause = where_clause + l + '="' + v + '" '
      else:
        where_clause = where_clause + 'AND ' + l + '="' + v + '" '

    return self.db._update('DELETE FROM ' + tableName + ' WHERE ' + where_clause)

  def _addValue(self, table, vdict):
    keys, values = list_split(vdict.items())
    return self.db._insert(table, keys, values)

  def _delValue(self, table, vdict):
    keys, values = list_split(vdict.items())
    return self._delete(table, keys, values)

  def _addValues(self, table, vdicts):
    res = []
    for d in vdicts:
      res.append(self._addValue(table, d))
    return res

  def _delValues(self, table, vdicts):
    res = []
    for d in vdicts:
      res.append(self._delValue(table, d))
    return res

  def _query(self, table):
    """
    Returns values in a list instead of a tuple, i.e. retval[1] is a
    list of tuples, one per line of result.
    """
    retval = self.db._query("SELECT * from " + table)
    return retval['OK'], list(retval['Value'])

  # Helper functions.

  def addUsers(self, unames):
    """Add users. The argument is a list of strings representing
    usernames."""
    unames = [{'login':u} for u in unames]
    return self._addValues(t_users, unames)

  def addUser(self, uname):
    """Add one user. The argument is a string representing the
    username"""
    return self.addUsers([uname])[0]

  def delUsers(self, unames):
    """Delete users. The argument is a list of strings representing
    usernames."""
    unames = [{'login': u} for u in unames]
    return self._delValues(t_users, unames)

  def delUser(self, uname):
    """Delete a user. The argument is a string representing
    username."""
    return self.delUsers([uname])[0]

  def getUsers(self):
    """Return users registered in database. Return S_OK() with Value:
    a dict representing users with (for now) only a field 'login'.
    TODO: This function is not supposed to fail in normal conditions,
    and result incorrect if it fails. Fix this.
    """
    ret, users = self._query(t_users)
    users = [{'login': u} for u in users]
    return {'OK':ret, 'Value':users}

  def addStatuses(self, statuses):
    """Add statuses. Argument is a list of tuples (label, priority)"""
    statuses = [{'label':l, 'priority':p} for (l,p) in statuses]
    return self._addValues(t_statuses, statuses)

  def addStatus(self, label, priority):
    """Add a status. The argument is respectively a string and an
    integer, representing the name of the status and the priority"""
    return self.addStatuses([(label, priority)])[0]

  def delStatuses(self, statuses):
    """Delete statuses. Argument is a list of strings (labels)"""
    statuses = [{'label':l} for l in statuses]
    return self._delValues(t_statuses, statuses)

  def delStatus(self, status):
    return self.delStatuses([status])[0]

  def getStatuses(self):
    ret, statuses = self._query(t_statuses)
    statuses = [{'label':l, 'priority':p} for (l,p) in statuses]
    return {'OK':ret, 'Value':statuses}

  def addCheckFreq(self, kwargs):
    """
    Add a new check frequency. Arguments must be a dict with fields:
    granularity, site_type, status, freq.
    """
    return self._addValue(t_checkfreqs, kwargs)

  def delCheckFreq(self, kwargs):
    """
    Delete check frequencies. Arguments must be a dict with fields
    part or all of: granularity, site_type, status, freq.
    """
    return self._delValue(t_checkfreqs, kwargs)

  def getCheckFreqs(self):
    ret, freqs = self._query(t_checkfreqs)
    freqs = [{'granularity':g, 'site_type':st,'status':sta, 'freq':f}
             for (g,st,sta,f) in freqs]
    return {'OK':ret, 'Value':freqs}

  def addAssigneeGroup(self, kwargs):
    """
    Add new assignee groups. Argument must be a dict with fields:
    label, login, granularity, site_type, service_type, resource_type,
    notification.
    """
    return self._addValue(t_assigneegroups, kwargs)

  def delAssigneeGroup(self, kwargs):
    """
    Delete assignee groups. Argument must be a dict with fields all or
    part of: label, login, granularity, site_type, service_type,
    resource_type, notification.
    """
    return self._delValue(t_assigneegroups, kwargs)

  def getAssigneeGroups(self):
    ret, groups = self._query(t_assigneegroups)
    groups = [{'label':label, 'login':login, 'granularity':granularity,
               'site_type':site_type, 'service_type':service_type,
               'resource_type':resource_type, 'notification':notification}
              for (label, login, granularity, site_type,
                   service_type, resource_type, notification) in groups
              ]
    return {'OK':ret, 'Value':groups}

  def addPolicy(self, kwargs):
    """
    Add new policies. Argument must be a dict with fiels: label,
    description, status, former_status, site_type, service_type,
    resource_type.
    """
    return self._addValue(t_policies, kwargs)

  def delPolicy(self, kwargs):
    """
    Delete policies. Argument must be a dict with fields all or part
    of: label, description, status, former_status, site_type,
    service_type, resource_type, or a list of labels.
    """
    return self._delValue(t_policies, kwargs)


  def getPolicies(self):
    ret, policies = self._query(t_policies)
    policies = [{'label':label, 'description':description, 'status':status,
                 'former_status':former_status, 'site_type':site_type,
                 'service_type':service_type, 'resource_type':resource_type}
                for (label, description, status, former_status,
                     site_type, service_type, resource_type) in policies
                ]
    return {'OK':ret, 'Value':policies}