Makefile.common                       |    2 +
 configure.ac                          |    2 +
 opensaf.spec.in                       |    6 +
 python/pyosaf/Makefile.am             |    2 +
 python/pyosaf/utils/Makefile.am       |   24 ++
 python/pyosaf/utils/__init__.py       |    0 
 python/pyosaf/utils/immom/Makefile.am |   26 ++
 python/pyosaf/utils/immom/__init__.py |  196 +++++++++++++++++
 python/pyosaf/utils/immom/ccb.py      |  375 ++++++++++++++++++++++++++++++++++
 python/pyosaf/utils/immom/common.py   |   32 ++
 python/pyosaf/utils/immom/iterator.py |  139 ++++++++++++
 python/pyosaf/utils/immom/object.py   |  108 +++++++++
 12 files changed, 912 insertions(+), 0 deletions(-)


Hans created the opensaf-tools repo and contributed the amf/immom package as a 
part of it.
The amf/immom package contains useful utilities that can be used by other 
packages/tools.
This patch moves these opensaf-tools/amf/immom as a subpackage of a new utils 
subpackage under pyosaf
of the opensaf staging repository.
Note: The amf-tools is also adjusted to work with these changes and will be 
uploaded to the amf-tools repository
separately.

diff --git a/Makefile.common b/Makefile.common
--- a/Makefile.common
+++ b/Makefile.common
@@ -35,3 +35,5 @@ lsbinitdir = $(initscriptdir)
 systemddir = $(systemdsystemunitdir)
 lockdir = $(localstatedir)/lock/subsys
 pkgpyosafdir = $(pythondir)/pyosaf
