Thanks Hans,

New exception is just an improvement to make exception type and message 
clearer. It informs ERR_INIT to user so that user knows that OI needs to be 
initialized before any function is used. Something like that: 

>>> from pyosaf.utils import immoi
>>> immoi.get_available_classes_in_imm()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pyosaf/utils/__init__.py", line 
243, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pyosaf/utils/immoi/__init__.py", 
line 312, in get_available_classes_in_imm
    raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
pyosaf.utils.SafException: SA_AIS_ERR_INIT


If not use new exception (current version in develop branch), it is raising 
AttributeError exception for the case above.

>>> from pyosaf.utils import immoi
>>> immoi.get_available_classes_in_imm()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pyosaf/utils/__init__.py", line 
243, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pyosaf/utils/immoi/__init__.py", 
line 314, in get_available_classes_in_imm
    return _oi_agent.get_available_classes_in_imm()
AttributeError: 'NoneType' object has no attribute 
'get_available_classes_in_imm'

To avoid this minor non-backwards compatible issue, I will increase the version 
of pyosaf utils (pyosaf/utils/__init__.py) to "1.0.1", how do you think?

Regards,
Hieu

-----Original Message-----
From: Hans Nordebäck [mailto:hans.nordeb...@ericsson.com] 
Sent: Monday, January 8, 2018 7:23 PM
To: Hieu Thanh Nguyen <hieu.t.ngu...@dektech.com.au>; Anders Widell 
<anders.wid...@ericsson.com>; srinivas.mangip...@oracle.com
Cc: opensaf-devel@lists.sourceforge.net
Subject: RE: [PATCH 1/1] pyosaf: refactor IMM utils [#2683]

Hi Hieu,

Yes, I noticed that e.g. initialize is needed, but also other changes e.g. new 
exceptions are thrown. 
These changes implies that applications may have to be updated and thus the 
changes are not backwards compatible.

/Regards HansN

-----Original Message-----
From: Hieu Nguyen [mailto:hieu.t.ngu...@dektech.com.au] 
Sent: den 8 januari 2018 13:06
To: Hans Nordebäck <hans.nordeb...@ericsson.com>; Anders Widell 
<anders.wid...@ericsson.com>; srinivas.mangip...@oracle.com
Cc: opensaf-devel@lists.sourceforge.net
Subject: RE: [PATCH 1/1] pyosaf: refactor IMM utils [#2683]

Hi Hans,

I answered your questions below:
Q: " These changes are not backwards compatible ?"
A: These change still support pyosaf utils old version. Your sample missing 
immoi.initialize() before, correctly:
python
>>> from pyosaf.utils import immoi
>>> immoi.initialize()
>>> immoi.get_available_classes_in_imm()

I keep all old interfaces of imm utils with @deprecate functions in __init__.py 
file.

Q: " Why is some behavior changed in e.g. functions marked as deprecated?"
A: We changed some imm utils behavior because that is requested by ticket #2602.
https://sourceforge.net/p/opensaf/tickets/2602/

Same as title of ticket #2602 " improvement of high level python interfaces ". 
We want users should be change from functions to OOP.

Regards,
Hieu
-----Original Message-----
From: Hans Nordebäck [mailto:hans.nordeb...@ericsson.com] 
Sent: Monday, January 8, 2018 5:56 PM
To: Hieu Nguyen <hieu.t.ngu...@dektech.com.au>; anders.wid...@ericsson.com; 
srinivas.mangip...@oracle.com
Cc: opensaf-devel@lists.sourceforge.net
Subject: Re: [PATCH 1/1] pyosaf: refactor IMM utils [#2683]

Hi Hieu,

I have some initial questions regarding this patch:

These changes are not backwards compatible, e.g.:

     python

     >>> from pyosaf.utils import immoi

     >>> immoi.get_available_classes_in_imm()

do not work after this patch.

Why is some behavior changed in e.g. functions marked as deprecated? E.g 
adding exceptions.

/Regards HansN


On 12/20/2017 09:25 AM, Hieu Nguyen wrote:
> + improve OI utils use a separate instance OM agent
> + refactor OM utils with Ccb inheritace OmAgent, rename some classes...
> ---
>   python/Makefile.am                       |   1 +
>   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 +-
>   10 files changed, 739 insertions(+), 559 deletions(-)
>   create mode 100644 python/pyosaf/utils/immoi/agent.py
>
> diff --git a/python/Makefile.am b/python/Makefile.am
> index 08338bb..1952d5e 100644
> --- a/python/Makefile.am
> +++ b/python/Makefile.am
> @@ -61,6 +61,7 @@ pkgpyosafutilslog_PYTHON = \
>   
>   pkgpyosafutilsimmoi_PYTHON = \
>       python/pyosaf/utils/immoi/__init__.py \
> +     python/pyosaf/utils/immoi/agent.py \
>       python/pyosaf/utils/immoi/implementer.py
>   
>   pkgpyosafutilsntf_PYTHON = \
> 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
> +# 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
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to