Hi Hieu,

it sounds good. The question about backwards compatible was to highlight possible application problems, it should not

be too hard to avoid this non backward compatibility, either as you suggest, changing version, or perhaps, with some overhead,

do the init if needed in each function, (similar to the singleton pattern).

/Regards HansN



On 01/09/2018 04:28 AM, Hieu Nguyen wrote:
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:[email protected]]
Sent: Monday, January 8, 2018 7:23 PM
To: Hieu Thanh Nguyen <[email protected]>; Anders Widell 
<[email protected]>; [email protected]
Cc: [email protected]
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:[email protected]]
Sent: den 8 januari 2018 13:06
To: Hans Nordebäck <[email protected]>; Anders Widell 
<[email protected]>; [email protected]
Cc: [email protected]
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:[email protected]]
Sent: Monday, January 8, 2018 5:56 PM
To: Hieu Nguyen <[email protected]>; [email protected]; 
[email protected]
Cc: [email protected]
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to