+ improve OI utils use a separate instance OM agent
+ refactor OM utils with Ccb inheritace OmAgent, rename some classes...
---
python/pyosaf/utils/immoi/__init__.py | 531 +++++++------------------------
python/pyosaf/utils/immoi/agent.py | 473 +++++++++++++++++++++++++++
python/pyosaf/utils/immoi/implementer.py | 141 ++++----
python/pyosaf/utils/immom/__init__.py | 7 +-
python/pyosaf/utils/immom/accessor.py | 31 +-
python/pyosaf/utils/immom/agent.py | 31 +-
python/pyosaf/utils/immom/ccb.py | 71 +----
python/pyosaf/utils/immom/iterator.py | 4 +-
python/pyosaf/utils/immom/object.py | 4 +-
9 files changed, 736 insertions(+), 557 deletions(-)
create mode 100644 python/pyosaf/utils/immoi/agent.py
diff --git a/python/pyosaf/utils/immoi/__init__.py
b/python/pyosaf/utils/immoi/__init__.py
index 1b4dece..7247b0e 100644
--- a/python/pyosaf/utils/immoi/__init__.py
+++ b/python/pyosaf/utils/immoi/__init__.py
@@ -22,298 +22,23 @@ Supported functions:
- Set/clear/release implementer for class/object
- Create/delete/update runtime object
- Get class/object attributes
-- Get IMM error strings
+- Get/set IMM error strings
+- Get parent for dn
+- Get class for dn
+- Get objects for class
+- Get available classes of IMM
"""
from __future__ import print_function
-from copy import deepcopy
-from ctypes import c_char_p, c_void_p, cast, pointer
-
-from pyosaf.saAis import SaStringT, SaVersionT, SaNameT, SaSelectionObjectT, \
- unmarshalSaStringTArray, eSaDispatchFlagsT, eSaAisErrorT
-from pyosaf import saImm, saImmOi
-from pyosaf.saImm import unmarshalSaImmValue, SaImmAttrNameT, \
- SaImmAttrValuesT_2, SaImmClassNameT, SaImmSearchParametersT_2, \
- eSaImmValueTypeT, SaImmAttrDefinitionT_2, SaImmClassCategoryT, \
- SaImmAttrModificationT_2, eSaImmAttrModificationTypeT
-from pyosaf.saImmOi import SaImmOiHandleT, SaImmOiImplementerNameT
-from pyosaf.utils import immom, log_err, bad_handle_retry, decorate, \
- deprecate, initialize_decorate, SafException
+
+from pyosaf.saAis import SaSelectionObjectT, eSaAisErrorT
+from pyosaf.utils import deprecate, SafException
from pyosaf.utils.immom.object import ImmObject
-from pyosaf.utils.immom.ccb import marshal_c_array
-from pyosaf.utils.immom.iterator import SearchIterator
+from pyosaf.utils.immoi.agent import OiAgent
-OPENSAF_IMM_OBJECT = "opensafImm=opensafImm,safApp=safImmService"
_oi_agent = None
-# Decorate pure saImmOi* API's with error-handling retry and exception raising
-saImmOiInitialize_2 = initialize_decorate(saImmOi.saImmOiInitialize_2)
-saImmOiSelectionObjectGet = decorate(saImmOi.saImmOiSelectionObjectGet)
-saImmOiDispatch = decorate(saImmOi.saImmOiDispatch)
-saImmOiFinalize = decorate(saImmOi.saImmOiFinalize)
-saImmOiImplementerSet = decorate(saImmOi.saImmOiImplementerSet)
-saImmOiImplementerClear = decorate(saImmOi.saImmOiImplementerClear)
-saImmOiClassImplementerSet = decorate(saImmOi.saImmOiClassImplementerSet)
-saImmOiClassImplementerRelease = \
- decorate(saImmOi.saImmOiClassImplementerRelease)
-saImmOiObjectImplementerSet = decorate(saImmOi.saImmOiObjectImplementerSet)
-saImmOiObjectImplementerRelease = \
- decorate(saImmOi.saImmOiObjectImplementerRelease)
-saImmOiRtObjectCreate_2 = decorate(saImmOi.saImmOiRtObjectCreate_2)
-saImmOiRtObjectDelete = decorate(saImmOi.saImmOiRtObjectDelete)
-saImmOiRtObjectUpdate_2 = decorate(saImmOi.saImmOiRtObjectUpdate_2)
-saImmOiAdminOperationResult = decorate(saImmOi.saImmOiAdminOperationResult)
-saImmOiAdminOperationResult_o2 = \
- decorate(saImmOi.saImmOiAdminOperationResult_o2)
-saImmOiAugmentCcbInitialize = decorate(saImmOi.saImmOiAugmentCcbInitialize)
-saImmOiCcbSetErrorString = decorate(saImmOi.saImmOiCcbSetErrorString)
-
-
-class OiAgent(object):
- """ This class acts as a high-level OI agent, providing OI functions to
- the users as a higher level, and relieving the users of the need to manage
- the life cycle of the OI agent and providing general interface for
- Implementer or Applier used
- """
- def __init__(self, version=None):
- """ Constructor for OiAgent class
-
- Args:
- version (SaVersionT): OI API version
- """
- self.handle = None
- self.init_version = version if version is not None \
- else SaVersionT('A', 2, 15)
- self.version = None
- self.selection_object = None
- self.callbacks = None
- global _oi_agent
- _oi_agent = self
-
- def _fetch_sel_obj(self):
- """ Obtain a selection object (OS file descriptor)
-
- Returns:
- SaAisErrorT: Return code of the saImmOiSelectionObjectGet() API
- """
- rc = saImmOiSelectionObjectGet(self.handle, self.selection_object)
- if rc != eSaAisErrorT.SA_AIS_OK:
- log_err("saImmOiSelectionObjectGet FAILED - %s" %
- eSaAisErrorT.whatis(rc))
-
- return rc
-
- def initialize(self, callbacks=None):
- """ Initialize the IMM OI agent
-
- Args:
- callbacks (SaImmOiCallbacksT_2): OI callbacks to register with IMM
-
- Returns:
- SaAisErrorT: Return code of OI initialize
- """
- self.handle = SaImmOiHandleT()
- self.selection_object = SaSelectionObjectT()
- if callbacks is not None:
- self.callbacks = callbacks
- self.version = deepcopy(self.init_version)
- rc = saImmOiInitialize_2(self.handle, self.callbacks,
- self.version)
- if rc == eSaAisErrorT.SA_AIS_OK:
- rc = self._fetch_sel_obj()
- if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
- rc = self.re_initialize()
- else:
- log_err("saImmOiInitialize_2 FAILED - %s" %
- eSaAisErrorT.whatis(rc))
-
- return rc
-
- @bad_handle_retry
- def re_initialize(self):
- """ Re-initialize the IMM OI agent
-
- Returns:
- SaAisErrorT: Return code of OI initialize
- """
- self.finalize()
- rc = self.initialize()
-
- return rc
-
- def finalize(self):
- """ Finalize IMM OI agent handle
-
- Returns:
- SaAisErrorT: Return code of OI finalize
- """
- rc = eSaAisErrorT.SA_AIS_OK
- if self.handle is not None:
- rc = saImmOiFinalize(self.handle)
- if rc != eSaAisErrorT.SA_AIS_OK:
- log_err("saImmOiFinalize FAILED - %s" %
- eSaAisErrorT.whatis(rc))
- elif rc == eSaAisErrorT.SA_AIS_OK \
- or rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
- # If the Finalize() call returned BAD_HANDLE, the handle should
- # already become stale and invalid, so we reset it anyway.
- self.handle = None
- return rc
-
- def get_selection_object(self):
- """ Return the selection object associating with the OI handle
-
- Returns:
- SaSelectionObjectT: Selection object associated with the OI handle
- """
- return self.selection_object
-
- def dispatch(self, flags=eSaDispatchFlagsT.SA_DISPATCH_ALL):
- """ Dispatch all queued callbacks
-
- Args:
- flags (eSaDispatchFlagsT): Flags specifying dispatch mode
-
- Returns:
- SaAisErrorT: Return code of OI dispatch
- """
- rc = saImmOiDispatch(self.handle, flags)
- return rc
-
- def create_runtime_object(self, class_name, parent_name, runtime_obj):
- """ Create a runtime object
-
- Args:
- class_name (str): Class name
- parent_name (str): Parent name
- runtime_obj (ImmObject): Runtime object to create
-
- Returns:
- SaAisErrorT: Return code of OI create runtime object
- """
- # Marshall parameters
- c_class_name = SaImmClassNameT(class_name)
- if parent_name:
- c_parent_name = SaNameT(parent_name)
- else:
- c_parent_name = None
-
- c_attr_values = []
-
- for name, (c_attr_type, values) in runtime_obj.attrs.items():
- if values is None:
- values = []
- elif values == [None]:
- values = []
-
- # Make sure all values are in lists
- if not isinstance(values, list):
- values = [values]
-
- # Create the values struct
- c_attr = SaImmAttrValuesT_2()
- c_attr.attrName = SaImmAttrNameT(name)
- c_attr.attrValueType = c_attr_type
- c_attr.attrValuesNumber = len(values)
-
- if not values:
- c_attr.attrValues = None
- else:
- c_attr.attrValues = marshal_c_array(c_attr_type, values)
-
- c_attr_values.append(c_attr)
-
- rc = saImmOiRtObjectCreate_2(self.handle, c_class_name,
- c_parent_name, c_attr_values)
- return rc
-
- def delete_runtime_object(self, dn):
- """ Delete a runtime object
-
- Args:
- dn (str): Runtime object dn
-
- Returns:
- SaAisErrorT: Return code of OI delete runtime object
- """
- # Marshall the parameter
- c_dn = SaNameT(dn)
- rc = saImmOiRtObjectDelete(self.handle, c_dn)
-
- return rc
-
- def update_runtime_object(self, dn, attributes):
- """ Update the specified object with the requested attribute
- modifications
-
- Args:
- dn (str): Object dn
- attributes (dict): Dictionary of attribute modifications
-
- Returns:
- SaAisErrorT: Return code of OI update runtime object
- """
- # Get the class name for the object
- class_name = get_class_name_for_dn(dn)
-
- # Create and marshall attribute modifications
- attr_mods = []
-
- for name, values in attributes.items():
- if values is None:
- print("WARNING: Received no values for %s in %s" % (name, dn))
- continue
- if not isinstance(values, list):
- values = [values]
-
- attr_type = get_attribute_type(name, class_name)
- c_attr_mod = SaImmAttrModificationT_2()
- c_attr_mod.modType = \
- eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_REPLACE
- c_attr_mod.modAttr = SaImmAttrValuesT_2()
- c_attr_mod.modAttr.attrName = SaImmAttrNameT(name)
- c_attr_mod.modAttr.attrValueType = attr_type
- c_attr_mod.modAttr.attrValuesNumber = len(values)
- c_attr_mod.modAttr.attrValues = marshal_c_array(attr_type, values)
- attr_mods.append(c_attr_mod)
-
- rc = saImmOiRtObjectUpdate_2(self.handle, SaNameT(dn), attr_mods)
-
- return rc
-
- def report_admin_operation_result(self, invocation_id, result):
- """ Report the result of an administrative operation
-
- Args:
- invocation_id (SaInvocationT): Invocation id
- result (SaAisErrorT): Result of admin operation
-
- Returns:
- SaAisErrorT: Return code of OI admin operation
- """
- rc = saImmOiAdminOperationResult(self.handle, invocation_id,
- result)
-
- return rc
-
- def set_error_string(self, ccb_id, error_string):
- """ Set the error string
- This can only be called from within OI callbacks of a real implementer.
-
- Args:
- ccb_id (SaImmOiCcbIdT): CCB id
- error_string (str): Error string
-
- Returns:
- SaAisErrorT: Return code of OI CCB set error string
- """
- c_error_string = SaStringT(error_string)
- rc = saImmOiCcbSetErrorString(self.handle, ccb_id, c_error_string)
-
- return rc
-
-
# Keep old user interfaces of OI pyosaf utils
@deprecate
def initialize(callbacks=None):
@@ -327,8 +52,8 @@ def initialize(callbacks=None):
is not SA_AIS_OK
"""
global _oi_agent
- if _oi_agent is None:
- _oi_agent = OiAgent()
+ _oi_agent = OiAgent()
+
rc = _oi_agent.initialize(callbacks=callbacks)
if rc != eSaAisErrorT.SA_AIS_OK:
raise SafException(rc)
@@ -342,10 +67,9 @@ def get_selection_object():
SaSelectionObjectT: Return code of selection object get
Raises:
- SafException: If the return code of the corresponding OI API call(s)
- is not SA_AIS_OK
+ SafException: If the OI agent is not initialized
"""
- if _oi_agent is not None:
+ if _oi_agent is None:
# SA_AIS_ERR_INIT is returned if user calls this function without first
# calling initialize()
raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
@@ -363,11 +87,16 @@ def create_rt_object(class_name, parent_name, runtime_obj):
runtime_obj (ImmObject): Runtime object to create
Raises:
- SafException: If the return code of the corresponding OI API call(s)
- is not SA_AIS_OK
+ SafException: If the OI agent is not initialized
"""
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ rc = eSaAisErrorT.SA_AIS_ERR_INIT
+ else:
+ rc = _oi_agent.create_runtime_object(class_name, parent_name,
+ runtime_obj)
- rc = _oi_agent.create_runtime_object(class_name, parent_name, runtime_obj)
if rc != eSaAisErrorT.SA_AIS_OK:
raise SafException(rc)
@@ -380,10 +109,15 @@ def delete_rt_object(dn):
dn (str): Runtime object dn
Raises:
- SafException: If the return code of the corresponding OI API call(s)
- is not SA_AIS_OK
+ SafException: If the OI agent is not initialized
"""
- rc = _oi_agent.delete_runtime_object(dn)
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ rc = eSaAisErrorT.SA_AIS_ERR_INIT
+ else:
+ rc = _oi_agent.delete_runtime_object(dn)
+
if rc != eSaAisErrorT.SA_AIS_OK:
raise SafException(rc)
@@ -398,10 +132,15 @@ def update_rt_object(dn, attributes):
attributes (dict): Dictionary of attribute modifications
Raises:
- SafException: If the return code of the corresponding OI API call(s)
- is not SA_AIS_OK
+ SafException: If the OI agent is not initialized
"""
- rc = _oi_agent.update_runtime_object(dn, attributes)
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ rc = eSaAisErrorT.SA_AIS_ERR_INIT
+ else:
+ rc = _oi_agent.update_runtime_object(dn, attributes)
+
if rc != eSaAisErrorT.SA_AIS_OK:
raise SafException(rc)
@@ -415,10 +154,15 @@ def report_admin_operation_result(invocation_id, result):
result (SaAisErrorT): Result of admin operation
Raises:
- SafException: If the return code of the corresponding OI API call(s)
- is not SA_AIS_OK
+ SafException: If the OI agent is not initialized
"""
- rc = _oi_agent.report_admin_operation_result(invocation_id, result)
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ rc = eSaAisErrorT.SA_AIS_ERR_INIT
+ else:
+ rc = _oi_agent.report_admin_operation_result(invocation_id, result)
+
if rc != eSaAisErrorT.SA_AIS_OK:
raise SafException(rc)
@@ -433,26 +177,20 @@ def set_error_string(ccb_id, error_string):
error_string (str): Error string
Raises:
- SafException: If the return code of the corresponding OI API call(s)
- is not SA_AIS_OK
+ SafException: If the OI agent is not initialized
"""
- rc = _oi_agent.set_error_string(ccb_id, error_string)
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ rc = eSaAisErrorT.SA_AIS_ERR_INIT
+ else:
+ rc = _oi_agent.set_error_string(ccb_id, error_string)
+
if rc != eSaAisErrorT.SA_AIS_OK:
raise SafException(rc)
-def get_class_category(class_name):
- """ Return the category of the given class
-
- Args:
- class_name (str): Class name
-
- Returns:
- SaImmClassCategoryT: Class category
- """
- return immom.get_class_category(class_name)
-
-
+@deprecate
def get_parent_name_for_dn(dn):
""" Return the parent's dn of the given object's dn
@@ -461,13 +199,19 @@ def get_parent_name_for_dn(dn):
Returns:
str: DN of the object's parent
+
+ Raises:
+ SafException: If the OI agent is not initialized
"""
- if ',' in dn:
- return dn.split(',', 1)[1]
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
- return ""
+ return _oi_agent.get_parent_name_for_dn(dn)
+@deprecate
def get_object_names_for_class(class_name):
""" Return instances of the given class
@@ -476,28 +220,19 @@ def get_object_names_for_class(class_name):
Returns:
list: List of object names
+
+ Raises:
+ SafException: If the OI agent is not initialized
"""
- # Marshall the search parameter
- c_class_name = c_char_p(class_name)
- c_search_param = SaImmSearchParametersT_2()
- c_search_param.searchOneAttr.attrName = "SaImmAttrClassName"
- c_search_param.searchOneAttr.attrValueType = \
- eSaImmValueTypeT.SA_IMM_ATTR_SASTRINGT
- c_search_param.searchOneAttr.attrValue = \
- cast(pointer(c_class_name), c_void_p)
-
- # Create the search iterator
- found_objs = SearchIterator(search_param=c_search_param,
- attribute_names=['SaImmAttrClassName'])
- found_objs.init()
- # Return the dn's of found objects
- object_names = []
- for obj in found_objs:
- object_names.append(obj.dn)
-
- return object_names
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
+
+ return _oi_agent.get_object_names_for_class(class_name)
+@deprecate
def get_class_name_for_dn(dn):
""" Return the class name for an instance with the given dn
@@ -506,14 +241,19 @@ def get_class_name_for_dn(dn):
Returns:
str: Class name
+
+ Raises:
+ SafException: If the OI agent is not initialized
"""
- obj = immom.get(dn, ["SaImmAttrClassName"])
- if not obj:
- return None
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
- return obj.SaImmAttrClassName
+ return _oi_agent.get_class_name_for_dn(dn)
+@deprecate
def get_object_no_runtime(dn):
""" Return the IMM object with the given dn
@@ -522,10 +262,19 @@ def get_object_no_runtime(dn):
Returns:
ImmObject: Imm object
+
+ Raises:
+ SafException: If the OI agent is not initialized
"""
- return immom.get(dn, ['SA_IMM_SEARCH_GET_CONFIG_ATTR'])
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
+ return _oi_agent.get_object_no_runtime(dn)
+
+@deprecate
def get_attribute_type(attribute, class_name):
""" Return the type of the attribute in the given class
@@ -535,72 +284,37 @@ def get_attribute_type(attribute, class_name):
Returns:
str: Attribute type
- """
- class_desc = immom.class_description_get(class_name)
- attr_desc = [attr for attr in class_desc if
- attr.attrName == attribute][0]
-
- return attr_desc.attrValueType
-
-def get_rdn_attribute_for_class(class_name):
- """ Return the RDN attribute for the given class
-
- Args:
- class_name (str): Class name
-
- Returns:
- str: RDN of the class
+ Raises:
+ SafException: If the OI agent is not initialized
"""
- desc = immom.class_description_get(class_name)
-
- for attr_desc in desc:
- if attr_desc.attrFlags & saImm.saImm.SA_IMM_ATTR_RDN:
- return attr_desc.attrName
-
- return None
-
-
-def unmarshal_len_array(c_array, length, value_type):
- """ Convert C array with a known length to a Python list
-
- Args:
- c_array (C array): Array in C
- length (int): Length of array
- value_type (str): Element type in array
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
- Returns:
- list: The list converted from c_array
- """
- if not c_array:
- return []
- ctype = c_array[0].__class__
- if ctype is str:
- return unmarshalSaStringTArray(c_array)
- val_list = []
- i = 0
- for ptr in c_array:
- if i == length:
- break
- if not ptr:
- break
- val = unmarshalSaImmValue(ptr, value_type)
- val_list.append(val)
- i = i + 1
-
- return val_list
+ return _oi_agent.get_attribute_type(attribute, class_name)
+@deprecate
def get_available_classes_in_imm():
""" Return a list of all available classes in IMM
Returns:
list: List of available classes
+
+ Raises:
+ SafException: If the OI agent is not initialized
"""
- opensaf_imm = immom.get(OPENSAF_IMM_OBJECT)
- return opensaf_imm.opensafImmClassNames
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
+ return _oi_agent.get_available_classes_in_imm()
+
+@deprecate
def create_non_existing_imm_object(class_name, parent_name,
attributes):
""" Create an ImmObject instance for an object that has not yet existed
@@ -613,21 +327,14 @@ def create_non_existing_imm_object(class_name,
parent_name,
Returns:
ImmObject: Imm object
- """
- rdn_attribute = get_rdn_attribute_for_class(class_name)
- rdn_value = attributes[rdn_attribute][0]
-
- if parent_name:
- dn = '%s,%s' % (rdn_value, parent_name)
- else:
- dn = rdn_value
-
- obj = ImmObject(class_name=class_name, dn=dn)
- for name, values in attributes.items():
- obj.__setattr__(name, values)
-
- obj.__setattr__('SaImmAttrClassName', class_name)
- obj.__setattr__('dn', dn)
+ Raises:
+ SafException: If the OI agent is not initialized
+ """
+ if _oi_agent is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)
- return obj
+ return _oi_agent.create_non_existing_imm_object(class_name, parent_name,
+ attributes)
diff --git a/python/pyosaf/utils/immoi/agent.py
b/python/pyosaf/utils/immoi/agent.py
new file mode 100644
index 0000000..1e34b4f
--- /dev/null
+++ b/python/pyosaf/utils/immoi/agent.py
@@ -0,0 +1,473 @@
+############################################################################
+#
+# (C) Copyright 2015 The OpenSAF Foundation
+# (C) Copyright 2017 Ericsson AB. All rights reserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# 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..1c9f0d8 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
@@ -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)
--
2.7.4
------------------------------------------------------------------------------
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