+pkgpyosafutilsdir = $(pythondir)/pyosaf/utils
+pkgpyosafutilsimmomdir = $(pythondir)/pyosaf/utils/immom
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -677,6 +677,8 @@ AC_CONFIG_FILES([
         java/amf_agent/Makefile
         python/Makefile
         python/pyosaf/Makefile
+        python/pyosaf/utils/Makefile
+        python/pyosaf/utils/immom/Makefile
         osaf/Makefile
         osaf/libs/Makefile
         osaf/libs/agents/Makefile
diff --git a/opensaf.spec.in b/opensaf.spec.in
--- a/opensaf.spec.in
+++ b/opensaf.spec.in
@@ -1510,6 +1510,12 @@ fi
 %{python_sitelib}/pyosaf/*.py
 %{python_sitelib}/pyosaf/*.pyc
 %{python_sitelib}/pyosaf/*.pyo
+%{python_sitelib}/pyosaf/utils/*.py
+%{python_sitelib}/pyosaf/utils/*.pyc
+%{python_sitelib}/pyosaf/utils/*.pyo
+%{python_sitelib}/pyosaf/utils/immom/*.py
+%{python_sitelib}/pyosaf/utils/immom/*.pyc
+%{python_sitelib}/pyosaf/utils/immom/*.pyo
 %endif
 
 
diff --git a/python/pyosaf/Makefile.am b/python/pyosaf/Makefile.am
--- a/python/pyosaf/Makefile.am
+++ b/python/pyosaf/Makefile.am
@@ -34,3 +34,5 @@ pkgpyosaf_PYTHON = \
        saMsg.py \
        saNtf.py \
        saSmf.py
+
+SUBDIRS = utils
diff --git a/python/pyosaf/utils/Makefile.am b/python/pyosaf/utils/Makefile.am
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/Makefile.am
@@ -0,0 +1,24 @@
+#      -*- OpenSAF  -*-
+#
+# (C) Copyright 2011 The OpenSAF Foundation
+#
+# 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): Oracle
+#
+
+include $(top_srcdir)/Makefile.common
+
+MAINTAINERCLEANFILES = Makefile.in
+
+pkgpyosafutils_PYTHON = \
+       __init__.py
+
+SUBDIRS = immom
diff --git a/python/pyosaf/utils/__init__.py b/python/pyosaf/utils/__init__.py
new file mode 100644
diff --git a/python/pyosaf/utils/immom/Makefile.am 
b/python/pyosaf/utils/immom/Makefile.am
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/immom/Makefile.am
@@ -0,0 +1,26 @@
+#      -*- OpenSAF  -*-
+#
+# (C) Copyright 2011 The OpenSAF Foundation
+#
+# 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): Oracle
+#
+
+include $(top_srcdir)/Makefile.common
+
+MAINTAINERCLEANFILES = Makefile.in
+
+pkgpyosafutilsimmom_PYTHON = \
+       __init__.py \
+       ccb.py \
+       common.py \
+       iterator.py \
+       object.py
diff --git a/python/pyosaf/utils/immom/__init__.py 
b/python/pyosaf/utils/immom/__init__.py
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/immom/__init__.py
@@ -0,0 +1,196 @@
+############################################################################
+#
+# (C) Copyright 2014 The OpenSAF Foundation
+#
+# 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 OM common utilitites
+'''
+
+import os
+import time
+from ctypes import pointer
+
+from pyosaf import saAis
+from pyosaf.saAis import eSaAisErrorT, SaVersionT, SaNameT, unmarshalNullArray
+from pyosaf import saImmOm, saImm
+from pyosaf.saImm import eSaImmScopeT, unmarshalSaImmValue, SaImmAttrNameT, \
+    SaImmAttrValuesT_2
+from pyosaf.saImmOm import SaImmHandleT, SaImmAccessorHandleT,\
+    saImmOmAdminOwnerInitialize
+
+from pyosaf.utils.immom.common import SafException
+from pyosaf.utils.immom.object import ImmObject
+
+HANDLE = saImmOm.SaImmHandleT()
+ACCESSOR_HANDLE = SaImmAccessorHandleT()
+
+TRYAGAIN_CNT = 60
+
+
+def _initialize():
+    ''' saImmOmInitialize with TRYAGAIN handling '''
+    version = SaVersionT('A', 2, 1)
+    one_sec_sleeps = 0
+    err = saImmOm.saImmOmInitialize(HANDLE, None, version)
+    while err == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+        if one_sec_sleeps == TRYAGAIN_CNT:
+            break
+        time.sleep(1)
+        one_sec_sleeps += 1
+        err = saImmOm.saImmOmInitialize(HANDLE, None, version)
+
+    if err != eSaAisErrorT.SA_AIS_OK:
+        raise SafException(err,
+                           "saImmOmInitialize: %s" % eSaAisErrorT.whatis(err))
+
+    # TODO TRYAGAIN handling? Is it needed?
+    err = saImmOm.saImmOmAccessorInitialize(HANDLE, ACCESSOR_HANDLE)
+    if err != eSaAisErrorT.SA_AIS_OK:
+        raise SafException(err,
+                           "saImmOmAccessorInitialize: %s" %
+                           eSaAisErrorT.whatis(err))
+
+
+def get(object_name, attr_name_list=None):
+    ''' obtain values of some attributes of the specified object '''
+
+    attrib_names = [SaImmAttrNameT(a) for a in attr_name_list]\
+        if attr_name_list else None
+
+    attributes = pointer(pointer(SaImmAttrValuesT_2()))
+
+    one_sec_sleeps = 0
+    err = saImmOm.saImmOmAccessorGet_2(ACCESSOR_HANDLE,
+                                       SaNameT(object_name),
+                                       attrib_names, attributes)
+    while err == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+        if one_sec_sleeps == TRYAGAIN_CNT:
+            break
+        time.sleep(1)
+        one_sec_sleeps += 1
+        err = saImmOm.saImmOmAccessorGet_2(ACCESSOR_HANDLE,
+                                           SaNameT(object_name),
+                                           attrib_names, attributes)
+
+    if err == eSaAisErrorT.SA_AIS_ERR_NOT_EXIST:
+        return None
+
+    if err != eSaAisErrorT.SA_AIS_OK:
+        raise SafException(err,
+                           "saImmOmInitialize: %s" % eSaAisErrorT.whatis(err))
+
+    attribs = {}
+    attr_list = unmarshalNullArray(attributes)
+    for attr in attr_list:
+        attr_range = range(attr.attrValuesNumber)
+        attribs[attr.attrName] = [
+            attr.attrValueType,
+            [unmarshalSaImmValue(
+                attr.attrValues[val],
+                attr.attrValueType) for val in attr_range]
+            ]
+
+    return ImmObject(object_name, attribs)
+
+# initialize handles needed when module is loaded
+_initialize()
+
+
+def class_description_get(class_name):
+    ''' get class description as a python list '''
+
+    attr_defs = pointer(pointer(saImm.SaImmAttrDefinitionT_2()))
+    category = saImm.SaImmClassCategoryT()
+    err = saImmOm.saImmOmClassDescriptionGet_2(HANDLE,
+                                               class_name,
+                                               category,
+                                               attr_defs)
+    if err != eSaAisErrorT.SA_AIS_OK:
+        raise SafException(err, "saImmOmClassDescriptionGet_2(%s)" %
+                           class_name)
+
+    return saAis.unmarshalNullArray(attr_defs)
+
+
+def admin_op_invoke(dn, op_id, params=None):
+    ''' invokes admin op for dn '''
+    owner_handle = saImmOm.SaImmAdminOwnerHandleT()
+    owner_name = saImmOm.SaImmAdminOwnerNameT(os.getlogin())
+    err = saImmOm.saImmOmAdminOwnerInitialize(HANDLE,
+                                              owner_name,
+                                              saAis.eSaBoolT.SA_TRUE,
+                                              owner_handle)
+
+    if err != eSaAisErrorT.SA_AIS_OK:
+        print "saImmOmAdminOwnerInitialize: %s" % eSaAisErrorT.whatis(err)
+        raise SafException(err)
+
+    idx = dn.rfind(",")
+    parent_name = SaNameT(dn[idx+1:])
+    object_names = [parent_name]
+    err = saImmOm.saImmOmAdminOwnerSet(owner_handle, object_names,
+                                       eSaImmScopeT.SA_IMM_SUBTREE)
+    if err != eSaAisErrorT.SA_AIS_OK:
+        print "saImmOmAdminOwnerInitialize: %s" % eSaAisErrorT.whatis(err)
+        raise SafException(err)
+
+    if params is None:
+        params = []
+
+    object_dn = SaNameT(dn)
+    retval = saAis.SaAisErrorT()
+
+    err = saImmOm.saImmOmAdminOperationInvoke_2(
+        owner_handle,
+        object_dn,
+        0,
+        op_id,
+        params,
+        retval,
+        saAis.saAis.SA_TIME_ONE_SECOND * 10)
+
+    if err != eSaAisErrorT.SA_AIS_OK:
+        print "saImmOmAdminOperationInvoke_2: %s" % eSaAisErrorT.whatis(err)
+        raise SafException(err)
+
+    one_sec_sleeps = 0
+    while retval.value == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+        if one_sec_sleeps == TRYAGAIN_CNT:
+            break
+        time.sleep(0.1)
+        one_sec_sleeps += 1
+        err = saImmOm.saImmOmAdminOperationInvoke_2(
+            owner_handle,
+            object_dn,
+            0,
+            op_id,
+            params,
+            retval,
+            saAis.saAis.SA_TIME_ONE_SECOND * 10)
+
+    if err != eSaAisErrorT.SA_AIS_OK:
+        print "saImmOmAdminOperationInvoke_2: %s" % eSaAisErrorT.whatis(err)
+        raise SafException(err)
+
+    if retval.value != eSaAisErrorT.SA_AIS_OK:
+        print "saImmOmAdminOperationInvoke_2: %s" % \
+            eSaAisErrorT.whatis(retval.value)
+        raise SafException(retval.value)
+
+    error = saImmOm.saImmOmAdminOwnerFinalize(owner_handle)
+    if error != eSaAisErrorT.SA_AIS_OK:
+        print "saImmOmAdminOwnerFinalize: %s" % eSaAisErrorT.whatis(error)
+        raise SafException(error)
diff --git a/python/pyosaf/utils/immom/ccb.py b/python/pyosaf/utils/immom/ccb.py
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/immom/ccb.py
@@ -0,0 +1,375 @@
+############################################################################
+#
+# (C) Copyright 2014 The OpenSAF Foundation
+#
+# 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
+#
+############################################################################
+'''
+Class representing an IMM CCB.
+'''
+
+import time
+from ctypes import c_void_p, pointer, cast
+
+from pyosaf.saAis import eSaAisErrorT, SaNameT, SaStringT, \
+    SaDoubleT, SaTimeT, SaUint64T, SaInt64T, SaUint32T, SaInt32T, SaFloatT
+
+from pyosaf.saImm import eSaImmScopeT, eSaImmValueTypeT, SaImmAttrValuesT_2
+
+from pyosaf import saImm
+from pyosaf import saImmOm
+from pyosaf import saAis
+
+import pyosaf.utils.immom
+from pyosaf.utils.immom.common import SafException
+
+TRYAGAIN_CNT = 60
+
+
+def _value_to_ctype_ptr(value_type, value):
+    ''' convert a value to a ctypes value ptr '''
+    if value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAINT32T:
+        ctypeptr = cast(pointer(SaInt32T(value)), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAUINT32T:
+        ctypeptr = cast(pointer(SaUint32T(long(value))), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAINT64T:
+        ctypeptr = cast(pointer(SaInt64T(long(value))), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAUINT64T:
+        ctypeptr = cast(pointer(SaUint64T(long(value))), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SATIMET:
+        ctypeptr = cast(pointer(SaTimeT(long(value))), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SANAMET:
+        ctypeptr = cast(pointer(SaNameT(value)), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAFLOATT:
+        ctypeptr = cast(pointer(SaFloatT(value)), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SADOUBLET:
+        ctypeptr = cast(pointer(SaDoubleT(value)), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SASTRINGT:
+        ctypeptr = cast(pointer(SaStringT(value)), c_void_p)
+    elif value_type is eSaImmValueTypeT.SA_IMM_ATTR_SAANYT:
+        assert 0
+    else:
+        assert 0
+
+    return ctypeptr
+
+def marshal_c_array(value_type, value_list):
+    ''' creates a C array initialized with values from value_list '''
+    c_array_type = saImm.SaImmAttrValueT * len(value_list)
+    c_array = c_array_type()
+    for i in range(len(value_list)):
+        c_array[i] = _value_to_ctype_ptr(value_type, value_list[i])
+    return c_array
+
+class Ccb(object):
+    def __init__(self):
+        self.owner_handle = saImmOm.SaImmAdminOwnerHandleT()
+
+        owner_name = saImmOm.SaImmAdminOwnerNameT("DummyName")
+        one_sec_sleeps = 0
+        err = saImmOm.saImmOmAdminOwnerInitialize(pyosaf.utils.immom.HANDLE, 
owner_name,
+                saAis.eSaBoolT.SA_TRUE, self.owner_handle)
+        while err == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+            if one_sec_sleeps == TRYAGAIN_CNT:
+                break
+            time.sleep(1)
+            one_sec_sleeps += 1
+            err = 
saImmOm.saImmOmAdminOwnerInitialize(pyosaf.utils.immom.HANDLE, owner_name,
+                saAis.eSaBoolT.SA_TRUE, self.owner_handle)
+
+        if err != eSaAisErrorT.SA_AIS_OK:
+            print "saImmOmAdminOwnerInitialize: %s" % eSaAisErrorT.whatis(err)
+            raise SafException(err)
+
+        self.ccb_handle = saImmOm.SaImmCcbHandleT()
+
+        ccb_flags = saImmOm.SaImmCcbFlagsT(
+            saImm.saImm.SA_IMM_CCB_REGISTERED_OI)
+        one_sec_sleeps = 0
+        err = saImmOm.saImmOmCcbInitialize(self.owner_handle, ccb_flags,
+                                           self.ccb_handle)
+        while err == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+            if one_sec_sleeps == TRYAGAIN_CNT:
+                break
+            time.sleep(1)
+            one_sec_sleeps += 1
+            err = saImmOm.saImmOmCcbInitialize(self.owner_handle, ccb_flags,
+                                               self.ccb_handle)
+
+        if err != eSaAisErrorT.SA_AIS_OK:
+            print "saImmOmCcbInitialize: %s" % eSaAisErrorT.whatis(err)
+            raise SafException(err)
+
+    def __del__(self):
+        one_sec_sleeps = 0
+        error = saImmOm.saImmOmAdminOwnerFinalize(self.owner_handle)
+        while error == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+            if one_sec_sleeps == TRYAGAIN_CNT:
+                break
+            time.sleep(1)
+            one_sec_sleeps += 1
+            error = saImmOm.saImmOmAdminOwnerFinalize(self.owner_handle)
+
+        if error != eSaAisErrorT.SA_AIS_OK:
+            print "saImmOmAdminOwnerFinalize: %s" % eSaAisErrorT.whatis(error)
+            raise SafException(error)
+
+    def create(self, obj, _parent_name=None):
+        ''' add to the CCB the object 'obj' '''
+        if _parent_name is not None:
+            parent_name = SaNameT(_parent_name)
+            object_names = [parent_name]
+            err = saImmOm.saImmOmAdminOwnerSet(self.owner_handle, object_names,
+                eSaImmScopeT.SA_IMM_SUBTREE)
+            if err != eSaAisErrorT.SA_AIS_OK:
+                msg = "saImmOmAdminOwnerSet: %s - obj:%s" % \
+                    (_parent_name, eSaAisErrorT.whatis(err))
+                raise SafException(err, msg)
+        else:
+            parent_name = None
+
+        attr_values = []
+        for attr_name, type_values in obj.attrs.iteritems():
+            values = type_values[1]
+            attr = SaImmAttrValuesT_2()
+            attr.attrName = attr_name
+            attr.attrValueType = type_values[0]
+            attr.attrValuesNumber = len(values)
+            attr.attrValues = marshal_c_array(attr.attrValueType, values)
+            attr_values.append(attr)
+
+        err = saImmOm.saImmOmCcbObjectCreate_2(self.ccb_handle,
+                                               obj.class_name,
+                                               parent_name,
+                                               attr_values)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            msg = "saImmOmCcbObjectCreate_2: %s, parent:%s, class:%s" % (
+                eSaAisErrorT.whatis(err), _parent_name, obj.class_name)
+            raise SafException(err, msg)
+
+    def delete(self, _object_name):
+        if _object_name is None:
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_NOT_EXIST)
+
+        object_name = SaNameT(_object_name)
+        object_names = [object_name]
+
+        err = saImmOm.saImmOmAdminOwnerSet(self.owner_handle, object_names,
+            eSaImmScopeT.SA_IMM_SUBTREE)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(err, "saImmOmAdminOwnerSet: %s - %s" % \
+                (_object_name, eSaAisErrorT.whatis(err)))
+
+        err = saImmOm.saImmOmCcbObjectDelete(self.ccb_handle, object_name)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(err, "saImmOmCcbObjectDelete: %s - %s" % \
+                (_object_name, eSaAisErrorT.whatis(err)))
+
+    def modify_value_add(self, object_name, attr_name, value):
+        ''' add to the CCB an ADD modification of an existing object '''
+
+        assert object_name
+
+        # first get class name to read class description to get value type...
+        try:
+            obj = pyosaf.utils.immom.get(object_name)
+        except SafException as err:
+            print "failed: %s" % err
+            return
+
+        object_names = [SaNameT(object_name)]
+        class_name = obj.SaImmAttrClassName
+        value_type = None
+        attr_def_list = pyosaf.utils.immom.class_description_get(class_name)
+        for attr_def in attr_def_list:
+            if attr_def.attrName == attr_name:
+                value_type = attr_def.attrValueType
+                break
+
+        if value_type is None:
+            # means attribute name is invalid
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_NOT_EXIST,
+                "attribute '%s' does not exist" % attr_name)
+
+        err = saImmOm.saImmOmAdminOwnerSet(self.owner_handle, object_names,
+            eSaImmScopeT.SA_IMM_ONE)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(err, "saImmOmAdminOwnerSet: %s - %s" % \
+                (object_name, eSaAisErrorT.whatis(err)))
+
+        attr_mods = []
+        attr_mod = saImmOm.SaImmAttrModificationT_2()
+        attr_mod.modType = \
+            saImmOm.eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_ADD
+        attr_mod.modAttr = SaImmAttrValuesT_2()
+        attr_mod.modAttr.attrName = attr_name
+        attr_mod.modAttr.attrValueType = value_type
+        attr_mod.modAttr.attrValuesNumber = 1
+
+        values = []
+        values.append(value)
+        try:
+            ptr2ctype = _value_to_ctype_ptr(value_type, value)
+        except ValueError:
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
+                "value '%s' has wrong type" % value)
+
+        attr_mod.modAttr.attrValues = pointer(ptr2ctype)
+        attr_mods.append(attr_mod)
+
+        err = saImmOm.saImmOmCcbObjectModify_2(self.ccb_handle,
+            object_names[0], attr_mods)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            print "saImmOmCcbObjectModify_2: %s, %s" % 
(eSaAisErrorT.whatis(err), object_name)
+            raise SafException(err)
+
+    def modify_value_replace(self, object_name, attr_name, value):
+        ''' add to the CCB an REPLACE modification of an existing object '''
+
+        assert object_name
+
+        # first get class name to read class description to get value type...
+        try:
+            obj = pyosaf.utils.immom.get(object_name)
+        except SafException as err:
+            print "failed: %s" % err
+            return
+
+        object_names = [SaNameT(object_name)]
+        class_name = obj.SaImmAttrClassName
+        value_type = None
+        attr_def_list = pyosaf.utils.immom.class_description_get(class_name)
+        for attr_def in attr_def_list:
+            if attr_def.attrName == attr_name:
+                value_type = attr_def.attrValueType
+                break
+
+        if value_type is None:
+            # means attribute name is invalid
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_NOT_EXIST,
+                "attribute '%s' does not exist" % attr_name)
+
+        err = saImmOm.saImmOmAdminOwnerSet(self.owner_handle, object_names,
+            eSaImmScopeT.SA_IMM_ONE)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(err, "saImmOmAdminOwnerSet: %s - %s" % \
+                (object_name, eSaAisErrorT.whatis(err)))
+
+        attr_mods = []
+        attr_mod = saImmOm.SaImmAttrModificationT_2()
+        attr_mod.modType = \
+            saImmOm.eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_REPLACE
+        attr_mod.modAttr = SaImmAttrValuesT_2()
+        attr_mod.modAttr.attrName = attr_name
+        attr_mod.modAttr.attrValueType = value_type
+        attr_mod.modAttr.attrValuesNumber = 1
+
+        values = []
+        values.append(value)
+        try:
+            ptr2ctype = _value_to_ctype_ptr(value_type, value)
+        except ValueError:
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
+                "value '%s' has wrong type" % value)
+
+        attr_mod.modAttr.attrValues = pointer(ptr2ctype)
+        attr_mods.append(attr_mod)
+
+        err = saImmOm.saImmOmCcbObjectModify_2(self.ccb_handle,
+            object_names[0], attr_mods)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            print "saImmOmCcbObjectModify_2: %s, %s" % 
(eSaAisErrorT.whatis(err), object_name)
+            raise SafException(err)
+
+    def modify_value_delete(self, object_name, attr_name, value):
+        ''' add to the CCB an DELETE modification of an existing object '''
+
+        assert object_name
+
+        # first get class name to read class description to get value type...
+        try:
+            obj = pyosaf.utils.immom.get(object_name)
+        except SafException as err:
+            print "failed: %s" % err
+            return
+
+        object_names = [SaNameT(object_name)]
+        class_name = obj.SaImmAttrClassName
+        value_type = None
+        attr_def_list = pyosaf.utils.immom.class_description_get(class_name)
+        for attr_def in attr_def_list:
+            if attr_def.attrName == attr_name:
+                value_type = attr_def.attrValueType
+                break
+
+        if value_type is None:
+            # means attribute name is invalid
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_NOT_EXIST,
+                "attribute '%s' does not exist" % attr_name)
+
+        err = saImmOm.saImmOmAdminOwnerSet(self.owner_handle, object_names,
+            eSaImmScopeT.SA_IMM_ONE)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(err, "saImmOmAdminOwnerSet: %s - %s" % \
+                (object_name, eSaAisErrorT.whatis(err)))
+
+        attr_mods = []
+        attr_mod = saImmOm.SaImmAttrModificationT_2()
+        attr_mod.modType = \
+            saImmOm.eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_DELETE
+        attr_mod.modAttr = SaImmAttrValuesT_2()
+        attr_mod.modAttr.attrName = attr_name
+        attr_mod.modAttr.attrValueType = value_type
+        attr_mod.modAttr.attrValuesNumber = 1
+
+        values = []
+        values.append(value)
+        try:
+            ptr2ctype = _value_to_ctype_ptr(value_type, value)
+        except ValueError:
+            raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
+                "value '%s' has wrong type" % value)
+
+        attr_mod.modAttr.attrValues = pointer(ptr2ctype)
+        attr_mods.append(attr_mod)
+
+        err = saImmOm.saImmOmCcbObjectModify_2(self.ccb_handle,
+            object_names[0], attr_mods)
+        if err != eSaAisErrorT.SA_AIS_OK:
+            print "saImmOmCcbObjectModify_2: %s, %s" % 
(eSaAisErrorT.whatis(err), object_name)
+            raise SafException(err)
+
+    def apply(self):
+        ''' Apply the CCB '''
+
+        one_sec_sleeps = 0
+        err = saImmOm.saImmOmCcbApply(self.ccb_handle)
+        while err == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+            if one_sec_sleeps == TRYAGAIN_CNT:
+                break
+            time.sleep(1)
+            one_sec_sleeps += 1
+            err = saImmOm.saImmOmCcbApply(self.ccb_handle)
+
+        if err != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(err)
+
+def test():
+    ccb = Ccb()
+    ccb.modify("safAmfCluster=myAmfCluster", "saAmfClusterStartupTimeout",
+               10000000000)
+    ccb.apply()
+    del ccb
+
+if __name__ == '__main__':
+    test()
diff --git a/python/pyosaf/utils/immom/common.py 
b/python/pyosaf/utils/immom/common.py
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/immom/common.py
@@ -0,0 +1,32 @@
+############################################################################
+#
+# (C) Copyright 2014 The OpenSAF Foundation
+#
+# 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 OM common utilitites
+'''
+
+from pyosaf.saAis import eSaAisErrorT
+
+class SafException(Exception):
+    ''' SAF Exception that can be printed '''
+    def __init__(self, value, msg=None):
+        Exception.__init__(self)
+        self.value = value
+        self.msg = msg
+    def __str__(self):
+        return eSaAisErrorT.whatis(self.value)
+
diff --git a/python/pyosaf/utils/immom/iterator.py 
b/python/pyosaf/utils/immom/iterator.py
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/immom/iterator.py
@@ -0,0 +1,139 @@
+############################################################################
+#
+# (C) Copyright 2014 The OpenSAF Foundation
+#
+# 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 Search iterators
+'''
+
+import sys
+import time
+import collections
+from ctypes import pointer, c_char_p, cast, c_void_p
+
+from pyosaf.saAis import eSaAisErrorT, SaNameT, unmarshalNullArray
+
+from pyosaf.saImm import saImm, eSaImmScopeT, eSaImmValueTypeT, \
+    unmarshalSaImmValue, SaImmAttrNameT, SaImmSearchParametersT_2, \
+    SaImmAttrValuesT_2
+
+from pyosaf import saImmOm
+import pyosaf.utils.immom
+from pyosaf.utils.immom.common import SafException
+from pyosaf.utils.immom.object import ImmObject
+
+TRYAGAIN_CNT = 60
+
+
+class SearchIterator(collections.Iterator):
+    ''' general search iterator '''
+    def __init__(self, root_name=None, scope=eSaImmScopeT.SA_IMM_SUBTREE,
+            attribute_names=None, _search_param=None):
+
+        self.search_handle = saImmOm.SaImmSearchHandleT()
+        if root_name is not None:
+            self.root_name = SaNameT(root_name)
+        else:
+            self.root_name = None
+        self.scope = scope
+        self.attribute_names = \
+            [SaImmAttrNameT(n) for n in attribute_names] \
+                if attribute_names else None
+
+        search_options = saImm.SA_IMM_SEARCH_ONE_ATTR
+        if attribute_names is None:
+            search_options |= saImm.SA_IMM_SEARCH_GET_ALL_ATTR
+        else:
+            search_options |= saImm.SA_IMM_SEARCH_GET_SOME_ATTR
+
+        if _search_param is None:
+            search_param = SaImmSearchParametersT_2()
+        else:
+            search_param = _search_param
+
+        err = saImmOm.saImmOmSearchInitialize_2(pyosaf.utils.immom.HANDLE, 
self.root_name,
+            self.scope, search_options, search_param, self.attribute_names,
+            self.search_handle)
+        one_sec_sleeps = 0
+        while err == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
+            if one_sec_sleeps == TRYAGAIN_CNT:
+                break
+            time.sleep(1)
+            one_sec_sleeps += 1
+            err = saImmOm.saImmOmSearchInitialize_2(pyosaf.utils.immom.HANDLE,
+                self.root_name, self.scope, search_options, search_param,
+                self.attribute_names, self.search_handle)
+
+        if err != eSaAisErrorT.SA_AIS_OK:
+            if err == eSaAisErrorT.SA_AIS_ERR_NOT_EXIST:
+                self.search_handle = None
+                raise SafException(err, "%s does not exist" % root_name)
+            else:
+                raise SafException(err)
+
+    def __del__(self):
+        if self.search_handle is not None:
+            error = saImmOm.saImmOmSearchFinalize(self.search_handle)
+            if error != eSaAisErrorT.SA_AIS_OK:
+                raise SafException(error)
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        name = SaNameT()
+        attributes = pointer(pointer(SaImmAttrValuesT_2()))
+        error = saImmOm.saImmOmSearchNext_2(self.search_handle, name,
+                                            attributes)
+        if error == eSaAisErrorT.SA_AIS_ERR_NOT_EXIST:
+            raise StopIteration
+        elif error != eSaAisErrorT.SA_AIS_OK:
+            raise SafException(error)
+
+        attribs = {}
+        attr_list = unmarshalNullArray(attributes)
+        for attr in attr_list:
+            attr_range = range(attr.attrValuesNumber)
+            attribs[attr.attrName] = [attr.attrValueType,
+                [unmarshalSaImmValue(
+                    attr.attrValues[val],
+                    attr.attrValueType) for val in attr_range]
+                ]
+
+        return ImmObject(name.value, attribs)
+
+
+class InstanceIterator(SearchIterator):
+    ''' iterator over instances of a class '''
+    def __init__(self, class_name, root_name=None):
+        name = c_char_p(class_name)
+        search_param = SaImmSearchParametersT_2()
+        search_param.searchOneAttr.attrName = "SaImmAttrClassName"
+        search_param.searchOneAttr.attrValueType = \
+            eSaImmValueTypeT.SA_IMM_ATTR_SASTRINGT
+        search_param.searchOneAttr.attrValue = cast(pointer(name), c_void_p)
+        SearchIterator.__init__(self, root_name, _search_param=search_param)
+
+
+def test():
+    ''' test function '''
+    it = InstanceIterator(sys.argv[1])
+    for dn, attr in it:
+        print dn.split("=")[1]
+        print attr, "\n"
+
+if __name__ == '__main__':
+    test()
diff --git a/python/pyosaf/utils/immom/object.py 
b/python/pyosaf/utils/immom/object.py
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/immom/object.py
@@ -0,0 +1,108 @@
+############################################################################
+#
+# (C) Copyright 2014 The OpenSAF Foundation
+#
+# 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 Object representation.
+'''
+
+from pyosaf.saImm import saImm
+from pyosaf import saImmOm
+import pyosaf.utils.immom
+
+
+class ImmObject(object):
+    ''' Instances of this class represents an IMM object.
+        Created by iterators and accessor reading from IMM or when
+        creating objects in IMM.
+    '''
+
+    ''' cache of class descriptions for the purpose to know if an attribute
+    is multivalue and also its type
+    '''
+    class_desc = {}
+
+    def __init__(self, dn=None, attributes=None, class_name=None):
+        '''
+        Constructor for IMM object.
+        attributes is a map where attribute name is key, value is a tuple
+        of (valueType, values), values is a list.
+        class_name and attributes are mutually exclusive.
+        '''
+        self.__dict__["dn"] = dn
+
+        # mutually exclusive for read vs create
+        if class_name is not None:
+            assert attributes is None
+            self.__dict__["attrs"] = {}
+            self.__dict__["class_name"] = class_name
+            self.class_desc[class_name] = \
+                pyosaf.utils.immom.class_description_get(class_name)
+        elif attributes is not None:
+            assert class_name is None
+            self.__dict__["attrs"] = attributes
+            class_name = attributes["SaImmAttrClassName"][1][0]
+            self.__dict__["class_name"] = class_name
+            if not class_name in self.class_desc:
+                self.class_desc[class_name] = \
+                    pyosaf.utils.immom.class_description_get(class_name)
+        else:
+            raise
+
+    def get_value_type(self, attrname):
+        ''' returns IMM value type of the named attribute '''
+        for attrdef in self.class_desc[self.class_name]:
+            if attrdef.attrName == attrname:
+                return attrdef.attrValueType
+
+    def __attr_is_multivalue(self, attrname):
+        ''' returns True if attribute is multivalue (internal) '''
+        for attrdef in self.class_desc[self.class_name]:
+            if attrdef.attrName == attrname:
+                return attrdef.attrFlags & saImm.SA_IMM_ATTR_MULTI_VALUE
+
+    def __getattr__(self, name):
+        if not name in self.attrs:
+            raise KeyError("%s is not a valid attribute name" % name)
+
+        if self.__attr_is_multivalue(name):
+            return self.attrs[name][1]  # returns a list of values
+        else:
+            if len(self.attrs[name][1]) > 0:
+                return self.attrs[name][1][0]  # returns single value
+            else:
+                return None
+
+    def __getitem__(self, item):
+        return self.__getattr__(item)
+
+    def __contains__(self, attr_name):
+        if attr_name in self.attrs:
+            if len(self.attrs[attr_name][1]) > 0:
+                return True
+            else:
+                return False
+        else:
+            return False
+
+    def __setattr__(self, key, value):
+        value_type = self.get_value_type(key)
+        if type(value) is list:
+            attr_value = (value_type, value)
+        else:
+            attr_value = (value_type, [value])
+
+        self.attrs[key] = attr_value

------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to