"Fossies" - the Fresh Open Source Software Archive

Member "opensaf-5.21.09/python/pyosaf/utils/immoi/agent.py" (31 May 2021, 16321 Bytes) of package /linux/misc/opensaf-5.21.09.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "agent.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 5.20.11_vs_5.21.03.

    1 ############################################################################
    2 #
    3 # (C) Copyright 2015 The OpenSAF Foundation
    4 # (C) Copyright 2017 Ericsson AB. All rights reserved.
    5 #
    6 # This program is distributed in the hope that it will be useful, but
    7 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    8 # or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
    9 # under the GNU Lesser General Public License Version 2.1, February 1999.
   10 # The complete license can be accessed from the following location:
   11 # http://opensource.org/licenses/lgpl-license.php
   12 # See the Copying file included with the OpenSAF distribution for full
   13 # licensing terms.
   14 #
   15 # Author(s): Ericsson
   16 #
   17 ############################################################################
   18 """
   19 IMM OI common utilities
   20 
   21 Supported functions:
   22 - Set/clear/release implementer for class/object
   23 - Create/delete/update runtime object
   24 - Get class/object attributes
   25 - Get IMM error strings
   26 """
   27 from __future__ import print_function
   28 from copy import deepcopy
   29 from ctypes import c_void_p, cast, pointer
   30 
   31 from pyosaf.saAis import SaStringT, SaVersionT, SaNameT, SaSelectionObjectT, \
   32     eSaDispatchFlagsT, eSaAisErrorT
   33 from pyosaf import saImmOi
   34 from pyosaf.saImm import SaImmAttrNameT, SaImmAttrValuesT_2, SaImmClassNameT, \
   35     SaImmSearchParametersT_2, eSaImmValueTypeT, SaImmAttrModificationT_2, \
   36     eSaImmAttrModificationTypeT
   37 from pyosaf.saImmOi import SaImmOiHandleT
   38 from pyosaf.utils import log_err, bad_handle_retry, decorate, \
   39     initialize_decorate
   40 from pyosaf.utils.immom.object import ImmObject
   41 from pyosaf.utils.immom.ccb import marshal_c_array
   42 from pyosaf.utils.immom.iterator import SearchIterator
   43 from pyosaf.utils.immom.agent import ImmOmAgent
   44 from pyosaf.utils.immom.accessor import ImmOmAccessor
   45 
   46 
   47 OPENSAF_IMM_OBJECT = "opensafImm=opensafImm,safApp=safImmService"
   48 
   49 
   50 # Decorate pure saImmOi* API's with error-handling retry and exception raising
   51 saImmOiInitialize_2 = initialize_decorate(saImmOi.saImmOiInitialize_2)
   52 saImmOiSelectionObjectGet = decorate(saImmOi.saImmOiSelectionObjectGet)
   53 saImmOiDispatch = decorate(saImmOi.saImmOiDispatch)
   54 saImmOiFinalize = decorate(saImmOi.saImmOiFinalize)
   55 saImmOiImplementerSet = decorate(saImmOi.saImmOiImplementerSet)
   56 saImmOiImplementerClear = decorate(saImmOi.saImmOiImplementerClear)
   57 saImmOiClassImplementerSet = decorate(saImmOi.saImmOiClassImplementerSet)
   58 saImmOiClassImplementerRelease = \
   59     decorate(saImmOi.saImmOiClassImplementerRelease)
   60 saImmOiObjectImplementerSet = decorate(saImmOi.saImmOiObjectImplementerSet)
   61 saImmOiObjectImplementerRelease = \
   62     decorate(saImmOi.saImmOiObjectImplementerRelease)
   63 saImmOiRtObjectCreate_2 = decorate(saImmOi.saImmOiRtObjectCreate_2)
   64 saImmOiRtObjectDelete = decorate(saImmOi.saImmOiRtObjectDelete)
   65 saImmOiRtObjectUpdate_2 = decorate(saImmOi.saImmOiRtObjectUpdate_2)
   66 saImmOiAdminOperationResult = decorate(saImmOi.saImmOiAdminOperationResult)
   67 saImmOiAdminOperationResult_o2 = \
   68     decorate(saImmOi.saImmOiAdminOperationResult_o2)
   69 saImmOiAugmentCcbInitialize = decorate(saImmOi.saImmOiAugmentCcbInitialize)
   70 saImmOiCcbSetErrorString = decorate(saImmOi.saImmOiCcbSetErrorString)
   71 
   72 
   73 class OiAgent(object):
   74     """ This class acts as a high-level OI agent, providing OI functions to
   75     the users as a higher level, and relieving the users of the need to manage
   76     the life cycle of the OI agent and providing general interface for
   77     Implementer or Applier used
   78     """
   79     def __init__(self, version=None):
   80         """ Constructor for OiAgent class
   81 
   82         Args:
   83             version (SaVersionT): OI API version
   84         """
   85         self.handle = None
   86         self.init_version = version if version is not None \
   87             else SaVersionT('A', 2, 15)
   88         self.version = None
   89         self.selection_object = None
   90         self.callbacks = None
   91         self.imm_om = None
   92         self.accessor = None
   93 
   94     def _fetch_sel_obj(self):
   95         """ Obtain a selection object (OS file descriptor)
   96 
   97         Returns:
   98             SaAisErrorT: Return code of the saImmOiSelectionObjectGet() API
   99         """
  100         rc = saImmOiSelectionObjectGet(self.handle, self.selection_object)
  101         if rc != eSaAisErrorT.SA_AIS_OK:
  102             log_err("saImmOiSelectionObjectGet FAILED - %s" %
  103                     eSaAisErrorT.whatis(rc))
  104 
  105         return rc
  106 
  107     def initialize(self, callbacks=None):
  108         """ Initialize the IMM OI agent
  109 
  110         Args:
  111             callbacks (SaImmOiCallbacksT_2): OI callbacks to register with IMM
  112 
  113         Returns:
  114             SaAisErrorT: Return code of OI initialize
  115         """
  116         self.imm_om = ImmOmAgent(self.init_version)
  117         rc = self.imm_om.init()
  118 
  119         if rc == eSaAisErrorT.SA_AIS_OK:
  120             if not self.accessor:
  121                 self.accessor = ImmOmAccessor(self.init_version)
  122                 rc = self.accessor.init()
  123                 if rc != eSaAisErrorT.SA_AIS_OK:
  124                     log_err("saImmOmAccessorInitialize FAILED - %s" %
  125                             eSaAisErrorT.whatis(rc))
  126                     return rc
  127 
  128             self.handle = SaImmOiHandleT()
  129             self.selection_object = SaSelectionObjectT()
  130             if callbacks is not None:
  131                 self.callbacks = callbacks
  132             self.version = deepcopy(self.init_version)
  133             rc = saImmOiInitialize_2(self.handle, self.callbacks,
  134                                      self.version)
  135             if rc == eSaAisErrorT.SA_AIS_OK:
  136                 rc = self._fetch_sel_obj()
  137                 if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
  138                     rc = self.re_initialize()
  139             else:
  140                 log_err("saImmOiInitialize_2 FAILED - %s" %
  141                         eSaAisErrorT.whatis(rc))
  142         else:
  143             log_err("saImmOmInitialize FAILED - %s" % eSaAisErrorT.whatis(rc))
  144 
  145         return rc
  146 
  147     @bad_handle_retry
  148     def re_initialize(self):
  149         """ Re-initialize the IMM OI agent
  150 
  151         Returns:
  152             SaAisErrorT: Return code of OI initialize
  153         """
  154         self.finalize()
  155         rc = self.initialize()
  156 
  157         return rc
  158 
  159     def finalize(self):
  160         """ Finalize IMM OI agent handle
  161 
  162         Returns:
  163             SaAisErrorT: Return code of OI finalize
  164         """
  165         rc = eSaAisErrorT.SA_AIS_OK
  166         if self.handle is not None:
  167             rc = saImmOiFinalize(self.handle)
  168             if rc != eSaAisErrorT.SA_AIS_OK:
  169                 log_err("saImmOiFinalize FAILED - %s" %
  170                         eSaAisErrorT.whatis(rc))
  171 
  172             if rc == eSaAisErrorT.SA_AIS_OK \
  173                     or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
  174                 # If the Finalize() call returned BAD_HANDLE, the handle should
  175                 # already become stale and invalid, so we reset it anyway.
  176                 self.handle = None
  177         return rc
  178 
  179     def get_selection_object(self):
  180         """ Return the selection object associating with the OI handle
  181 
  182         Returns:
  183             SaSelectionObjectT: Selection object associated with the OI handle
  184         """
  185         return self.selection_object
  186 
  187     def dispatch(self, flags=eSaDispatchFlagsT.SA_DISPATCH_ALL):
  188         """ Dispatch all queued callbacks
  189 
  190         Args:
  191             flags (eSaDispatchFlagsT): Flags specifying dispatch mode
  192 
  193         Returns:
  194             SaAisErrorT: Return code of OI dispatch
  195         """
  196         rc = saImmOiDispatch(self.handle, flags)
  197         if rc != eSaAisErrorT.SA_AIS_OK:
  198             log_err("saImmOiDispatch FAILED - %s" % eSaAisErrorT.whatis(rc))
  199         return rc
  200 
  201     def create_runtime_object(self, class_name, parent_name, runtime_obj):
  202         """ Create a runtime object
  203 
  204         Args:
  205             class_name (str): Class name
  206             parent_name (str): Parent name
  207             runtime_obj (ImmObject): Runtime object to create
  208 
  209         Returns:
  210             SaAisErrorT: Return code of OI create runtime object
  211         """
  212         # Marshall parameters
  213         c_class_name = SaImmClassNameT(class_name)
  214         if parent_name:
  215             c_parent_name = SaNameT(parent_name)
  216         else:
  217             c_parent_name = None
  218 
  219         c_attr_values = []
  220 
  221         for name, (c_attr_type, values) in runtime_obj.attrs.items():
  222             if values is None:
  223                 values = []
  224             elif values == [None]:
  225                 values = []
  226 
  227             # Make sure all values are in lists
  228             if not isinstance(values, list):
  229                 values = [values]
  230 
  231             # Create the values struct
  232             c_attr = SaImmAttrValuesT_2()
  233             c_attr.attrName = SaImmAttrNameT(name)
  234             c_attr.attrValueType = c_attr_type
  235             c_attr.attrValuesNumber = len(values)
  236 
  237             if not values:
  238                 c_attr.attrValues = None
  239             else:
  240                 c_attr.attrValues = marshal_c_array(c_attr_type, values)
  241 
  242             c_attr_values.append(c_attr)
  243 
  244         rc = saImmOiRtObjectCreate_2(self.handle, c_class_name,
  245                                      c_parent_name, c_attr_values)
  246 
  247         if rc != eSaAisErrorT.SA_AIS_OK:
  248             log_err("saImmOiRtObjectCreate_2 FAILED - %s" %
  249                     eSaAisErrorT.whatis(rc))
  250         return rc
  251 
  252     def delete_runtime_object(self, dn):
  253         """ Delete a runtime object
  254 
  255         Args:
  256             dn (str): Runtime object dn
  257 
  258         Returns:
  259             SaAisErrorT: Return code of OI delete runtime object
  260         """
  261         # Marshall the parameter
  262         c_dn = SaNameT(dn)
  263         rc = saImmOiRtObjectDelete(self.handle, c_dn)
  264 
  265         if rc != eSaAisErrorT.SA_AIS_OK:
  266             log_err("saImmOiRtObjectDelete FAILED - %s" %
  267                     eSaAisErrorT.whatis(rc))
  268         return rc
  269 
  270     def update_runtime_object(self, dn, attributes):
  271         """ Update the specified object with the requested attribute
  272         modifications
  273 
  274         Args:
  275             dn (str): Object dn
  276             attributes (dict): Dictionary of attribute modifications
  277 
  278         Returns:
  279             SaAisErrorT: Return code of OI update runtime object
  280         """
  281         # Get the class name for the object
  282         class_name = self.get_class_name_for_dn(dn)
  283 
  284         # Create and marshall attribute modifications
  285         attr_mods = []
  286 
  287         for name, values in attributes.items():
  288             if values is None:
  289                 print("WARNING: Received no values for %s in %s" % (name, dn))
  290                 continue
  291             if not isinstance(values, list):
  292                 values = [values]
  293 
  294             attr_type = self.get_attribute_type(name, class_name)
  295             c_attr_mod = SaImmAttrModificationT_2()
  296             c_attr_mod.modType = \
  297                 eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_REPLACE
  298             c_attr_mod.modAttr = SaImmAttrValuesT_2()
  299             c_attr_mod.modAttr.attrName = SaImmAttrNameT(name)
  300             c_attr_mod.modAttr.attrValueType = attr_type
  301             c_attr_mod.modAttr.attrValuesNumber = len(values)
  302             c_attr_mod.modAttr.attrValues = marshal_c_array(attr_type, values)
  303             attr_mods.append(c_attr_mod)
  304 
  305         rc = saImmOiRtObjectUpdate_2(self.handle, SaNameT(dn), attr_mods)
  306 
  307         if rc != eSaAisErrorT.SA_AIS_OK:
  308             log_err("saImmOiRtObjectUpdate_2 FAILED - %s" %
  309                     eSaAisErrorT.whatis(rc))
  310         return rc
  311 
  312     def report_admin_operation_result(self, invocation_id, result):
  313         """ Report the result of an administrative operation
  314 
  315         Args:
  316             invocation_id (SaInvocationT): Invocation id
  317             result (SaAisErrorT): Result of admin operation
  318 
  319         Returns:
  320             SaAisErrorT: Return code of OI admin operation
  321         """
  322         rc = saImmOiAdminOperationResult(self.handle, invocation_id, result)
  323         if rc != eSaAisErrorT.SA_AIS_OK:
  324             log_err("saImmOiAdminOperationResult FAILED - %s" %
  325                     eSaAisErrorT.whatis(rc))
  326         return rc
  327 
  328     def set_error_string(self, ccb_id, error_string):
  329         """ Set the error string
  330         This can only be called from within OI callbacks of a real implementer.
  331 
  332         Args:
  333             ccb_id (SaImmOiCcbIdT): CCB id
  334             error_string (str): Error string
  335 
  336         Returns:
  337             SaAisErrorT: Return code of OI CCB set error string
  338         """
  339         c_error_string = SaStringT(error_string)
  340         rc = saImmOiCcbSetErrorString(self.handle, ccb_id, c_error_string)
  341 
  342         if rc != eSaAisErrorT.SA_AIS_OK:
  343             log_err("saImmOiCcbSetErrorString FAILED - %s" %
  344                     eSaAisErrorT.whatis(rc))
  345         return rc
  346 
  347     def get_attribute_type(self, attribute, class_name):
  348         """ Return the type of the attribute in the given class
  349 
  350         Args:
  351             attribute (str): Attribute name
  352             class_name (str): Class name
  353 
  354         Returns:
  355             str: Attribute type
  356         """
  357         _, class_desc = self.imm_om.get_class_description(class_name)
  358         attr_desc = [attr for attr in class_desc if
  359                      str(attr.attrName) == attribute][0]
  360 
  361         return attr_desc.attrValueType
  362 
  363     @staticmethod
  364     def get_parent_name_for_dn(dn):
  365         """ Return the parent's dn of the given object's dn
  366 
  367         Args:
  368             dn (str): Object dn
  369 
  370         Returns:
  371             str: DN of the object's parent
  372         """
  373         if ',' in dn:
  374             return dn.split(',', 1)[1]
  375 
  376         return ""
  377 
  378     @staticmethod
  379     def get_object_names_for_class(class_name):
  380         """ Return instances of the given class
  381 
  382         Args:
  383             class_name (str): Class name
  384 
  385         Returns:
  386             list: List of object names
  387         """
  388         # Marshall the search parameter
  389         c_class_name = SaStringT(class_name)
  390         c_search_param = SaImmSearchParametersT_2()
  391         c_search_param.searchOneAttr.attrName = SaStringT("SaImmAttrClassName")
  392         c_search_param.searchOneAttr.attrValueType = \
  393             eSaImmValueTypeT.SA_IMM_ATTR_SASTRINGT
  394         c_search_param.searchOneAttr.attrValue = \
  395             cast(pointer(c_class_name), c_void_p)
  396 
  397         # Create the search iterator
  398         found_objs = SearchIterator(search_param=c_search_param,
  399                                     attribute_names=['SaImmAttrClassName'])
  400         found_objs.init()
  401         # Return the dn's of found objects
  402         object_names = []
  403         for obj in found_objs:
  404             object_names.append(obj.dn)
  405 
  406         return object_names
  407 
  408     def get_class_name_for_dn(self, dn):
  409         """ Return the class name for an instance with the given dn
  410 
  411         Args:
  412             dn (str): Object dn
  413 
  414         Returns:
  415             str: Class name
  416         """
  417         _, obj = self.accessor.get(dn, ["SaImmAttrClassName"])
  418         if not obj:
  419             return None
  420 
  421         return obj.SaImmAttrClassName
  422 
  423     def get_object_no_runtime(self, dn):
  424         """ Return the IMM object with the given dn
  425 
  426         Args:
  427             dn (str): Object dn
  428 
  429         Returns:
  430             ImmObject: Imm object
  431         """
  432         _, obj = self.accessor.get(dn, ['SA_IMM_SEARCH_GET_CONFIG_ATTR'])
  433         return obj
  434 
  435     def get_available_classes_in_imm(self):
  436         """ Return a list of all available classes in IMM
  437 
  438         Returns:
  439             list: List of available classes
  440         """
  441         _, opensaf_imm = self.accessor.get(OPENSAF_IMM_OBJECT)
  442         return opensaf_imm.opensafImmClassNames
  443 
  444     def create_non_existing_imm_object(self, class_name, parent_name,
  445                                        attributes):
  446         """ Create an ImmObject instance for an object that has not yet existed
  447         in IMM
  448 
  449         Args:
  450             class_name (str): Class name
  451             parent_name (str): Parent name
  452             attributes (dict): Dictionary of class attributes
  453 
  454         Returns:
  455             ImmObject: Imm object
  456         """
  457         rdn_attribute = self.imm_om.get_rdn_attribute_for_class(class_name)
  458         rdn_value = attributes[rdn_attribute][0]
  459 
  460         if parent_name:
  461             dn = '%s,%s' % (rdn_value, parent_name)
  462         else:
  463             dn = rdn_value
  464 
  465         obj = ImmObject(class_name=class_name, dn=dn)
  466 
  467         for name, values in attributes.items():
  468             obj.__setattr__(name, values)
  469 
  470         obj.__setattr__('SaImmAttrClassName', class_name)
  471         obj.__setattr__('dn', dn)
  472 
  473         return obj