Hi Hans, Anders and Srinivas,
Happy new year !!! I wish you will be healthy and happiness in 2018. I already answered Hans's question, how can I test for this patch. Please spend a little time help me review for this patch. Ticket-2681 <https://sourceforge.net/p/opensaf/tickets/2681/> depends on this patch. Regards, Hieu -----Original Message----- From: Hieu Nguyen [mailto:[email protected]] Sent: Wednesday, December 20, 2017 8:16 AM To: 'Hans Nordebäck' <[email protected]>; '[email protected]' <[email protected]>; '[email protected]' <[email protected]> Cc: '[email protected]' <[email protected]> Subject: RE: [PATCH 1/1] pyosaf: refactor IMM utils [#2683] Hi Hans, Thank for your reply. I have been modified /samples in pyosaf to test. That's in attached file. Regards, Hieu -----Original Message----- From: Hans Nordebäck [ <mailto:[email protected]> mailto:[email protected]] Sent: Tuesday, December 19, 2017 10:19 PM To: Hieu Nguyen < <mailto:[email protected]> [email protected]>; <mailto:[email protected]> [email protected]; <mailto:[email protected]> [email protected] Cc: <mailto:[email protected]> [email protected] Subject: Re: [PATCH 1/1] pyosaf: refactor IMM utils [#2683] Hi Hieu, before I start reviewing, a question, how has this patch been tested? /Regards HansN On 12/19/2017 06:17 AM, Hieu Nguyen wrote: > + improve OI utils use a separate instance OM agent > + refactor OM utils with Ccb inheritace OmAgent, rename some classes... > --- > python/pyosaf/utils/immoi/__init__.py | 531 > +++++++------------------------ > python/pyosaf/utils/immoi/agent.py | 473 +++++++++++++++++++++++++++ > python/pyosaf/utils/immoi/implementer.py | 145 +++++---- > python/pyosaf/utils/immom/__init__.py | 7 +- > python/pyosaf/utils/immom/accessor.py | 31 +- > python/pyosaf/utils/immom/agent.py | 31 +- > python/pyosaf/utils/immom/ccb.py | 71 +---- > python/pyosaf/utils/immom/iterator.py | 4 +- > python/pyosaf/utils/immom/object.py | 4 +- > 9 files changed, 738 insertions(+), 559 deletions(-) > create mode 100644 python/pyosaf/utils/immoi/agent.py > > diff --git a/python/pyosaf/utils/immoi/__init__.py > b/python/pyosaf/utils/immoi/__init__.py > index 1b4dece..7247b0e 100644 > --- a/python/pyosaf/utils/immoi/__init__.py > +++ b/python/pyosaf/utils/immoi/__init__.py > @@ -22,298 +22,23 @@ Supported functions: > - Set/clear/release implementer for class/object > - Create/delete/update runtime object > - Get class/object attributes > -- Get IMM error strings > +- Get/set IMM error strings > +- Get parent for dn > +- Get class for dn > +- Get objects for class > +- Get available classes of IMM > """ > from __future__ import print_function > -from copy import deepcopy > -from ctypes import c_char_p, c_void_p, cast, pointer > - > -from pyosaf.saAis import SaStringT, SaVersionT, SaNameT, SaSelectionObjectT, > \ > - unmarshalSaStringTArray, eSaDispatchFlagsT, eSaAisErrorT > -from pyosaf import saImm, saImmOi > -from pyosaf.saImm import unmarshalSaImmValue, SaImmAttrNameT, \ > - SaImmAttrValuesT_2, SaImmClassNameT, SaImmSearchParametersT_2, \ > - eSaImmValueTypeT, SaImmAttrDefinitionT_2, SaImmClassCategoryT, \ > - SaImmAttrModificationT_2, eSaImmAttrModificationTypeT > -from pyosaf.saImmOi import SaImmOiHandleT, SaImmOiImplementerNameT > -from pyosaf.utils import immom, log_err, bad_handle_retry, decorate, \ > - deprecate, initialize_decorate, SafException > + > +from pyosaf.saAis import SaSelectionObjectT, eSaAisErrorT > +from pyosaf.utils import deprecate, SafException > from pyosaf.utils.immom.object import ImmObject > -from pyosaf.utils.immom.ccb import marshal_c_array > -from pyosaf.utils.immom.iterator import SearchIterator > +from pyosaf.utils.immoi.agent import OiAgent > > > -OPENSAF_IMM_OBJECT = "opensafImm=opensafImm,safApp=safImmService" > _oi_agent = None > > > -# Decorate pure saImmOi* API's with error-handling retry and exception > raising > -saImmOiInitialize_2 = initialize_decorate(saImmOi.saImmOiInitialize_2) > -saImmOiSelectionObjectGet = decorate(saImmOi.saImmOiSelectionObjectGet) > -saImmOiDispatch = decorate(saImmOi.saImmOiDispatch) > -saImmOiFinalize = decorate(saImmOi.saImmOiFinalize) > -saImmOiImplementerSet = decorate(saImmOi.saImmOiImplementerSet) > -saImmOiImplementerClear = decorate(saImmOi.saImmOiImplementerClear) > -saImmOiClassImplementerSet = decorate(saImmOi.saImmOiClassImplementerSet) > -saImmOiClassImplementerRelease = \ > - decorate(saImmOi.saImmOiClassImplementerRelease) > -saImmOiObjectImplementerSet = decorate(saImmOi.saImmOiObjectImplementerSet) > -saImmOiObjectImplementerRelease = \ > - decorate(saImmOi.saImmOiObjectImplementerRelease) > -saImmOiRtObjectCreate_2 = decorate(saImmOi.saImmOiRtObjectCreate_2) > -saImmOiRtObjectDelete = decorate(saImmOi.saImmOiRtObjectDelete) > -saImmOiRtObjectUpdate_2 = decorate(saImmOi.saImmOiRtObjectUpdate_2) > -saImmOiAdminOperationResult = decorate(saImmOi.saImmOiAdminOperationResult) > -saImmOiAdminOperationResult_o2 = \ > - decorate(saImmOi.saImmOiAdminOperationResult_o2) > -saImmOiAugmentCcbInitialize = decorate(saImmOi.saImmOiAugmentCcbInitialize) > -saImmOiCcbSetErrorString = decorate(saImmOi.saImmOiCcbSetErrorString) > - > - > -class OiAgent(object): > - """ This class acts as a high-level OI agent, providing OI functions to > - the users as a higher level, and relieving the users of the need to > manage > - the life cycle of the OI agent and providing general interface for > - Implementer or Applier used > - """ > - def __init__(self, version=None): > - """ Constructor for OiAgent class > - > - Args: > - version (SaVersionT): OI API version > - """ > - self.handle = None > - self.init_version = version if version is not None \ > - else SaVersionT('A', 2, 15) > - self.version = None > - self.selection_object = None > - self.callbacks = None > - global _oi_agent > - _oi_agent = self > - > - def _fetch_sel_obj(self): > - """ Obtain a selection object (OS file descriptor) > - > - Returns: > - SaAisErrorT: Return code of the saImmOiSelectionObjectGet() API > - """ > - rc = saImmOiSelectionObjectGet(self.handle, self.selection_object) > - if rc != eSaAisErrorT.SA_AIS_OK: > - log_err("saImmOiSelectionObjectGet FAILED - %s" % > - eSaAisErrorT.whatis(rc)) > - > - return rc > - > - def initialize(self, callbacks=None): > - """ Initialize the IMM OI agent > - > - Args: > - callbacks (SaImmOiCallbacksT_2): OI callbacks to register with > IMM > - > - Returns: > - SaAisErrorT: Return code of OI initialize > - """ > - self.handle = SaImmOiHandleT() > - self.selection_object = SaSelectionObjectT() > - if callbacks is not None: > - self.callbacks = callbacks > - self.version = deepcopy(self.init_version) > - rc = saImmOiInitialize_2(self.handle, self.callbacks, > - self.version) > - if rc == eSaAisErrorT.SA_AIS_OK: > - rc = self._fetch_sel_obj() > - if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > - rc = self.re_initialize() > - else: > - log_err("saImmOiInitialize_2 FAILED - %s" % > - eSaAisErrorT.whatis(rc)) > - > - return rc > - > - @bad_handle_retry > - def re_initialize(self): > - """ Re-initialize the IMM OI agent > - > - Returns: > - SaAisErrorT: Return code of OI initialize > - """ > - self.finalize() > - rc = self.initialize() > - > - return rc > - > - def finalize(self): > - """ Finalize IMM OI agent handle > - > - Returns: > - SaAisErrorT: Return code of OI finalize > - """ > - rc = eSaAisErrorT.SA_AIS_OK > - if self.handle is not None: > - rc = saImmOiFinalize(self.handle) > - if rc != eSaAisErrorT.SA_AIS_OK: > - log_err("saImmOiFinalize FAILED - %s" % > - eSaAisErrorT.whatis(rc)) > - elif rc == eSaAisErrorT.SA_AIS_OK \ > - or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > - # If the Finalize() call returned BAD_HANDLE, the handle > should > - # already become stale and invalid, so we reset it anyway. > - self.handle = None > - return rc > - > - def get_selection_object(self): > - """ Return the selection object associating with the OI handle > - > - Returns: > - SaSelectionObjectT: Selection object associated with the OI > handle > - """ > - return self.selection_object > - > - def dispatch(self, flags=eSaDispatchFlagsT.SA_DISPATCH_ALL): > - """ Dispatch all queued callbacks > - > - Args: > - flags (eSaDispatchFlagsT): Flags specifying dispatch mode > - > - Returns: > - SaAisErrorT: Return code of OI dispatch > - """ > - rc = saImmOiDispatch(self.handle, flags) > - return rc > - > - def create_runtime_object(self, class_name, parent_name, runtime_obj): > - """ Create a runtime object > - > - Args: > - class_name (str): Class name > - parent_name (str): Parent name > - runtime_obj (ImmObject): Runtime object to create > - > - Returns: > - SaAisErrorT: Return code of OI create runtime object > - """ > - # Marshall parameters > - c_class_name = SaImmClassNameT(class_name) > - if parent_name: > - c_parent_name = SaNameT(parent_name) > - else: > - c_parent_name = None > - > - c_attr_values = [] > - > - for name, (c_attr_type, values) in runtime_obj.attrs.items(): > - if values is None: > - values = [] > - elif values == [None]: > - values = [] > - > - # Make sure all values are in lists > - if not isinstance(values, list): > - values = [values] > - > - # Create the values struct > - c_attr = SaImmAttrValuesT_2() > - c_attr.attrName = SaImmAttrNameT(name) > - c_attr.attrValueType = c_attr_type > - c_attr.attrValuesNumber = len(values) > - > - if not values: > - c_attr.attrValues = None > - else: > - c_attr.attrValues = marshal_c_array(c_attr_type, values) > - > - c_attr_values.append(c_attr) > - > - rc = saImmOiRtObjectCreate_2(self.handle, c_class_name, > - c_parent_name, c_attr_values) > - return rc > - > - def delete_runtime_object(self, dn): > - """ Delete a runtime object > - > - Args: > - dn (str): Runtime object dn > - > - Returns: > - SaAisErrorT: Return code of OI delete runtime object > - """ > - # Marshall the parameter > - c_dn = SaNameT(dn) > - rc = saImmOiRtObjectDelete(self.handle, c_dn) > - > - return rc > - > - def update_runtime_object(self, dn, attributes): > - """ Update the specified object with the requested attribute > - modifications > - > - Args: > - dn (str): Object dn > - attributes (dict): Dictionary of attribute modifications > - > - Returns: > - SaAisErrorT: Return code of OI update runtime object > - """ > - # Get the class name for the object > - class_name = get_class_name_for_dn(dn) > - > - # Create and marshall attribute modifications > - attr_mods = [] > - > - for name, values in attributes.items(): > - if values is None: > - print("WARNING: Received no values for %s in %s" % (name, > dn)) > - continue > - if not isinstance(values, list): > - values = [values] > - > - attr_type = get_attribute_type(name, class_name) > - c_attr_mod = SaImmAttrModificationT_2() > - c_attr_mod.modType = \ > - eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_REPLACE > - c_attr_mod.modAttr = SaImmAttrValuesT_2() > - c_attr_mod.modAttr.attrName = SaImmAttrNameT(name) > - c_attr_mod.modAttr.attrValueType = attr_type > - c_attr_mod.modAttr.attrValuesNumber = len(values) > - c_attr_mod.modAttr.attrValues = marshal_c_array(attr_type, > values) > - attr_mods.append(c_attr_mod) > - > - rc = saImmOiRtObjectUpdate_2(self.handle, SaNameT(dn), attr_mods) > - > - return rc > - > - def report_admin_operation_result(self, invocation_id, result): > - """ Report the result of an administrative operation > - > - Args: > - invocation_id (SaInvocationT): Invocation id > - result (SaAisErrorT): Result of admin operation > - > - Returns: > - SaAisErrorT: Return code of OI admin operation > - """ > - rc = saImmOiAdminOperationResult(self.handle, invocation_id, > - result) > - > - return rc > - > - def set_error_string(self, ccb_id, error_string): > - """ Set the error string > - This can only be called from within OI callbacks of a real > implementer. > - > - Args: > - ccb_id (SaImmOiCcbIdT): CCB id > - error_string (str): Error string > - > - Returns: > - SaAisErrorT: Return code of OI CCB set error string > - """ > - c_error_string = SaStringT(error_string) > - rc = saImmOiCcbSetErrorString(self.handle, ccb_id, c_error_string) > - > - return rc > - > - > # Keep old user interfaces of OI pyosaf utils > @deprecate > def initialize(callbacks=None): > @@ -327,8 +52,8 @@ def initialize(callbacks=None): > is not SA_AIS_OK > """ > global _oi_agent > - if _oi_agent is None: > - _oi_agent = OiAgent() > + _oi_agent = OiAgent() > + > rc = _oi_agent.initialize(callbacks=callbacks) > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) > @@ -342,10 +67,9 @@ def get_selection_object(): > SaSelectionObjectT: Return code of selection object get > > Raises: > - SafException: If the return code of the corresponding OI API call(s) > - is not SA_AIS_OK > + SafException: If the OI agent is not initialized > """ > - if _oi_agent is not None: > + if _oi_agent is None: > # SA_AIS_ERR_INIT is returned if user calls this function without > first > # calling initialize() > raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > @@ -363,11 +87,16 @@ def create_rt_object(class_name, parent_name, > runtime_obj): > runtime_obj (ImmObject): Runtime object to create > > Raises: > - SafException: If the return code of the corresponding OI API call(s) > - is not SA_AIS_OK > + SafException: If the OI agent is not initialized > """ > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + rc = eSaAisErrorT.SA_AIS_ERR_INIT > + else: > + rc = _oi_agent.create_runtime_object(class_name, parent_name, > + runtime_obj) > > - rc = _oi_agent.create_runtime_object(class_name, parent_name, > runtime_obj) > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) > > @@ -380,10 +109,15 @@ def delete_rt_object(dn): > dn (str): Runtime object dn > > Raises: > - SafException: If the return code of the corresponding OI API call(s) > - is not SA_AIS_OK > + SafException: If the OI agent is not initialized > """ > - rc = _oi_agent.delete_runtime_object(dn) > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + rc = eSaAisErrorT.SA_AIS_ERR_INIT > + else: > + rc = _oi_agent.delete_runtime_object(dn) > + > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) > > @@ -398,10 +132,15 @@ def update_rt_object(dn, attributes): > attributes (dict): Dictionary of attribute modifications > > Raises: > - SafException: If the return code of the corresponding OI API call(s) > - is not SA_AIS_OK > + SafException: If the OI agent is not initialized > """ > - rc = _oi_agent.update_runtime_object(dn, attributes) > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + rc = eSaAisErrorT.SA_AIS_ERR_INIT > + else: > + rc = _oi_agent.update_runtime_object(dn, attributes) > + > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) > > @@ -415,10 +154,15 @@ def report_admin_operation_result(invocation_id, > result): > result (SaAisErrorT): Result of admin operation > > Raises: > - SafException: If the return code of the corresponding OI API call(s) > - is not SA_AIS_OK > + SafException: If the OI agent is not initialized > """ > - rc = _oi_agent.report_admin_operation_result(invocation_id, result) > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + rc = eSaAisErrorT.SA_AIS_ERR_INIT > + else: > + rc = _oi_agent.report_admin_operation_result(invocation_id, result) > + > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) > > @@ -433,26 +177,20 @@ def set_error_string(ccb_id, error_string): > error_string (str): Error string > > Raises: > - SafException: If the return code of the corresponding OI API call(s) > - is not SA_AIS_OK > + SafException: If the OI agent is not initialized > """ > - rc = _oi_agent.set_error_string(ccb_id, error_string) > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + rc = eSaAisErrorT.SA_AIS_ERR_INIT > + else: > + rc = _oi_agent.set_error_string(ccb_id, error_string) > + > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) > > > -def get_class_category(class_name): > - """ Return the category of the given class > - > - Args: > - class_name (str): Class name > - > - Returns: > - SaImmClassCategoryT: Class category > - """ > - return immom.get_class_category(class_name) > - > - > +@deprecate > def get_parent_name_for_dn(dn): > """ Return the parent's dn of the given object's dn > > @@ -461,13 +199,19 @@ def get_parent_name_for_dn(dn): > > Returns: > str: DN of the object's parent > + > + Raises: > + SafException: If the OI agent is not initialized > """ > - if ',' in dn: > - return dn.split(',', 1)[1] > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > > - return "" > + return _oi_agent.get_parent_name_for_dn(dn) > > > +@deprecate > def get_object_names_for_class(class_name): > """ Return instances of the given class > > @@ -476,28 +220,19 @@ def get_object_names_for_class(class_name): > > Returns: > list: List of object names > + > + Raises: > + SafException: If the OI agent is not initialized > """ > - # Marshall the search parameter > - c_class_name = c_char_p(class_name) > - c_search_param = SaImmSearchParametersT_2() > - c_search_param.searchOneAttr.attrName = "SaImmAttrClassName" > - c_search_param.searchOneAttr.attrValueType = \ > - eSaImmValueTypeT.SA_IMM_ATTR_SASTRINGT > - c_search_param.searchOneAttr.attrValue = \ > - cast(pointer(c_class_name), c_void_p) > - > - # Create the search iterator > - found_objs = SearchIterator(search_param=c_search_param, > - attribute_names=['SaImmAttrClassName']) > - found_objs.init() > - # Return the dn's of found objects > - object_names = [] > - for obj in found_objs: > - object_names.append(obj.dn) > - > - return object_names > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > + > + return _oi_agent.get_object_names_for_class(class_name) > > > +@deprecate > def get_class_name_for_dn(dn): > """ Return the class name for an instance with the given dn > > @@ -506,14 +241,19 @@ def get_class_name_for_dn(dn): > > Returns: > str: Class name > + > + Raises: > + SafException: If the OI agent is not initialized > """ > - obj = immom.get(dn, ["SaImmAttrClassName"]) > - if not obj: > - return None > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > > - return obj.SaImmAttrClassName > + return _oi_agent.get_class_name_for_dn(dn) > > > +@deprecate > def get_object_no_runtime(dn): > """ Return the IMM object with the given dn > > @@ -522,10 +262,19 @@ def get_object_no_runtime(dn): > > Returns: > ImmObject: Imm object > + > + Raises: > + SafException: If the OI agent is not initialized > """ > - return immom.get(dn, ['SA_IMM_SEARCH_GET_CONFIG_ATTR']) > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > > + return _oi_agent.get_object_no_runtime(dn) > > + > +@deprecate > def get_attribute_type(attribute, class_name): > """ Return the type of the attribute in the given class > > @@ -535,72 +284,37 @@ def get_attribute_type(attribute, class_name): > > Returns: > str: Attribute type > - """ > - class_desc = immom.class_description_get(class_name) > - attr_desc = [attr for attr in class_desc if > - attr.attrName == attribute][0] > - > - return attr_desc.attrValueType > > - > -def get_rdn_attribute_for_class(class_name): > - """ Return the RDN attribute for the given class > - > - Args: > - class_name (str): Class name > - > - Returns: > - str: RDN of the class > + Raises: > + SafException: If the OI agent is not initialized > """ > - desc = immom.class_description_get(class_name) > - > - for attr_desc in desc: > - if attr_desc.attrFlags & saImm.saImm.SA_IMM_ATTR_RDN: > - return attr_desc.attrName > - > - return None > - > - > -def unmarshal_len_array(c_array, length, value_type): > - """ Convert C array with a known length to a Python list > - > - Args: > - c_array (C array): Array in C > - length (int): Length of array > - value_type (str): Element type in array > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > > - Returns: > - list: The list converted from c_array > - """ > - if not c_array: > - return [] > - ctype = c_array[0].__class__ > - if ctype is str: > - return unmarshalSaStringTArray(c_array) > - val_list = [] > - i = 0 > - for ptr in c_array: > - if i == length: > - break > - if not ptr: > - break > - val = unmarshalSaImmValue(ptr, value_type) > - val_list.append(val) > - i = i + 1 > - > - return val_list > + return _oi_agent.get_attribute_type(attribute, class_name) > > > +@deprecate > def get_available_classes_in_imm(): > """ Return a list of all available classes in IMM > > Returns: > list: List of available classes > + > + Raises: > + SafException: If the OI agent is not initialized > """ > - opensaf_imm = immom.get(OPENSAF_IMM_OBJECT) > - return opensaf_imm.opensafImmClassNames > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > > + return _oi_agent.get_available_classes_in_imm() > > + > +@deprecate > def create_non_existing_imm_object(class_name, parent_name, > attributes): > """ Create an ImmObject instance for an object that has not yet existed > @@ -613,21 +327,14 @@ def create_non_existing_imm_object(class_name, > parent_name, > > Returns: > ImmObject: Imm object > - """ > - rdn_attribute = get_rdn_attribute_for_class(class_name) > - rdn_value = attributes[rdn_attribute][0] > - > - if parent_name: > - dn = '%s,%s' % (rdn_value, parent_name) > - else: > - dn = rdn_value > - > - obj = ImmObject(class_name=class_name, dn=dn) > > - for name, values in attributes.items(): > - obj.__setattr__(name, values) > - > - obj.__setattr__('SaImmAttrClassName', class_name) > - obj.__setattr__('dn', dn) > + Raises: > + SafException: If the OI agent is not initialized > + """ > + if _oi_agent is None: > + # SA_AIS_ERR_INIT is returned if user calls this function without > first > + # calling initialize() > + raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT) > > - return obj > + return _oi_agent.create_non_existing_imm_object(class_name, parent_name, > + attributes) > diff --git a/python/pyosaf/utils/immoi/agent.py > b/python/pyosaf/utils/immoi/agent.py > new file mode 100644 > index 0000000..1e34b4f > --- /dev/null > +++ b/python/pyosaf/utils/immoi/agent.py > @@ -0,0 +1,473 @@ > +############################################################################ > +# > +# (C) Copyright 2015 The OpenSAF Foundation > +# (C) Copyright 2017 Ericsson AB. All rights reserved. > +# > +# This program is distributed in the hope that it will be useful, but > +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY > +# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed > +# under the GNU Lesser General Public License Version 2.1, February 1999. > +# The complete license can be accessed from the following location: > +# <http://opensource.org/licenses/lgpl-license.php> > http://opensource.org/licenses/lgpl-license.php > +# See the Copying file included with the OpenSAF distribution for full > +# licensing terms. > +# > +# Author(s): Ericsson > +# > +############################################################################ > +""" > +IMM OI common utilities > + > +Supported functions: > +- Set/clear/release implementer for class/object > +- Create/delete/update runtime object > +- Get class/object attributes > +- Get IMM error strings > +""" > +from __future__ import print_function > +from copy import deepcopy > +from ctypes import c_char_p, c_void_p, cast, pointer > + > +from pyosaf.saAis import SaStringT, SaVersionT, SaNameT, SaSelectionObjectT, > \ > + eSaDispatchFlagsT, eSaAisErrorT > +from pyosaf import saImmOi > +from pyosaf.saImm import SaImmAttrNameT, SaImmAttrValuesT_2, > SaImmClassNameT, \ > + SaImmSearchParametersT_2, eSaImmValueTypeT, SaImmAttrModificationT_2, \ > + eSaImmAttrModificationTypeT > +from pyosaf.saImmOi import SaImmOiHandleT > +from pyosaf.utils import log_err, bad_handle_retry, decorate, \ > + initialize_decorate > +from pyosaf.utils.immom.object import ImmObject > +from pyosaf.utils.immom.ccb import marshal_c_array > +from pyosaf.utils.immom.iterator import SearchIterator > +from pyosaf.utils.immom.agent import OmAgent > +from pyosaf.utils.immom.accessor import Accessor > + > + > +OPENSAF_IMM_OBJECT = "opensafImm=opensafImm,safApp=safImmService" > + > + > +# Decorate pure saImmOi* API's with error-handling retry and exception > raising > +saImmOiInitialize_2 = initialize_decorate(saImmOi.saImmOiInitialize_2) > +saImmOiSelectionObjectGet = decorate(saImmOi.saImmOiSelectionObjectGet) > +saImmOiDispatch = decorate(saImmOi.saImmOiDispatch) > +saImmOiFinalize = decorate(saImmOi.saImmOiFinalize) > +saImmOiImplementerSet = decorate(saImmOi.saImmOiImplementerSet) > +saImmOiImplementerClear = decorate(saImmOi.saImmOiImplementerClear) > +saImmOiClassImplementerSet = decorate(saImmOi.saImmOiClassImplementerSet) > +saImmOiClassImplementerRelease = \ > + decorate(saImmOi.saImmOiClassImplementerRelease) > +saImmOiObjectImplementerSet = decorate(saImmOi.saImmOiObjectImplementerSet) > +saImmOiObjectImplementerRelease = \ > + decorate(saImmOi.saImmOiObjectImplementerRelease) > +saImmOiRtObjectCreate_2 = decorate(saImmOi.saImmOiRtObjectCreate_2) > +saImmOiRtObjectDelete = decorate(saImmOi.saImmOiRtObjectDelete) > +saImmOiRtObjectUpdate_2 = decorate(saImmOi.saImmOiRtObjectUpdate_2) > +saImmOiAdminOperationResult = decorate(saImmOi.saImmOiAdminOperationResult) > +saImmOiAdminOperationResult_o2 = \ > + decorate(saImmOi.saImmOiAdminOperationResult_o2) > +saImmOiAugmentCcbInitialize = decorate(saImmOi.saImmOiAugmentCcbInitialize) > +saImmOiCcbSetErrorString = decorate(saImmOi.saImmOiCcbSetErrorString) > + > + > +class OiAgent(object): > + """ This class acts as a high-level OI agent, providing OI functions to > + the users as a higher level, and relieving the users of the need to > manage > + the life cycle of the OI agent and providing general interface for > + Implementer or Applier used > + """ > + def __init__(self, version=None): > + """ Constructor for OiAgent class > + > + Args: > + version (SaVersionT): OI API version > + """ > + self.handle = None > + self.init_version = version if version is not None \ > + else SaVersionT('A', 2, 15) > + self.version = None > + self.selection_object = None > + self.callbacks = None > + self.imm_om = None > + self.accessor = None > + > + def _fetch_sel_obj(self): > + """ Obtain a selection object (OS file descriptor) > + > + Returns: > + SaAisErrorT: Return code of the saImmOiSelectionObjectGet() API > + """ > + rc = saImmOiSelectionObjectGet(self.handle, self.selection_object) > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiSelectionObjectGet FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + > + return rc > + > + def initialize(self, callbacks=None): > + """ Initialize the IMM OI agent > + > + Args: > + callbacks (SaImmOiCallbacksT_2): OI callbacks to register with > IMM > + > + Returns: > + SaAisErrorT: Return code of OI initialize > + """ > + self.imm_om = OmAgent(self.init_version) > + rc = self.imm_om.init() > + > + if rc == eSaAisErrorT.SA_AIS_OK: > + if not self.accessor: > + self.accessor = Accessor(self.init_version) > + rc = self.accessor.init() > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOmAccessorInitialize FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + return rc > + > + self.handle = SaImmOiHandleT() > + self.selection_object = SaSelectionObjectT() > + if callbacks is not None: > + self.callbacks = callbacks > + self.version = deepcopy(self.init_version) > + rc = saImmOiInitialize_2(self.handle, self.callbacks, > + self.version) > + if rc == eSaAisErrorT.SA_AIS_OK: > + rc = self._fetch_sel_obj() > + if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > + rc = self.re_initialize() > + else: > + log_err("saImmOiInitialize_2 FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + else: > + log_err("saImmOmInitialize FAILED - %s" % > eSaAisErrorT.whatis(rc)) > + > + return rc > + > + @bad_handle_retry > + def re_initialize(self): > + """ Re-initialize the IMM OI agent > + > + Returns: > + SaAisErrorT: Return code of OI initialize > + """ > + self.finalize() > + rc = self.initialize() > + > + return rc > + > + def finalize(self): > + """ Finalize IMM OI agent handle > + > + Returns: > + SaAisErrorT: Return code of OI finalize > + """ > + rc = eSaAisErrorT.SA_AIS_OK > + if self.handle is not None: > + rc = saImmOiFinalize(self.handle) > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiFinalize FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + > + if rc == eSaAisErrorT.SA_AIS_OK \ > + or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > + # If the Finalize() call returned BAD_HANDLE, the handle > should > + # already become stale and invalid, so we reset it anyway. > + self.handle = None > + return rc > + > + def get_selection_object(self): > + """ Return the selection object associating with the OI handle > + > + Returns: > + SaSelectionObjectT: Selection object associated with the OI > handle > + """ > + return self.selection_object > + > + def dispatch(self, flags=eSaDispatchFlagsT.SA_DISPATCH_ALL): > + """ Dispatch all queued callbacks > + > + Args: > + flags (eSaDispatchFlagsT): Flags specifying dispatch mode > + > + Returns: > + SaAisErrorT: Return code of OI dispatch > + """ > + rc = saImmOiDispatch(self.handle, flags) > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiDispatch FAILED - %s" % eSaAisErrorT.whatis(rc)) > + return rc > + > + def create_runtime_object(self, class_name, parent_name, runtime_obj): > + """ Create a runtime object > + > + Args: > + class_name (str): Class name > + parent_name (str): Parent name > + runtime_obj (ImmObject): Runtime object to create > + > + Returns: > + SaAisErrorT: Return code of OI create runtime object > + """ > + # Marshall parameters > + c_class_name = SaImmClassNameT(class_name) > + if parent_name: > + c_parent_name = SaNameT(parent_name) > + else: > + c_parent_name = None > + > + c_attr_values = [] > + > + for name, (c_attr_type, values) in runtime_obj.attrs.items(): > + if values is None: > + values = [] > + elif values == [None]: > + values = [] > + > + # Make sure all values are in lists > + if not isinstance(values, list): > + values = [values] > + > + # Create the values struct > + c_attr = SaImmAttrValuesT_2() > + c_attr.attrName = SaImmAttrNameT(name) > + c_attr.attrValueType = c_attr_type > + c_attr.attrValuesNumber = len(values) > + > + if not values: > + c_attr.attrValues = None > + else: > + c_attr.attrValues = marshal_c_array(c_attr_type, values) > + > + c_attr_values.append(c_attr) > + > + rc = saImmOiRtObjectCreate_2(self.handle, c_class_name, > + c_parent_name, c_attr_values) > + > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiRtObjectCreate_2 FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + return rc > + > + def delete_runtime_object(self, dn): > + """ Delete a runtime object > + > + Args: > + dn (str): Runtime object dn > + > + Returns: > + SaAisErrorT: Return code of OI delete runtime object > + """ > + # Marshall the parameter > + c_dn = SaNameT(dn) > + rc = saImmOiRtObjectDelete(self.handle, c_dn) > + > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiRtObjectDelete FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + return rc > + > + def update_runtime_object(self, dn, attributes): > + """ Update the specified object with the requested attribute > + modifications > + > + Args: > + dn (str): Object dn > + attributes (dict): Dictionary of attribute modifications > + > + Returns: > + SaAisErrorT: Return code of OI update runtime object > + """ > + # Get the class name for the object > + class_name = self.get_class_name_for_dn(dn) > + > + # Create and marshall attribute modifications > + attr_mods = [] > + > + for name, values in attributes.items(): > + if values is None: > + print("WARNING: Received no values for %s in %s" % (name, > dn)) > + continue > + if not isinstance(values, list): > + values = [values] > + > + attr_type = self.get_attribute_type(name, class_name) > + c_attr_mod = SaImmAttrModificationT_2() > + c_attr_mod.modType = \ > + eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_REPLACE > + c_attr_mod.modAttr = SaImmAttrValuesT_2() > + c_attr_mod.modAttr.attrName = SaImmAttrNameT(name) > + c_attr_mod.modAttr.attrValueType = attr_type > + c_attr_mod.modAttr.attrValuesNumber = len(values) > + c_attr_mod.modAttr.attrValues = marshal_c_array(attr_type, > values) > + attr_mods.append(c_attr_mod) > + > + rc = saImmOiRtObjectUpdate_2(self.handle, SaNameT(dn), attr_mods) > + > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiRtObjectUpdate_2 FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + return rc > + > + def report_admin_operation_result(self, invocation_id, result): > + """ Report the result of an administrative operation > + > + Args: > + invocation_id (SaInvocationT): Invocation id > + result (SaAisErrorT): Result of admin operation > + > + Returns: > + SaAisErrorT: Return code of OI admin operation > + """ > + rc = saImmOiAdminOperationResult(self.handle, invocation_id, result) > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiAdminOperationResult FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + return rc > + > + def set_error_string(self, ccb_id, error_string): > + """ Set the error string > + This can only be called from within OI callbacks of a real > implementer. > + > + Args: > + ccb_id (SaImmOiCcbIdT): CCB id > + error_string (str): Error string > + > + Returns: > + SaAisErrorT: Return code of OI CCB set error string > + """ > + c_error_string = SaStringT(error_string) > + rc = saImmOiCcbSetErrorString(self.handle, ccb_id, c_error_string) > + > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiCcbSetErrorString FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + return rc > + > + def get_attribute_type(self, attribute, class_name): > + """ Return the type of the attribute in the given class > + > + Args: > + attribute (str): Attribute name > + class_name (str): Class name > + > + Returns: > + str: Attribute type > + """ > + _, class_desc = self.imm_om.get_class_description(class_name) > + attr_desc = [attr for attr in class_desc if > + attr.attrName == attribute][0] > + > + return attr_desc.attrValueType > + > + @staticmethod > + def get_parent_name_for_dn(dn): > + """ Return the parent's dn of the given object's dn > + > + Args: > + dn (str): Object dn > + > + Returns: > + str: DN of the object's parent > + """ > + if ',' in dn: > + return dn.split(',', 1)[1] > + > + return "" > + > + @staticmethod > + def get_object_names_for_class(class_name): > + """ Return instances of the given class > + > + Args: > + class_name (str): Class name > + > + Returns: > + list: List of object names > + """ > + # Marshall the search parameter > + c_class_name = c_char_p(class_name) > + c_search_param = SaImmSearchParametersT_2() > + c_search_param.searchOneAttr.attrName = "SaImmAttrClassName" > + c_search_param.searchOneAttr.attrValueType = \ > + eSaImmValueTypeT.SA_IMM_ATTR_SASTRINGT > + c_search_param.searchOneAttr.attrValue = \ > + cast(pointer(c_class_name), c_void_p) > + > + # Create the search iterator > + found_objs = SearchIterator(search_param=c_search_param, > + attribute_names=['SaImmAttrClassName']) > + found_objs.init() > + # Return the dn's of found objects > + object_names = [] > + for obj in found_objs: > + object_names.append(obj.dn) > + > + return object_names > + > + def get_class_name_for_dn(self, dn): > + """ Return the class name for an instance with the given dn > + > + Args: > + dn (str): Object dn > + > + Returns: > + str: Class name > + """ > + _, obj = self.accessor.get(dn, ["SaImmAttrClassName"]) > + if not obj: > + return None > + > + return obj.SaImmAttrClassName > + > + def get_object_no_runtime(self, dn): > + """ Return the IMM object with the given dn > + > + Args: > + dn (str): Object dn > + > + Returns: > + ImmObject: Imm object > + """ > + _, obj = self.accessor.get(dn, ['SA_IMM_SEARCH_GET_CONFIG_ATTR']) > + return obj > + > + def get_available_classes_in_imm(self): > + """ Return a list of all available classes in IMM > + > + Returns: > + list: List of available classes > + """ > + _, opensaf_imm = self.accessor.get(OPENSAF_IMM_OBJECT) > + return opensaf_imm.opensafImmClassNames > + > + def create_non_existing_imm_object(self, class_name, parent_name, > + attributes): > + """ Create an ImmObject instance for an object that has not yet > existed > + in IMM > + > + Args: > + class_name (str): Class name > + parent_name (str): Parent name > + attributes (dict): Dictionary of class attributes > + > + Returns: > + ImmObject: Imm object > + """ > + rdn_attribute = self.imm_om.get_rdn_attribute_for_class(class_name) > + rdn_value = attributes[rdn_attribute][0] > + > + if parent_name: > + dn = '%s,%s' % (rdn_value, parent_name) > + else: > + dn = rdn_value > + > + obj = ImmObject(class_name=class_name, dn=dn) > + > + for name, values in attributes.items(): > + obj.__setattr__(name, values) > + > + obj.__setattr__('SaImmAttrClassName', class_name) > + obj.__setattr__('dn', dn) > + > + return obj > diff --git a/python/pyosaf/utils/immoi/implementer.py > b/python/pyosaf/utils/immoi/implementer.py > index da1d945..f8f66cd 100755 > --- a/python/pyosaf/utils/immoi/implementer.py > +++ b/python/pyosaf/utils/immoi/implementer.py > @@ -21,12 +21,13 @@ from __future__ import print_function > import select > import itertools > > -from pyosaf.saAis import eSaAisErrorT, unmarshalNullArray > +from pyosaf.saAis import eSaAisErrorT, unmarshalNullArray, \ > + unmarshalSaStringTArray > from pyosaf import saImm, saImmOi > from pyosaf.saImm import eSaImmValueTypeT, eSaImmAttrModificationTypeT, \ > - eSaImmClassCategoryT, SaImmClassNameT > + eSaImmClassCategoryT, SaImmClassNameT, unmarshalSaImmValue > from pyosaf.saImmOi import SaImmOiImplementerNameT > -from pyosaf.utils import immom, immoi, SafException, decorate, > bad_handle_retry > +from pyosaf.utils import SafException, decorate, bad_handle_retry, log_err > from pyosaf.utils.immoi import OiAgent > from pyosaf.utils.immom.object import ImmObject > > @@ -35,9 +36,6 @@ saImmOiClassImplementerSet = > decorate(saImmOi.saImmOiClassImplementerSet) > saImmOiImplementerSet = decorate(saImmOi.saImmOiImplementerSet) > > > -implementer_instance = None > - > - > class AdminOperationParameter(object): > """ This class represents an admin operation parameter """ > def __init__(self, name, param_type, value): > @@ -101,12 +99,13 @@ class _ContainmentConstraint(object): > self.upper = upper > > > -class Constraints(object): > +class Constraints(OiAgent): > """ Class defining constraints for changes to the instances implemented > by > the OI > """ > def __init__(self): > """ Create an empty Constraints instance """ > + super(Constraints, self).__init__() > self.containments = {} > self.cardinality = {} > > @@ -153,7 +152,7 @@ class Constraints(object): > if ',' not in child.dn: > continue > > - if immoi.get_parent_name_for_dn(child.dn) == _parent_name \ > + if self.get_parent_name_for_dn(child.dn) == _parent_name \ > and child.class_name == _class_name: > _current_children.append(child) > > @@ -170,10 +169,10 @@ class Constraints(object): > return False > > # Validate containments affected by create or delete > - deleted_objs = [immoi.get_object_no_runtime(dn) for dn in deleted] > + deleted_objs = [self.get_object_no_runtime(dn) for dn in deleted] > > for obj in itertools.chain(created, deleted_objs): > - parent_name = immoi.get_parent_name_for_dn(obj.dn) > + parent_name = self.get_parent_name_for_dn(obj.dn) > > # Handle the case where there is no parent > if not parent_name: > @@ -196,7 +195,7 @@ class Constraints(object): > if parent_obj: > parent_class = parent_obj[0].class_name > else: > - parent_class = immoi.get_class_name_for_dn(dn=parent_name) > + parent_class = self.get_class_name_for_dn(dn=parent_name) > > # Ignore children where no constraint is defined for the child > or > # the parent > @@ -244,10 +243,10 @@ class Implementer(OiAgent): > def __init__(self, class_names=None, name="wrapper", on_create=None, > on_delete=None, on_modify=None, on_validate=None, > on_apply=None, on_runtime_values_get=None, > - admin_operations=None, constraints=None): > + admin_operations=None, constraints=None, version=None): > """ Create an Implementer instance """ > # Initialize OI agent > - super(Implementer, self).__init__() > + super(Implementer, self).__init__(version=version) > > self.class_names = class_names > self.name = name > @@ -263,14 +262,43 @@ class Implementer(OiAgent): > self.ccbs = {} > self.implemented_names = [] > > - global implementer_instance > - implementer_instance = self > - > # Register OI callbacks > self._register_callbacks() > > # Initialize OI API and register as implementer for the classes > - self._register() > + rc = self._register() > + if rc != eSaAisErrorT.SA_AIS_OK: > + raise Exception("ERROR: Can't register a implementer") > + > + @staticmethod > + def unmarshal_len_array(c_array, length, value_type): > + """ Convert C array with a known length to a Python list > + > + Args: > + c_array (C array): Array in C > + length (int): Length of array > + value_type (str): Element type in array > + > + Returns: > + list: The list converted from c_array > + """ > + if not c_array: > + return [] > + ctype = c_array[0].__class__ > + if ctype is str: > + return unmarshalSaStringTArray(c_array) > + val_list = [] > + i = 0 > + for ptr in c_array: > + if i == length: > + break > + if not ptr: > + break > + val = unmarshalSaImmValue(ptr, value_type) > + val_list.append(val) > + i = i + 1 > + > + return val_list > > def _register_callbacks(self): > """ Register OI callbacks """ > @@ -297,8 +325,7 @@ class Implementer(OiAgent): > saImmOi.SaImmOiAdminOperationCallbackT_2( > self._admin_operation_callback) > > - @staticmethod > - def _admin_operation_callback(oi_handle, c_invocation_id, c_name, > + def _admin_operation_callback(self, oi_handle, c_invocation_id, c_name, > c_operation_id, c_params): > """ Callback for administrative operations > > @@ -329,12 +356,11 @@ class Implementer(OiAgent): > params.append(parameter) > > # Invoke the operation > - result = implementer_instance.admin_operation(operation_id, name, > - params) > + result = self.admin_operation(operation_id, name, params) > > # Report the result > try: > - immoi.report_admin_operation_result(invocation_id, result) > + self.report_admin_operation_result(invocation_id, result) > except SafException as err: > print("ERROR: Failed to report that %s::%s returned %s (%s)" % > (name, invocation_id, result, err.msg)) > @@ -358,11 +384,10 @@ class Implementer(OiAgent): > """ > all_instances = [] > > - for class_name in implementer_instance.class_names: > - dns = immoi.get_object_names_for_class(class_name) > + for class_name in self.class_names: > + dns = self.get_object_names_for_class(class_name) > for dn in dns: > - dn_in_str = str(dn.value) > - obj = immoi.get_object_no_runtime(dn_in_str) > + obj = self.get_object_no_runtime(dn) > all_instances.append(obj) > > updated = self.completed_ccbs[ccb_id]['updated'] > @@ -374,8 +399,7 @@ class Implementer(OiAgent): > del self.completed_ccbs[ccb_id] > > # Tell the implementer to apply the changes > - return implementer_instance.on_apply(all_instances, updated, > - created, deleted) > + return self.on_apply(all_instances, updated, created, deleted) > > def _attr_update_callback(self, oi_handle, c_name, c_attr_names): > """ Callback for attribute update operation > @@ -395,15 +419,13 @@ class Implementer(OiAgent): > attr_names = unmarshalNullArray(c_attr_names) > > # Get the class of the object > - class_name = immoi.get_class_name_for_dn(dn=name) > + class_name = self.get_class_name_for_dn(dn=name) > > # Get the values from the user and report back > attributes = {} > > for attr_name in attr_names: > - values = implementer_instance.on_runtime_values_get(name, > - class_name, > - attr_name) > + values = self.on_runtime_values_get(name, class_name, attr_name) > if values is None: > return eSaAisErrorT.SA_AIS_ERR_UNAVAILABLE > if not isinstance(values, list): > @@ -442,7 +464,7 @@ class Implementer(OiAgent): > self.ccbs[ccb_id].append({'type': 'DELETE', 'dn': name}) > > # Tell the implementer about the operation > - return implementer_instance.on_delete_added(name) > + return self.on_delete_added(name) > > def _ccb_modify_callback(self, oi_handle, ccb_id, c_name, > c_attr_modification): > @@ -470,7 +492,7 @@ class Implementer(OiAgent): > attr_name = attr.modAttr.attrName > attr_type = attr.modAttr.attrValueType > mod_type = attr.modType > - attr_values = immoi.unmarshal_len_array( > + attr_values = self.unmarshal_len_array( > attr.modAttr.attrValues, attr.modAttr.attrValuesNumber, > attr.modAttr.attrValueType) > attribute_modifications.append({'attribute': attr_name, > @@ -479,8 +501,7 @@ class Implementer(OiAgent): > 'values': attr_values}) > > # Tell the implementer about the modification > - result = implementer_instance.on_modify_added(attr_name, > mod_type, > - attr_values) > + result = self.on_modify_added(attr_name, mod_type, attr_values) > if result != eSaAisErrorT.SA_AIS_OK: > implementer_objection = result > > @@ -524,16 +545,15 @@ class Implementer(OiAgent): > attr_type = attr.attrValueType > nr_values = attr.attrValuesNumber > > - attr_values = immoi.unmarshal_len_array(attr.attrValues, > - nr_values, > - attr_type) > + attr_values = self.unmarshal_len_array(attr.attrValues, > + nr_values, attr_type) > if attr_values: > attributes[attr_name] = attr_values > else: > attributes[attr_name] = None > > # Fill in any missing attributes > - description = immom.class_description_get(class_name) > + _, description = self.imm_om.get_class_description(class_name) > > for attribute in description: > if attribute.attrName not in attributes: > @@ -550,10 +570,10 @@ class Implementer(OiAgent): > 'attributes': attributes}) > > # Tell the implementer about the operation > - obj = immoi.create_non_existing_imm_object(class_name, parent, > - attributes) > + obj = self.create_non_existing_imm_object(class_name, parent, > + attributes) > > - return implementer_instance.on_create_added(class_name, parent, obj) > + return self.on_create_added(class_name, parent, obj) > > def _ccb_completed_callback(self, oi_handle, ccb_id): > """ Callback for completed CCB > @@ -581,8 +601,7 @@ class Implementer(OiAgent): > 'updated': updated} > > # Perform validation on the full transaction > - return implementer_instance.validate(ccb_id, instances, updated, > - created, deleted) > + return self.validate(ccb_id, instances, updated, created, deleted) > > def _collect_full_transaction(self, ccb_id): > """ Go through a completed CCB and summarize the full transaction as > @@ -605,11 +624,10 @@ class Implementer(OiAgent): > updated = [] > > # Go through current instances > - for class_name in implementer_instance.class_names: > - dns = immoi.get_object_names_for_class(class_name) > + for class_name in self.class_names: > + dns = self.get_object_names_for_class(class_name) > for dn in dns: > - dn_in_str = str(dn.value) > - obj = immoi.get_object_no_runtime(dn_in_str) > + obj = self.get_object_no_runtime(dn) > all_objects_now.append(obj) > > # Collect proposed state by applying changes on current state > @@ -621,7 +639,7 @@ class Implementer(OiAgent): > parent = operation['parent'] > class_name = operation['className'] > attributes = operation['attributes'] > - rdn_attr = immoi.get_rdn_attribute_for_class( > + rdn_attr = self.imm_om.get_rdn_attribute_for_class( > class_name=class_name) > rdn_value = attributes[rdn_attr][0] > > @@ -630,7 +648,7 @@ class Implementer(OiAgent): > else: > dn = rdn_value > > - instance = immoi.create_non_existing_imm_object( > + instance = self.create_non_existing_imm_object( > class_name, parent, attributes) > created.append(instance) > deleted = [obj for obj in deleted if obj.dn != dn] > @@ -725,6 +743,9 @@ class Implementer(OiAgent): > rc = saImmOiClassImplementerSet(self.handle, c_class_name) > if rc == eSaAisErrorT.SA_AIS_OK: > self.implemented_names.append(class_name) > + else: > + log_err("saImmOiClassImplementerSet FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > return rc > > def set_constraints(self, constraints): > @@ -862,7 +883,7 @@ class Implementer(OiAgent): > # Let the user code validate the CCB (if configured) > self.on_validate(instances, updated, created, deleted) > except SafException as err: > - immoi.set_error_string(ccb_id, err.msg) > + self.set_error_string(ccb_id, err.msg) > return err.value > except Exception: > return eSaAisErrorT.SA_AIS_ERR_FAILED_OPERATION > @@ -887,7 +908,7 @@ class Implementer(OiAgent): > SaAisErrorT: Return code of admin operation > """ > # Get the class name > - class_name = immoi.get_class_name_for_dn(object_name) > + class_name = self.get_class_name_for_dn(object_name) > > # Find and execute a matching admin operation > if self.admin_operations: > @@ -928,13 +949,13 @@ class Implementer(OiAgent): > SaAisErrorT: Return code of Implementer register > """ > # Initialize the OI API > - rc = self.initialize() > + rc = self.re_initialize() > > # Ensure that all classes are configuration classes > runtime_classes = None > if self.class_names is not None: > runtime_classes = [item for item in self.class_names > - if immoi.get_class_category(item) == > + if self.imm_om.get_class_category(item) == > eSaImmClassCategoryT.SA_IMM_CLASS_RUNTIME] > if runtime_classes: > raise Exception("ERROR: Can't be an applier for runtime " > @@ -944,7 +965,7 @@ class Implementer(OiAgent): > if rc == eSaAisErrorT.SA_AIS_OK: > rc = self._register_implementer(self.name) > > - available_classes = immoi.get_available_classes_in_imm() > + available_classes = self.get_available_classes_in_imm() > > if rc == eSaAisErrorT.SA_AIS_OK: > if self.class_names is not None: > @@ -969,6 +990,10 @@ class Implementer(OiAgent): > """ > implementer_name = SaImmOiImplementerNameT(oi_name) > rc = saImmOiImplementerSet(self.handle, implementer_name) > + > + if rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOiClassImplementerSet FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > return rc > > def update_runtime_attributes(self, dn, attributes): > @@ -995,7 +1020,7 @@ class Implementer(OiAgent): > SaAisErrorT: Return code of implementer object create > """ > # Get the parent name for the object > - parent_name = immoi.get_parent_name_for_dn(obj.dn) > + parent_name = self.get_parent_name_for_dn(obj.dn) > class_name = obj.class_name > > # Create the object > @@ -1062,11 +1087,11 @@ class Applier(Implementer): > SaAisErrorT: Return code of applier register > """ > # Initialize the OI API > - rc = self.initialize() > + rc = self.re_initialize() > > # Ensure that all classes are configuration classes > runtime_classes = [item for item in self.class_names > - if immoi.get_class_category(item) == > + if self.imm_om.get_class_category(item) == > eSaImmClassCategoryT.SA_IMM_CLASS_RUNTIME] > if runtime_classes: > raise Exception("ERROR: Can't be an applier for runtime classes > %s" > @@ -1076,7 +1101,7 @@ class Applier(Implementer): > rc = self._register_applier(self.name) > > # Register as applier for each class > - available_classes = immoi.get_available_classes_in_imm() > + available_classes = self.get_available_classes_in_imm() > > for class_name in self.class_names: > if class_name in available_classes: > diff --git a/python/pyosaf/utils/immom/__init__.py > b/python/pyosaf/utils/immom/__init__.py > index 57a9692..5706074 100644 > --- a/python/pyosaf/utils/immom/__init__.py > +++ b/python/pyosaf/utils/immom/__init__.py > @@ -21,7 +21,7 @@ from pyosaf.saAis import eSaAisErrorT > from pyosaf.utils import deprecate, SafException > from pyosaf.utils.immom import agent > from pyosaf.utils.immom.object import ImmObject > -from pyosaf.utils.immom.accessor import ImmOmAccessor > +from pyosaf.utils.immom.accessor import Accessor > > > # Decorate pure saImmOm* API's with error-handling retry and exception > raising > @@ -70,7 +70,7 @@ def initialize(): > SafException: If any IMM OM API call did not return SA_AIS_OK > """ > global _om_agent > - _om_agent = agent.ImmOmAgent() > + _om_agent = agent.OmAgent() > > # Initialize IMM OM handle and return the API return code > rc = _om_agent.init() > @@ -93,7 +93,7 @@ def get(object_name, attr_name_list=None, class_name=None): > Raises: > SafException: If any IMM OM API call did not return SA_AIS_OK > """ > - _accessor = ImmOmAccessor() > + _accessor = Accessor() > _accessor.init() > rc, imm_object = _accessor.get(object_name, attr_name_list, class_name) > > @@ -173,6 +173,7 @@ def get_rdn_attribute_for_class(class_name): > return _om_agent.get_rdn_attribute_for_class(class_name) > > > +@deprecate > def get_class_category(class_name): > """ Return the category of the given class > > diff --git a/python/pyosaf/utils/immom/accessor.py > b/python/pyosaf/utils/immom/accessor.py > index aac0f6d..b411387 100644 > --- a/python/pyosaf/utils/immom/accessor.py > +++ b/python/pyosaf/utils/immom/accessor.py > @@ -28,23 +28,23 @@ from pyosaf.utils.immom import agent > from pyosaf.utils.immom.object import ImmObject > > > -class ImmOmAccessor(agent.ImmOmAgentManager): > +class Accessor(agent.OmAgentManager): > """ This class provides functions of the ImmOm Accessor interface """ > def __init__(self, version=None): > - """ Constructor for ImmOmAccessor class > + """ Constructor for Accessor class > > Args: > version (SaVersionT): IMM OM version > """ > - super(ImmOmAccessor, self).__init__(version) > + super(Accessor, self).__init__(version) > self.accessor_handle = None > > def __enter__(self): > - """ Enter method for ImmOmAccessor class """ > + """ Enter method for Accessor class """ > return self > > def __exit__(self, exception_type, exception_value, traceback): > - """ Exit method for ImmOmAccessor class > + """ Exit method for Accessor class > > Finalize the accessor handle and the IMM OM agent handle > """ > @@ -56,7 +56,7 @@ class ImmOmAccessor(agent.ImmOmAgentManager): > self.handle = None > > def __del__(self): > - """ Destructor for ImmOmAccessor class > + """ Destructor for Accessor class > > Finalize the accessor handle and the IMM OM agent handle > """ > @@ -115,10 +115,8 @@ class ImmOmAccessor(agent.ImmOmAgentManager): > rc = agent.saImmOmAccessorGet_2(self.accessor_handle, > SaNameT(object_name), > attr_names, attributes) > - if rc != eSaAisErrorT.SA_AIS_OK: > - log_err("saImmOmAccessorGet_2 FAILED - %s" % > - eSaAisErrorT.whatis(rc)) > - else: > + > + if rc == eSaAisErrorT.SA_AIS_OK: > attrs = {} > attr_list = unmarshalNullArray(attributes) > for attr in attr_list: > @@ -130,6 +128,17 @@ class ImmOmAccessor(agent.ImmOmAgentManager): > for val in attr_range]] > if 'SaImmAttrClassName' not in attrs and class_name: > attrs['SaImmAttrClassName'] = class_name > - imm_obj = ImmObject(object_name, attrs) > + imm_obj = ImmObject(dn=object_name, attributes=attrs) > + > + if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > + init_rc = self.init() > + # If the re-initialization of agent handle succeeds, we still > need > + # to return BAD_HANDLE to the users, so that they would re-try > the > + # failed operation. Otherwise, the true error code is returned > + # to the user to decide further actions. > + if init_rc != eSaAisErrorT.SA_AIS_OK: > + log_err("saImmOmAccessorGet_2 FAILED - %s" % > + eSaAisErrorT.whatis(rc)) > + rc = init_rc > > return rc, imm_obj > diff --git a/python/pyosaf/utils/immom/agent.py > b/python/pyosaf/utils/immom/agent.py > index b813055..a313aea 100644 > --- a/python/pyosaf/utils/immom/agent.py > +++ b/python/pyosaf/utils/immom/agent.py > @@ -64,10 +64,10 @@ saImmOmAdminOperationContinuationClear = \ > decorate(saImmOm.saImmOmAdminOperationContinuationClear) > > > -class ImmOmAgentManager(object): > +class OmAgentManager(object): > """ This class manages the life cycle of an IMM OM agent """ > def __init__(self, version=None): > - """ Constructor for ImmOmAgentManager class > + """ Constructor for OmAgentManager class > > Args: > version (SaVersionT): IMM OM API version > @@ -79,11 +79,11 @@ class ImmOmAgentManager(object): > self.selection_object = None > > def __enter__(self): > - """ Enter method for ImmOmAgentManager class """ > + """ Enter method for OmAgentManager class """ > return self > > def __exit__(self, exception_type, exception_value, traceback): > - """ Exit method for ImmOmAgentManager class > + """ Exit method for OmAgentManager class > > Finalize the IMM OM agent handle > """ > @@ -92,7 +92,7 @@ class ImmOmAgentManager(object): > self.handle = None > > def __del__(self): > - """ Destructor for ImmOmAgentManager class > + """ Destructor for OmAgentManager class > > Finalize the IMM OM agent handle > """ > @@ -149,7 +149,8 @@ class ImmOmAgentManager(object): > if rc != eSaAisErrorT.SA_AIS_OK: > log_err("saImmOmFinalize FAILED - %s" % > eSaAisErrorT.whatis(rc)) > - elif rc == eSaAisErrorT.SA_AIS_OK \ > + > + if rc == eSaAisErrorT.SA_AIS_OK \ > or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > # If the Finalize() call returned BAD_HANDLE, the handle > should > # already become stale and invalid, so we reset it anyway. > @@ -157,7 +158,7 @@ class ImmOmAgentManager(object): > return rc > > > -class ImmOmAgent(ImmOmAgentManager): > +class OmAgent(OmAgentManager): > """ This class acts as a high-level IMM OM agent, providing IMM OM > functions to the users at a higher level, and relieving the users of the > need to manage the life cycle of the IMM OM agent """ > @@ -265,8 +266,8 @@ class ImmOmAgent(ImmOmAgentManager): > Returns: > SaAisErrorT: Return code of the corresponding IMM API call(s) > """ > - _owner = ImmOmAdminOwner(self.handle) > - rc = _owner.initialize() > + _owner = OmAdminOwner(self.handle) > + rc = _owner.init() > if rc == eSaAisErrorT.SA_AIS_OK: > index = dn.rfind(",") > object_rdn = dn[index+1:] > @@ -314,10 +315,10 @@ class ImmOmAgent(ImmOmAgentManager): > return c_category.value > > > -class ImmOmAdminOwner(object): > +class OmAdminOwner(object): > """ This class encapsulates the ImmOm Admin Owner interface """ > def __init__(self, imm_handle, owner_name=""): > - """ Constructor for ImmOmAdminOwner class > + """ Constructor for OmAdminOwner class > > Args: > imm_handle (SaImmHandleT): IMM OM agent handle > @@ -333,11 +334,11 @@ class ImmOmAdminOwner(object): > self.owner_handle = None > > def __enter__(self): > - """ Enter method for ImmOmAdminOwner class """ > + """ Enter method for OmAdminOwner class """ > return self > > def __exit__(self, exception_type, exception_value, traceback): > - """ Exit method for ImmOmAdminOwner class > + """ Exit method for OmAdminOwner class > > Finalize the admin owner handle > """ > @@ -346,7 +347,7 @@ class ImmOmAdminOwner(object): > self.owner_handle = None > > def __del__(self): > - """ Destructor for ImmOmAdminOwner class > + """ Destructor for OmAdminOwner class > > Finalize the admin owner handle > """ > @@ -354,7 +355,7 @@ class ImmOmAdminOwner(object): > saImmOm.saImmOmAdminOwnerFinalize(self.owner_handle) > self.owner_handle = None > > - def initialize(self): > + def init(self): > """ Initialize the IMM admin owner interface > > Return: > diff --git a/python/pyosaf/utils/immom/ccb.py > b/python/pyosaf/utils/immom/ccb.py > index 042a726..15b891b 100644 > --- a/python/pyosaf/utils/immom/ccb.py > +++ b/python/pyosaf/utils/immom/ccb.py > @@ -21,12 +21,13 @@ from ctypes import c_void_p, pointer, cast, POINTER > > from pyosaf.saAis import eSaAisErrorT, SaNameT, SaStringT, SaFloatT, \ > unmarshalNullArray, SaDoubleT, SaTimeT, SaUint64T, SaInt64T, SaUint32T, > \ > - SaInt32T, SaVersionT > + SaInt32T > from pyosaf.saImm import eSaImmScopeT, eSaImmValueTypeT, SaImmAttrValuesT_2 > from pyosaf import saImm > from pyosaf import saImmOm > from pyosaf.utils.immom import agent > -from pyosaf.utils.immom.accessor import ImmOmAccessor > +from pyosaf.utils.immom.agent import OmAgent > +from pyosaf.utils.immom.accessor import Accessor > from pyosaf.utils import log_err, bad_handle_retry > > > @@ -83,12 +84,11 @@ def marshal_c_array(value_type, value_list): > return c_array > > > -class Ccb(object): > +class Ccb(OmAgent): > """ Class representing an ongoing CCB """ > def __init__(self, flags=saImm.saImm.SA_IMM_CCB_REGISTERED_OI, > version=None): > - self.init_version = version if version else SaVersionT('A', 2, 15) > - self.imm_om = None > + super(Ccb, self).__init__(version=version) > self.admin_owner = None > self.accessor = None > self.ccb_handle = None > @@ -123,43 +123,13 @@ class Ccb(object): > if self.ccb_handle is not None: > saImmOm.saImmOmCcbFinalize(self.ccb_handle) > self.ccb_handle = None > + > if self.admin_owner: > del self.admin_owner > - if self.imm_om: > - del self.imm_om > - > - def clear_admin_owner(self, obj_name, scope=eSaImmScopeT.SA_IMM_SUBTREE): > - """ Clear the admin owner for the set of object identified by the > scope > - and obj_name parameters > - > - Args: > - obj_name (str): Object name > - scope (SaImmScopeT): Scope of the clear operation > - > - Returns: > - SaAisErrorT: Return code of the corresponding IMM API call(s) > - """ > - return self.imm_om.clear_admin_owner(obj_name, scope) > - > - def finalize(self): > - """ Finalize the CCB handle > - > - Returns: > - SaAisErrorT: Return code of the saImmOmCcbFinalize() API call > - """ > - rc = eSaAisErrorT.SA_AIS_OK > - if self.ccb_handle: > - rc = agent.saImmOmCcbFinalize(self.ccb_handle) > - if rc != eSaAisErrorT.SA_AIS_OK: > - log_err("saImmOmCcbFinalize FAILED - %s" % > - eSaAisErrorT.whatis(rc)) > - elif rc == eSaAisErrorT.SA_AIS_OK \ > - or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE: > - # If the Finalize() call returned BAD_HANDLE, the handle > should > - # already become stale and invalid, so we reset it anyway. > - self.ccb_handle = None > > - return rc > + if self.handle is not None: > + saImmOm.saImmOmFinalize(self.handle) > + self.handle = None > > @bad_handle_retry > def init(self, owner_name=""): > @@ -171,26 +141,22 @@ class Ccb(object): > Return: > SaAisErrorT: Return code of the corresponding IMM API calls > """ > - # Clean previous resources if any > - self.finalize() > - self.imm_om = agent.ImmOmAgent(self.init_version) > - rc = self.imm_om.init() > + rc = super(Ccb, self).init() > if rc == eSaAisErrorT.SA_AIS_OK: > - _om_handle = self.imm_om.get_handle() > - self.admin_owner = agent.ImmOmAdminOwner(_om_handle, owner_name) > - self.admin_owner.initialize() > + self.admin_owner = agent.OmAdminOwner(self.handle, owner_name) > + rc = self.admin_owner.init() > + > if rc == eSaAisErrorT.SA_AIS_OK: > _owner_handle = self.admin_owner.get_handle() > self.ccb_handle = saImmOm.SaImmCcbHandleT() > > - rc = agent.saImmOmCcbInitialize( > - _owner_handle, self.ccb_flags, self.ccb_handle) > + rc = agent.saImmOmCcbInitialize(_owner_handle, > self.ccb_flags, > + self.ccb_handle) > if rc != eSaAisErrorT.SA_AIS_OK: > log_err("saImmOmCcbInitialize FAILED - %s" % > eSaAisErrorT.whatis(rc)) > return rc > > - @bad_handle_retry > def create(self, obj, parent_name=None): > """ Create the CCB object > > @@ -237,7 +203,6 @@ class Ccb(object): > > return rc > > - @bad_handle_retry > def delete(self, object_name): > """ Add a delete operation of the object with the given DN to the > CCB > > @@ -269,7 +234,6 @@ class Ccb(object): > > return rc > > - @bad_handle_retry > def _modify(self, object_name, attr_name, values, mod_type): > """ Modify an existing object > > @@ -285,7 +249,7 @@ class Ccb(object): > rc = eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM > else: > if not self.accessor: > - self.accessor = ImmOmAccessor(self.init_version) > + self.accessor = Accessor(self.init_version) > self.accessor.init() > > # Get the attribute value type by reading the object's class > @@ -293,8 +257,7 @@ class Ccb(object): > rc, obj = self.accessor.get(object_name) > if rc == eSaAisErrorT.SA_AIS_OK: > class_name = obj.SaImmAttrClassName > - _, attr_def_list = \ > - self.imm_om.get_class_description(class_name) > + _, attr_def_list = self.get_class_description(class_name) > value_type = None > for attr_def in attr_def_list: > if attr_def.attrName == attr_name: > diff --git a/python/pyosaf/utils/immom/iterator.py > b/python/pyosaf/utils/immom/iterator.py > index 51f7e95..7402c94 100644 > --- a/python/pyosaf/utils/immom/iterator.py > +++ b/python/pyosaf/utils/immom/iterator.py > @@ -30,7 +30,7 @@ from pyosaf.utils.immom import agent > from pyosaf.utils.immom.object import ImmObject > > > -class SearchIterator(agent.ImmOmAgentManager, Iterator): > +class SearchIterator(agent.OmAgentManager, Iterator): > """ General search iterator """ > def __init__(self, root_name=None, scope=eSaImmScopeT.SA_IMM_SUBTREE, > attribute_names=None, search_param=None, version=None): > @@ -109,7 +109,7 @@ class SearchIterator(agent.ImmOmAgentManager, Iterator): > > [unmarshalSaImmValue(attr.attrValues[val], > attr.attrValueType) > for val in attr_range]] > - return ImmObject(obj_name, attrs) > + return ImmObject(str(obj_name), attrs) > > @bad_handle_retry > def init(self): > diff --git a/python/pyosaf/utils/immom/object.py > b/python/pyosaf/utils/immom/object.py > index 0cef920..435a244 100644 > --- a/python/pyosaf/utils/immom/object.py > +++ b/python/pyosaf/utils/immom/object.py > @@ -20,7 +20,7 @@ from pyosaf.saAis import eSaAisErrorT > from pyosaf.saImm import saImm > > from pyosaf.utils import SafException > -from pyosaf.utils.immom.agent import ImmOmAgent > +from pyosaf.utils.immom.agent import OmAgent > > > class ImmObject(object): > @@ -43,7 +43,7 @@ class ImmObject(object): > is not SA_AIS_OK > """ > self.__dict__["dn"] = dn > - _imm_om = ImmOmAgent() > + _imm_om = OmAgent() > rc = _imm_om.init() > if rc != eSaAisErrorT.SA_AIS_OK: > raise SafException(rc) ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Opensaf-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/opensaf-devel
