""" ResourceStatusHandler Module that allows users to access the ResourceStatusDB remotely. """ from __future__ import absolute_import from __future__ import division from __future__ import print_function # pylint: disable=too-many-arguments __RCSID__ = "59228e428 (2022-01-06 10:42:48 +0100) Christophe Haen " import six from DIRAC import gLogger, S_OK from DIRAC.Core.DISET.RequestHandler import RequestHandler, getServiceOption from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader def convert(table, params): """Conversion utility for backward compatibility""" gLogger.debug("Calls from old client") # In this case, "params" contain the "meta", so we at least need to swap! tableFromOldCall = params["table"] columnsFromOldCall = params.get("columns") olderFromOldCall = params.get("older") newerFromOldCall = params.get("newer") orderFromOldCall = params.get("order") limitFromOldCall = params.get("limit") params = table if columnsFromOldCall or olderFromOldCall or newerFromOldCall or orderFromOldCall or limitFromOldCall: params["Meta"] = {} if columnsFromOldCall: params["Meta"]["columns"] = columnsFromOldCall if olderFromOldCall: params["Meta"]["older"] = olderFromOldCall if newerFromOldCall: params["Meta"]["newer"] = newerFromOldCall if orderFromOldCall: params["Meta"]["order"] = orderFromOldCall if limitFromOldCall: params["Meta"]["limit"] = limitFromOldCall table = tableFromOldCall return params, table def loadResourceStatusComponent(moduleName, className): """ Create an object of a given database component. :param moduleName: module name to be loaded :param className: class name :return: object instance wrapped in a standard Dirac return object. """ objectLoader = ObjectLoader() componentModule = "ResourceStatusSystem.DB.%s" % (moduleName,) result = objectLoader.loadObject(componentModule, className) if not result["OK"]: gLogger.error("Failed to load RSS component", "%s: %s" % (moduleName, result["Message"])) return result componentClass = result["Value"] component = componentClass() return S_OK(component) class ResourceStatusHandler(RequestHandler): """ The ResourceStatusHandler exposes the DB front-end functions through a XML-RPC server, functionalities inherited from :class:`DIRAC.Core.DISET.RequestHandler.RequestHandler` According to the ResourceStatusDB philosophy, only functions of the type: - insert - update - select - delete are exposed. If you need anything more complicated, either look for it on the :class:`ResourceStatusClient`, or code it yourself. This way the DB and the Service are kept clean and tidied. """ def __init__(self, *args, **kwargs): super(ResourceStatusHandler, self).__init__(*args, **kwargs) @classmethod def initializeHandler(cls, serviceInfoDict): """ Handler initialization, where we: dynamically load ResourceStatus database plugin module, as advised by the config, (assumes that the module name and a class name are the same) set the ResourceManagementDB as global db. :param serviceInfoDict: service info dictionary :return: standard Dirac return object """ defaultOption, defaultClass = "ResourceStatusDB", "ResourceStatusDB" configValue = getServiceOption(serviceInfoDict, defaultOption, defaultClass) result = loadResourceStatusComponent(configValue, configValue) if not result["OK"]: return result cls.db = result["Value"] return S_OK() def __logResult(self, methodName, result): """ Method that writes to log error messages """ if not result["OK"]: self.log.error("%s%s" % (methodName, result["Message"])) types_insert = [[six.string_types, dict], dict] def export_insert(self, table, params): """ This method is a bridge to access :class:`ResourceStatusDB` remotely. It does not add neither processing nor validation. If you need to know more about this method, you must keep reading on the database documentation. :Parameters: **table** - `string` or `dict` should contain the table from which querying if it's a `dict` the query comes from a client prior to v6r18 **params** - `dict` arguments for the mysql query. Currently it is being used only for column selection. For example: meta = { 'columns' : [ 'Name' ] } will return only the 'Name' column. :return: S_OK() || S_ERROR() """ self.log.info("insert: %s %s" % (table, params)) res = self.db.insert(table, params) self.__logResult("insert", res) return res types_select = [[six.string_types, dict], dict] def export_select(self, table, params): """ This method is a bridge to access :class:`ResourceStatusDB` remotely. It does not add neither processing nor validation. If you need to know more about this method, you must keep reading on the database documentation. :Parameters: **table** - `string` or `dict` should contain the table from which querying if it's a `dict` the query comes from a client prior to v6r18 **params** - `dict` arguments for the mysql query. Currently it is being used only for column selection. For example: meta = { 'columns' : [ 'Name' ] } will return only the 'Name' column. :return: S_OK() || S_ERROR() """ self.log.info("select: %s %s" % (table, params)) res = self.db.select(table, params) self.__logResult("select", res) return res types_delete = [[six.string_types, dict], dict] def export_delete(self, table, params): """ This method is a bridge to access :class:`ResourceStatusDB` remotely.\ It does not add neither processing nor validation. If you need to know more \ about this method, you must keep reading on the database documentation. :Parameters: **table** - `string` or `dict` should contain the table from which querying if it's a `dict` the query comes from a client prior to v6r18 **params** - `dict` arguments for the mysql query. Currently it is being used only for column selection. For example: meta = { 'columns' : [ 'Name' ] } will return only the 'Name' column. :return: S_OK() || S_ERROR() """ self.log.info("delete: %s %s" % (table, params)) res = self.db.delete(table, params) self.__logResult("delete", res) return res types_addOrModify = [[six.string_types, dict], dict] def export_addOrModify(self, table, params): """ This method is a bridge to access :class:`ResourceStatusDB` remotely.\ It does not add neither processing nor validation. If you need to know more \ about this method, you must keep reading on the database documentation. :Parameters: **table** - `string` or `dict` should contain the table from which querying if it's a `dict` the query comes from a client prior to v6r18 **params** - `dict` arguments for the mysql query. Currently it is being used only for column selection. For example: meta = { 'columns' : [ 'Name' ] } will return only the 'Name' column. :return: S_OK() || S_ERROR() """ self.log.info("addOrModify: %s %s" % (table, params)) res = self.db.addOrModify(table, params) self.__logResult("addOrModify", res) return res types_addIfNotThere = [[six.string_types, dict], dict] def export_addIfNotThere(self, table, params): """ This method is a bridge to access :class:`ResourceStatusDB` remotely.\ It does not add neither processing nor validation. If you need to know more \ about this method, you must keep reading on the database documentation. :Parameters: **table** - `string` or `dict` should contain the table from which querying if it's a `dict` the query comes from a client prior to v6r18 **params** - `dict` arguments for the mysql query. Currently it is being used only for column selection. For example: meta = { 'columns' : [ 'Name' ] } will return only the 'Name' column. :return: S_OK() || S_ERROR() """ self.log.info("addIfNotThere: %s %s" % (table, params)) res = self.db.addIfNotThere(table, params) self.__logResult("addIfNotThere", res) return res