Improve the implementation of NTF pyosaf utils
---
python/Makefile.am | 6 +-
python/pyosaf/saNtf.py | 4 +-
python/pyosaf/utils/ntf/__init__.py | 855 ++++++++++---------------------
python/pyosaf/utils/ntf/agent.py | 500 ++++++++++++++++++
python/pyosaf/utils/ntf/producer.py | 711 ++++++++++++++++++++++++++
python/pyosaf/utils/ntf/reader.py | 187 +++++++
python/pyosaf/utils/ntf/subscriber.py | 923 ++++++++++++++++++++++++++++++++++
7 files changed, 2599 insertions(+), 587 deletions(-)
create mode 100644 python/pyosaf/utils/ntf/agent.py
create mode 100644 python/pyosaf/utils/ntf/producer.py
create mode 100644 python/pyosaf/utils/ntf/reader.py
create mode 100644 python/pyosaf/utils/ntf/subscriber.py
diff --git a/python/Makefile.am b/python/Makefile.am
index 390366a..0b79067 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -62,6 +62,10 @@ pkgpyosafutilsimmoi_PYTHON = \
python/pyosaf/utils/immoi/implementer.py
pkgpyosafutilsntf_PYTHON = \
- python/pyosaf/utils/ntf/__init__.py
+ python/pyosaf/utils/ntf/__init__.py \
+ python/pyosaf/utils/ntf/agent.py \
+ python/pyosaf/utils/ntf/producer.py \
+ python/pyosaf/utils/ntf/subscriber.py \
+ python/pyosaf/utils/ntf/reader.py
endif
diff --git a/python/pyosaf/saNtf.py b/python/pyosaf/saNtf.py
index 7438cdc..9ee096e 100644
--- a/python/pyosaf/saNtf.py
+++ b/python/pyosaf/saNtf.py
@@ -15,7 +15,7 @@
#
############################################################################
-from ctypes import POINTER, CFUNCTYPE, Structure, Union, CDLL, c_char
+from ctypes import POINTER, CFUNCTYPE, Structure, Union, CDLL, c_char, cast
from pyosaf.saAis import SaUint64T, SaEnumT, Enumeration, Const, BYREF, \
SaUint32T, SaUint16T, SaBoolT, SaStringT, SaNameT, SaTimeT, SaDoubleT,
\
SaInt64T, SaUint8T, SaInt8T, SaInt16T, SaInt32T, SaFloatT, SaAnyT
@@ -655,7 +655,7 @@ class SaNtfNotificationTypeFilterHandlesT_3(Structure):
('securityAlarmFilterHandle', SaNtfNotificationFilterHandleT),
('miscellaneousFilterHandle', SaNtfNotificationFilterHandleT)]
-saNtf.SA_NTF_FILTER_HANDLE_NULL = None
+saNtf.SA_NTF_FILTER_HANDLE_NULL = 0
#if defined(SA_NTF_A01) || defined(SA_NTF_A02)
class _notification(Union):
diff --git a/python/pyosaf/utils/ntf/__init__.py
b/python/pyosaf/utils/ntf/__init__.py
index a76867e..0687517 100644
--- a/python/pyosaf/utils/ntf/__init__.py
+++ b/python/pyosaf/utils/ntf/__init__.py
@@ -15,259 +15,49 @@
# Author(s): Ericsson
#
############################################################################
-# pylint: disable=unused-argument,too-many-arguments
+# pylint: disable=too-many-arguments
""" NTF common utilities """
-import ctypes
-
-from pyosaf.saAis import saAis, SaVersionT, SaSelectionObjectT, eSaBoolT, \
- eSaDispatchFlagsT
+from pyosaf.saAis import saAis, eSaAisErrorT, SaVersionT, eSaDispatchFlagsT
from pyosaf import saNtf
-from pyosaf.utils import decorate, initialize_decorate
-
-
-# Decorate pure saNtf* API's with error-handling retry and exception raising
-saNtfInitialize = initialize_decorate(saNtf.saNtfInitialize)
-saNtfLocalizedMessageFree = decorate(saNtf.saNtfLocalizedMessageFree)
-saNtfStateChangeNotificationFilterAllocate = \
- decorate(saNtf.saNtfStateChangeNotificationFilterAllocate)
-saNtfNotificationUnsubscribe = decorate(saNtf.saNtfNotificationUnsubscribe)
-saNtfNotificationReadInitialize = \
- decorate(saNtf.saNtfNotificationReadInitialize)
-saNtfInitialize_2 = initialize_decorate(saNtf.saNtfInitialize_2)
-saNtfNotificationReadInitialize_2 = \
- decorate(saNtf.saNtfNotificationReadInitialize_2)
-saNtfNotificationSubscribe = decorate(saNtf.saNtfNotificationSubscribe)
-saNtfInitialize_3 = initialize_decorate(saNtf.saNtfInitialize_3)
-saNtfSelectionObjectGet = decorate(saNtf.saNtfSelectionObjectGet)
-saNtfDispatch = decorate(saNtf.saNtfDispatch)
-saNtfFinalize = decorate(saNtf.saNtfFinalize)
-saNtfObjectCreateDeleteNotificationAllocate = \
- decorate(saNtf.saNtfObjectCreateDeleteNotificationAllocate)
-saNtfAttributeChangeNotificationAllocate = \
- decorate(saNtf.saNtfAttributeChangeNotificationAllocate)
-saNtfStateChangeNotificationAllocate = \
- decorate(saNtf.saNtfStateChangeNotificationAllocate)
-saNtfStateChangeNotificationAllocate_3 = \
- decorate(saNtf.saNtfStateChangeNotificationAllocate_3)
-saNtfAlarmNotificationAllocate = decorate(saNtf.saNtfAlarmNotificationAllocate)
-saNtfSecurityAlarmNotificationAllocate = \
- decorate(saNtf.saNtfSecurityAlarmNotificationAllocate)
-saNtfMiscellaneousNotificationAllocate = \
- decorate(saNtf.saNtfMiscellaneousNotificationAllocate)
-saNtfPtrValAllocate = decorate(saNtf.saNtfPtrValAllocate)
-saNtfArrayValAllocate = decorate(saNtf.saNtfArrayValAllocate)
-saNtfIdentifierAllocate = decorate(saNtf.saNtfIdentifierAllocate)
-saNtfNotificationSend = decorate(saNtf.saNtfNotificationSend)
-saNtfNotificationSendWithId = decorate(saNtf.saNtfNotificationSendWithId)
-saNtfNotificationFree = decorate(saNtf.saNtfNotificationFree)
-saNtfVariableDataSizeGet = decorate(saNtf.saNtfVariableDataSizeGet)
-saNtfLocalizedMessageGet = decorate(saNtf.saNtfLocalizedMessageGet)
-saNtfLocalizedMessageFree_2 = decorate(saNtf.saNtfLocalizedMessageFree_2)
-saNtfPtrValGet = decorate(saNtf.saNtfPtrValGet)
-saNtfArrayValGet = decorate(saNtf.saNtfArrayValGet)
-saNtfObjectCreateDeleteNotificationFilterAllocate = \
- decorate(saNtf.saNtfObjectCreateDeleteNotificationFilterAllocate)
-saNtfAttributeChangeNotificationFilterAllocate = \
- decorate(saNtf.saNtfAttributeChangeNotificationFilterAllocate)
-saNtfStateChangeNotificationFilterAllocate_2 = \
- decorate(saNtf.saNtfStateChangeNotificationFilterAllocate_2)
-saNtfAlarmNotificationFilterAllocate = \
- decorate(saNtf.saNtfAlarmNotificationFilterAllocate)
-saNtfSecurityAlarmNotificationFilterAllocate = \
- decorate(saNtf.saNtfSecurityAlarmNotificationFilterAllocate)
-saNtfNotificationFilterFree = decorate(saNtf.saNtfNotificationFilterFree)
-saNtfNotificationSubscribe_3 = decorate(saNtf.saNtfNotificationSubscribe_3)
-saNtfNotificationReadInitialize_3 = \
- decorate(saNtf.saNtfNotificationReadInitialize_3)
-saNtfNotificationUnsubscribe_2 = decorate(saNtf.saNtfNotificationUnsubscribe_2)
-saNtfNotificationReadNext = decorate(saNtf.saNtfNotificationReadNext)
-saNtfNotificationReadNext_3 = decorate(saNtf.saNtfNotificationReadNext_3)
-saNtfNotificationReadFinalize = decorate(saNtf.saNtfNotificationReadFinalize)
-
-
-handle = saNtf.SaNtfHandleT()
-selection_object = SaSelectionObjectT()
-callbacks = saNtf.SaNtfCallbacksT()
-
-
-class AdditionalInfo(object):
- """ Represent a piece of additional info to be included in a notification
- """
- def __init__(self, info_id, info_type, info_value):
- self.info_id = info_id
- self.info_type = info_type
- self.info_value = info_value
-
-
-class StateChange(object):
- """ Contain information about a state change event """
- def __init__(self):
- pass
-
-
-class AttributeChange(object):
- """ Contain information about a change in an attribute """
- def __init__(self):
- pass
-
-
-class Attribute(object):
- """ Contain information about the value and value type of an attribute """
- def __init__(self):
- pass
-
-
-class SecurityAlarmDetector(object):
- """ Represent an instance of a security alarm detector """
- def __init__(self, value=None, value_type=None):
- self.value = value
- self.value_type = value_type
+from pyosaf.utils import deprecate, SafException
+from pyosaf.utils.ntf import agent as ntf
+from pyosaf.utils.ntf.producer import NtfProducer
+from pyosaf.utils.ntf.subscriber import NtfSubscriber
-
-class ServiceUser(object):
- """ Represent a service user """
- def __init__(self, value=None, value_type=None):
- self.value = value
- self.value_type = value_type
-
-
-class ServiceProvider(object):
- """ Represent a service provider """
- def __init__(self, value=None, value_type=None):
- self.value = value
- self.value_type = value_type
-
-
-def dummy_func(*args):
- """ Dummy function used as a callback when no proper callbacks are set """
- pass
+_ntf_producer = None
+_ntf_subscriber = None
+@deprecate
def initialize(notification_callback=None):
""" Initialize the NTF library
Args:
notification_callback (SaNtfNotificationCallbackT): Callback to be
invoked by NTF server to deliver a notification to the subscriber
- """
- # Assign default values for callbacks
- callbacks.saNtfNotificationCallback = \
- saNtf.SaNtfNotificationCallbackT(dummy_func)
- callbacks.saNtfNotificationDiscardedCallback = \
- saNtf.SaNtfNotificationDiscardedCallbackT(dummy_func)
-
- # Override the default notification subscribe callback if one is provided
- if notification_callback:
- callbacks.saNtfNotificationCallback = \
- saNtf.SaNtfNotificationCallbackT(notification_callback)
-
- # Define which version of the NTF API to use
- version = SaVersionT('A', 1, 1)
-
- # Initialize the NTF interface
- saNtfInitialize(handle, callbacks, version)
-
- # Get the selection object
- saNtfSelectionObjectGet(handle, selection_object)
-
-
-def assign_ntf_value_to_attribute(attr_value_field, value, value_type):
- """ Assign the correct sub-field in the given attribute
-
- Args:
- attr_value_field (SaNtfValueT): Object attribute value in an object
- creation or deletion notification
- value (variable-size C data type): Actual value of the object attribute
- value_type (SaNtfValueTypeT): Type of the object attribute value
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
"""
- if value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT8:
- attr_value_field.uint8Val = value
-
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT8:
- attr_value_field.int8Val = value
-
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT16:
- attr_value_field.uint16Val = value
-
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT16:
- attr_value_field.int16Val = value
-
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT32:
- attr_value_field.uint32Val = value
-
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32:
- attr_value_field.int32Val = value
-
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_FLOAT:
- attr_value_field.floatVal = value
+ # Set the NTF API version to initialize
+ version = SaVersionT('A', 1, 1)
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT64:
- attr_value_field.uint64Val = value
+ global _ntf_producer
+ _ntf_producer = NtfProducer(version)
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT64:
- attr_value_field.int64Val = value
+ global _ntf_subscriber
+ _ntf_subscriber = NtfSubscriber(version)
- elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_DOUBLE:
- attr_value_field.doubleVal = value
+ rc = _ntf_producer.init()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
-
-def fill_in_header(notification_handle,
- header, notification_object, notifying_object, vendor_id,
- major_id, minor_id, additional_text, event_type, event_time,
- additional_info):
- """ Fill in the given notification header with the provided information
-
- Args:
- notification_handle (SaNtfNotificationHandleT): Notification handle
- header (SaNtfNotificationHeaderT): Notification header
- notification_object (str): Notification object's dn
- notifying_object (str): Notifying object's dn
- vendor_id (SaUint32T): Vendor id
- major_id (SaUint16T): Major id
- minor_id (SaUint16T): Minor id
- additional_text (str): Additional text
- event_type (SaNtfEventTypeT): Event type
- event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
- """
- header.eventType.contents.value = event_type
- header.notificationObject.contents.value = notification_object
- header.notificationObject.contents.length = len(notification_object)
- header.notifyingObject.contents.value = notifying_object
- header.notifyingObject.contents.length = len(notifying_object)
- header.notificationClassId.contents.vendorId = vendor_id
- header.notificationClassId.contents.majorId = major_id
- header.notificationClassId.contents.minorId = minor_id
- header.eventTime.contents.value = event_time
- header.numCorrelatedNotifications = 0
- header.lengthAdditionalText = len(additional_text)
-
- ctypes.memmove(header.additionalText,
- additional_text,
- len(additional_text))
-
- header.numAdditionalInfo = len(additional_info)
- header.thresholdInformation = None
-
- # Fill in additional info
- if additional_info:
- for i, add_info in enumerate(additional_info):
- header.additionalInfo[i].infoId = add_info.info_id
- header.additionalInfo[i].infoType = add_info.info_type
-
- dest_ptr = (ctypes.c_char * len(add_info.info_value))()
-
- saNtf.saNtfPtrValAllocate(notification_handle,
- len(add_info.info_value) + 1,
- dest_ptr,
- header.additionalInfo[i].infoValue)
- ctypes.memmove(ctypes.addressof(dest_ptr), add_info.info_value,
- len(add_info.info_value) + 1)
- else:
- header.additionalInfo = None
+ rc = _ntf_subscriber.init(notification_callback)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
+@deprecate
def send_object_create_notification(vendor_id, major_id, minor_id,
additional_text="",
notification_object="",
@@ -284,27 +74,42 @@ def send_object_create_notification(vendor_id, major_id,
minor_id,
additional_text (str): Additional text
notification_object (str): Notification object's dn
notifying_object (str): Notifying object's dn
- attributes (list): List of Attribute class instances
+ attributes (list(Attribute)): List of Attribute structures
event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
"""
- if attributes is None:
- attributes = []
+ ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+ if _ntf_producer is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ return eSaAisErrorT.SA_AIS_ERR_INIT
+
+ _ntf_producer.set_event_type(saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_CREATION)
+ _ntf_producer.set_class_id(ntf_class_id)
+ _ntf_producer.set_additional_text(additional_text)
+ _ntf_producer.set_notification_object(notification_object)
+ _ntf_producer.set_notifying_object(notifying_object)
+ if attributes:
+ _ntf_producer.set_object_attributes(attributes)
+ _ntf_producer.set_event_time(event_time)
+ if additional_info:
+ _ntf_producer.set_additional_info(additional_info)
- if additional_info is None:
- additional_info = []
+ rc = _ntf_producer.send_object_create_delete_notification()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
- _send_object_create_delete_notification(
- saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_CREATION,
- vendor_id, major_id, minor_id,
- additional_text=additional_text,
- notification_object=notification_object,
- notifying_object=notifying_object,
- attributes=attributes,
- event_time=event_time,
- additional_info=additional_info)
+ return rc
+@deprecate
def send_object_delete_notification(vendor_id, major_id, minor_id,
additional_text="",
notification_object="",
@@ -321,88 +126,95 @@ def send_object_delete_notification(vendor_id, major_id,
minor_id,
additional_text (str): Additional text
notification_object (str): Notification object's dn
notifying_object (str): Notifying object's dn
- attributes (list): List of Attribute class instances
+ attributes (list(Attribute)): List of Attribute structures
event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
"""
- if attributes is None:
- attributes = []
-
- if additional_info is None:
- additional_info = []
-
- _send_object_create_delete_notification(
- saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_DELETION,
- vendor_id, major_id, minor_id,
- additional_text=additional_text,
- notification_object=notification_object,
- notifying_object=notifying_object,
- attributes=attributes,
- event_time=event_time,
- additional_info=additional_info)
-
-
-def _send_object_create_delete_notification(event_type, vendor_id, major_id,
- minor_id, additional_text="",
- notification_object="",
- notifying_object="",
- attributes=None,
- event_time=saAis.SA_TIME_UNKNOWN,
- additional_info=None):
- """ Common function to send notification about an object creation/deletion
+ ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+ if _ntf_producer is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ return eSaAisErrorT.SA_AIS_ERR_INIT
+
+ _ntf_producer.set_event_type(saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_DELETION)
+ _ntf_producer.set_class_id(ntf_class_id)
+ _ntf_producer.set_additional_text(additional_text)
+ _ntf_producer.set_notification_object(notification_object)
+ _ntf_producer.set_notifying_object(notifying_object)
+ if attributes:
+ _ntf_producer.set_object_attributes(attributes)
+ _ntf_producer.set_event_time(event_time)
+ if additional_info:
+ _ntf_producer.set_additional_info(additional_info)
+
+ rc = _ntf_producer.send_object_create_delete_notification()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
+
+ return rc
+
+
+@deprecate
+def send_attribute_change_notification(
+ vendor_id, major_id, minor_id, additional_text="",
+ notification_object="", notifying_object="",
+ event_type=saNtf.eSaNtfEventTypeT.SA_NTF_ATTRIBUTE_ADDED,
+ event_time=saAis.SA_TIME_UNKNOWN, additional_info=None,
+ changed_attributes=None):
+ """ Send notification about an attribute change event
Args:
- event_type (SaNtfEventTypeT): Event type
vendor_id (SaUint32T): Vendor id
major_id (SaUint16T): Major id
minor_id (SaUint16T): Minor id
additional_text (str): Additional text
notification_object (str): Notification object's dn
notifying_object (str): Notifying object's dn
- attributes (list): List of Attribute class instances
+ event_type (SaNtfEventTypeT): Event type
event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
- """
-
- if attributes is None:
- attributes = []
-
- if additional_info is None:
- additional_info = []
-
- # Create the notification
- notification = saNtf.SaNtfObjectCreateDeleteNotificationT()
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
+ changed_attributes (list(AttributeChange)): List of AttributeChange
+ structures
- saNtfObjectCreateDeleteNotificationAllocate(handle, notification, 0,
- len(additional_text) + 1,
- len(additional_info),
- len(attributes), 0)
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
- # Fill in the header
- fill_in_header(notification.notificationHandle,
- notification.notificationHeader,
- notification_object, notifying_object, vendor_id,
- major_id, minor_id, additional_text,
- event_type, event_time, additional_info)
-
- # Fill in attributes
- for i in range(notification.numAttributes):
- ptr = notification.objectAttributes[i]
-
- ptr.attributeId = attributes[i].attribute_id
- ptr.attributeType = attributes[i].attribute_type
-
- assign_ntf_value_to_attribute(ptr.attributeValue,
- attributes[i].attribute_value,
- attributes[i].attribute_type)
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
+ """
+ ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+ if _ntf_producer is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ return eSaAisErrorT.SA_AIS_ERR_INIT
+
+ _ntf_producer.set_event_type(event_type)
+ _ntf_producer.set_class_id(ntf_class_id)
+ _ntf_producer.set_additional_text(additional_text)
+ _ntf_producer.set_notification_object(notification_object)
+ _ntf_producer.set_notifying_object(notifying_object)
+ _ntf_producer.set_event_time(event_time)
+ if additional_info:
+ _ntf_producer.set_additional_info(additional_info)
+ if changed_attributes:
+ _ntf_producer.set_changed_attributes(changed_attributes)
- # Send the notification
- saNtfNotificationSend(notification.notificationHandle)
+ rc = _ntf_producer.send_attribute_change_notification()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
- # Free the notification
- saNtfNotificationFree(notification.notificationHandle)
+ return rc
+@deprecate
def send_state_change_notification(vendor_id,
major_id,
minor_id,
@@ -422,119 +234,92 @@ def send_state_change_notification(vendor_id,
notification_object (str): Notification object's dn
notifying_object (str): Notifying object's dn
event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
- state_changes (list): List of StateChange class instances
- """
- if additional_info is None:
- additional_info = []
-
- if state_changes is None:
- state_changes = []
-
- event_type = saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_STATE_CHANGE
-
- # Create the notification
- notification = saNtf.SaNtfStateChangeNotificationT()
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
+ state_changes (list(StateChange)): List of StateChange structures
- saNtfStateChangeNotificationAllocate(handle, notification, 0,
- len(additional_text) + 1,
- len(additional_info),
- len(state_changes), 0)
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
- # Fill in the header
- fill_in_header(notification.notificationHandle,
- notification.notificationHeader,
- notification_object, notifying_object, vendor_id,
- major_id, minor_id, additional_text, event_type,
- event_time, additional_info)
-
- # Fill in state changes
- for i, state_change in enumerate(state_changes):
- notification.changedStates[i].stateId = state_change.state_id
- if state_change.old_state_present:
- notification.changedStates[i].oldStatePresent = eSaBoolT.SA_TRUE
- notification.changedStates[i].oldState = state_change.old_state
- else:
- notification.changedStates[i].oldStatePresent = eSaBoolT.SA_FALSE
-
- notification.changedStates[i].newState = state_change.new_state
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
+ """
+ ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+ if _ntf_producer is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ return eSaAisErrorT.SA_AIS_ERR_INIT
+
+ _ntf_producer.set_event_type(
+ saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_STATE_CHANGE)
+ _ntf_producer.set_class_id(ntf_class_id)
+ _ntf_producer.set_additional_text(additional_text)
+ _ntf_producer.set_notification_object(notification_object)
+ _ntf_producer.set_notifying_object(notifying_object)
+ _ntf_producer.set_event_time(event_time)
+ if additional_info:
+ _ntf_producer.set_additional_info(additional_info)
+ if state_changes:
+ _ntf_producer.set_state_changes(state_changes)
- # Send the notification
- saNtfNotificationSend(notification.notificationHandle)
+ rc = _ntf_producer.send_state_change_notification()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
- # Free the notification
- saNtfNotificationFree(notification.notificationHandle)
+ return rc
-def send_attribute_change_notification(
- vendor_id, major_id, minor_id, additional_text="",
+@deprecate
+def send_alarm_notification(
+ vendor_id, major_id, minor_id, perceived_severity, additional_text="",
notification_object="", notifying_object="",
- event_type=saNtf.eSaNtfEventTypeT.SA_NTF_ATTRIBUTE_ADDED,
- event_time=saAis.SA_TIME_UNKNOWN, additional_info=None,
- changed_attributes=None):
- """ Send notification about an attribute change event
+ event_type=saNtf.eSaNtfEventTypeT.SA_NTF_ALARM_PROCESSING,
+ event_time=saAis.SA_TIME_UNKNOWN, additional_info=None):
+ """ Send an alarm notification
Args:
vendor_id (SaUint32T): Vendor id
major_id (SaUint16T): Major id
minor_id (SaUint16T): Minor id
+ perceived_severity (SaNtfSeverityT): Perceived severity
additional_text (str): Additional text
notification_object (str): Notification object's dn
notifying_object (str): Notifying object's dn
event_type (SaNtfEventTypeT): Event type
event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
- changed_attributes (list): List of AttributeChange class instances
- """
- if additional_info is None:
- additional_info = []
-
- if changed_attributes is None:
- changed_attributes = []
-
- # Create the notification
- notification = saNtf.SaNtfAttributeChangeNotificationT()
-
- saNtfAttributeChangeNotificationAllocate(handle, notification, 0,
- len(additional_text) + 1,
- len(additional_info),
- len(changed_attributes), 0)
-
- # Fill in the header
- fill_in_header(notification.notificationHandle,
- notification.notificationHeader,
- notification_object, notifying_object, vendor_id,
- major_id, minor_id, additional_text, event_type,
- event_time, additional_info)
-
- # Fill in attributes
- for i, changed_attribute in enumerate(changed_attributes):
- ptr = notification.changedAttributes[i]
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
- ptr.attributeId = changed_attribute.attribute_id
- ptr.attributeType = changed_attribute.attribute_type
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
- if changed_attribute.old_attribute_present:
- ptr.oldAttributePresent = eSaBoolT.SA_TRUE
-
- assign_ntf_value_to_attribute(
- ptr.oldAttributeValue,
- changed_attribute.old_attribute_value,
- changed_attribute.attribute_type)
- else:
- ptr.oldAttributePresent = eSaBoolT.SA_FALSE
-
- assign_ntf_value_to_attribute(
- ptr.newAttributeValue, changed_attribute.new_attribute_value,
- changed_attribute.attribute_type)
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
+ """
+ ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+ if _ntf_producer is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ return eSaAisErrorT.SA_AIS_ERR_INIT
+
+ _ntf_producer.set_event_type(event_type)
+ _ntf_producer.set_class_id(ntf_class_id)
+ _ntf_producer.set_additional_text(additional_text)
+ _ntf_producer.set_notification_object(notification_object)
+ _ntf_producer.set_notifying_object(notifying_object)
+ _ntf_producer.set_event_time(event_time)
+ _ntf_producer.set_perceived_severity(perceived_severity)
+ if additional_info:
+ _ntf_producer.set_additional_info(additional_info)
- # Send the notification
- saNtfNotificationSend(notification.notificationHandle)
+ rc = _ntf_producer.send_alarm_notification()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
- # Free the notification
- saNtfNotificationFree(notification.notificationHandle)
+ return rc
+@deprecate
def send_security_alarm_notification(
vendor_id, major_id, minor_id, severity, alarm_detector, user,
provider, additional_text="", notification_object="",
@@ -550,220 +335,122 @@ def send_security_alarm_notification(
major_id (SaUint16T): Major id
minor_id (SaUint16T): Minor id
severity (SaNtfSeverityT): Severity
- alarm_detector (SecurityAlarmDetector): Alarm detector information
- user (ServiceUser): Service user information
- provider (ServiceProvider): Service provider information
+ alarm_detector (SecurityAlarmDetector): SecurityAlarmDetector
+ information structure
+ user (ServiceUser): ServiceUser information structure
+ provider (ServiceProvider): ServiceProvider information structure
additional_text (str): Additional text
notification_object (str): Notification object's dn
notifying_object (str): Notifying object's dn
event_type (SaNtfEventTypeT): Event type
event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
probable_cause (SaNtfProbableCauseT): Probable cause
- """
- if additional_info is None:
- additional_info = []
-
- # Create the notification
- notification = saNtf.SaNtfSecurityAlarmNotificationT()
-
- saNtfSecurityAlarmNotificationAllocate(handle, notification, 0,
- len(additional_text) + 1,
- len(additional_info), 0)
-
- # Fill in the header
- fill_in_header(notification.notificationHandle,
- notification.notificationHeader,
- notification_object, notifying_object, vendor_id,
- major_id, minor_id, additional_text, event_type,
- event_time, additional_info)
-
- # Fill in security alarm-specific fields
- notification.probableCause.contents.value = probable_cause
- notification.severity.contents.value = severity
-
- assign_ntf_value_to_attribute(notification.securityAlarmDetector,
- alarm_detector.value,
- alarm_detector.value_type)
- assign_ntf_value_to_attribute(notification.serviceUser,
- user.value,
- user.value_type)
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
- assign_ntf_value_to_attribute(notification.serviceProvider,
- provider.value,
- provider.value_type)
-
- # Send the notification
- saNtfNotificationSend(notification.notificationHandle)
-
- # Free the notification
- saNtfNotificationFree(notification.notificationHandle)
-
-
-def send_alarm_notification(
- vendor_id, major_id, minor_id, severity, additional_text="",
- notification_object="", notifying_object="",
- event_type=saNtf.eSaNtfEventTypeT.SA_NTF_ALARM_PROCESSING,
- event_time=saAis.SA_TIME_UNKNOWN, additional_info=None):
- """ Send an alarm notification
-
- Args:
- vendor_id (SaUint32T): Vendor id
- major_id (SaUint16T): Major id
- minor_id (SaUint16T): Minor id
- severity (SaNtfSeverityT): Severity
- additional_text (str): Additional text
- notification_object (str): Notification object's dn
- notifying_object (str): Notifying object's dn
- event_type (SaNtfEventTypeT): Event type
- event_time (SaTimeT): Event time
- additional_info (list): List of AdditionalInfo class instances
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
"""
- if additional_info is None:
- additional_info = []
-
- # Create the notification
- notification = saNtf.SaNtfAlarmNotificationT()
-
- saNtfAlarmNotificationAllocate(handle, notification, 0,
- len(additional_text) + 1,
- len(additional_info), 0, 0, 0, 0)
-
- # Fill in the header
- fill_in_header(notification.notificationHandle,
- notification.notificationHeader,
- notification_object, notifying_object, vendor_id,
- major_id, minor_id, additional_text, event_type,
- event_time, additional_info)
-
- notification.numMonitoredAttributes = 0
- notification.numSpecificProblems = 0
- notification.numProposedRepairActions = 0
- notification.perceivedSeverity.contents.value = severity
- notification.probableCause.contents.value = \
- saNtf.eSaNtfProbableCauseT.SA_NTF_DEGRADED_SIGNAL
+ ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+ if _ntf_producer is None:
+ # SA_AIS_ERR_INIT is returned if user calls this function without first
+ # calling initialize()
+ return eSaAisErrorT.SA_AIS_ERR_INIT
+
+ _ntf_producer.set_event_type(event_type)
+ _ntf_producer.set_class_id(ntf_class_id)
+ _ntf_producer.set_additional_text(additional_text)
+ _ntf_producer.set_notification_object(notification_object)
+ _ntf_producer.set_notifying_object(notifying_object)
+ _ntf_producer.set_event_time(event_time)
+ if additional_info:
+ _ntf_producer.set_additional_info(additional_info)
+ _ntf_producer.set_severity(severity)
+ _ntf_producer.set_probable_cause(probable_cause)
+ _ntf_producer.set_security_alarm_detector(alarm_detector)
+ _ntf_producer.set_service_user(user)
+ _ntf_producer.set_service_provider(provider)
- # Send the notification
- saNtfNotificationSend(notification.notificationHandle)
+ rc = _ntf_producer.send_security_alarm_notification()
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
- # Free the notification
- saNtfNotificationFree(notification.notificationHandle)
+ return rc
+@deprecate
def subscribe_for_notifications(notification_types=None):
- """ Subscribe for notifications from NTF. The types of notifications to
- subscribe to are passed in the notification_types list and subscriptions
- are set up for all types if the list is empty.
+ """ Subscribe for notifications from NTF with the types specified in the
+ notification_types list
+ If the list is not provided, all types of notification are subscribed to
+ by default.
Args:
- notification_types (list): List of notification types
- """
- filters = []
-
- filter_handles = saNtf.SaNtfNotificationTypeFilterHandlesT()
- filter_handles.objectCreateDeleteFilterHandle = \
- saNtf.SaNtfNotificationFilterHandleT(0)
- filter_handles.attributeChangeFilterHandle = \
- saNtf.SaNtfNotificationFilterHandleT(0)
- filter_handles.stateChangeFilterHandle = \
- saNtf.SaNtfNotificationFilterHandleT(0)
- filter_handles.alarmFilterHandle = saNtf.SaNtfNotificationFilterHandleT(0)
- filter_handles.securityFilterHandle = \
- saNtf.SaNtfNotificationFilterHandleT(0)
-
- # Create and allocate the alarm filter
- if not notification_types or \
- saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM in notification_types:
- notification_filter = saNtf.SaNtfAlarmNotificationFilterT()
+ notification_types (list(SaNtfNotificationTypeT)): List of
+ notification types
- saNtfAlarmNotificationFilterAllocate(handle, notification_filter,
- 0, 0, 0, 0, 0, 0, 0)
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
- filter_handles.alarmFilterHandle = \
- notification_filter.notificationFilterHandle
-
- filters.append(notification_filter.notificationFilterHandle)
-
- # Create and allocate the object create delete filter
- if not notification_types or \
- saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE in \
- notification_types:
- notification_filter = \
- saNtf.SaNtfObjectCreateDeleteNotificationFilterT()
-
- saNtfObjectCreateDeleteNotificationFilterAllocate(handle,
- notification_filter,
- 0, 0, 0, 0, 0)
-
- filter_handles.objectCreateDeleteFilterHandle = \
- notification_filter.notificationFilterHandle
- filters.append(notification_filter.notificationFilterHandle)
-
- # Create and allocate the attribute change filter
- if not notification_types or \
- saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE in \
- notification_types:
-
- notification_filter = saNtf.SaNtfAttributeChangeNotificationFilterT()
-
- saNtfAttributeChangeNotificationFilterAllocate(handle,
- notification_filter,
- 0, 0, 0, 0, 0)
-
- filter_handles.attributeChangeFilterHandle = \
- notification_filter.notificationFilterHandle
-
- filters.append(notification_filter.notificationFilterHandle)
-
- # Create and allocate the state change filter
- if not notification_types or \
- saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE in \
- notification_types:
-
- notification_filter = saNtf.SaNtfStateChangeNotificationFilterT()
-
- saNtfStateChangeNotificationFilterAllocate(handle,
- notification_filter,
- 0, 0, 0, 0, 0, 0)
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
+ """
+ rc = _ntf_subscriber.subscribe(1, notification_types)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
- filter_handles.stateChangeFilterHandle = \
- notification_filter.notificationFilterHandle
+ return rc
- filters.append(notification_filter.notificationFilterHandle)
- # Create and allocate the security alarm filter
- if not notification_types or \
- saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM in \
- notification_types:
+@deprecate
+def get_producer_handle():
+ """ Get the NTF producer agent handle
- notification_filter = saNtf.SaNtfSecurityAlarmNotificationFilterT()
+ Returns:
+ SaNtfHandleT: NTF producer agent handle
+ """
+ return _ntf_producer.get_handle()
- saNtfSecurityAlarmNotificationFilterAllocate(handle,
- notification_filter,
- 0, 0, 0, 0, 0, 0, 0, 0, 0)
- filter_handles.securityAlarmFilterHandle = \
- notification_filter.notificationFilterHandle
+@deprecate
+def get_subscriber_handle():
+ """ Get the NTF subscriber agent handle
- filters.append(notification_filter.notificationFilterHandle)
+ Returns:
+ SaNtfHandleT: NTF subscriber agent handle
+ """
+ return _ntf_subscriber.get_handle()
- # Create a unique subscription id
- sub_id = saNtf.SaNtfSubscriptionIdT(1)
- # Start subscription
- saNtfNotificationSubscribe(filter_handles, sub_id)
+@deprecate
+def get_subscriber_selection_object():
+ """ Get the selection object associated with the subscriber agent handle
- # Free up the filters
- for filter_handle in filters:
- saNtfNotificationFilterFree(filter_handle)
+ Returns:
+ SaSelectionObjectT: The NTF subscriber selection object
+ """
+ return _ntf_subscriber.get_selection_object()
+@deprecate
def dispatch(flags=eSaDispatchFlagsT.SA_DISPATCH_ALL):
""" Invoke NTF callbacks for queued events. The default is to dispatch all
available events.
Args:
flags (eSaDispatchFlagsT): Flags specifying dispatch mode
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+
+ Raises:
+ SafException: If any NTF API call did not return SA_AIS_OK
"""
- saNtfDispatch(handle, flags)
+ rc = _ntf_subscriber.dispatch(flags)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ raise SafException(rc)
+
+ return rc
diff --git a/python/pyosaf/utils/ntf/agent.py b/python/pyosaf/utils/ntf/agent.py
new file mode 100644
index 0000000..dd2d218
--- /dev/null
+++ b/python/pyosaf/utils/ntf/agent.py
@@ -0,0 +1,500 @@
+############################################################################
+#
+# (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
+#
+############################################################################
+# pylint: disable=unused-argument,too-few-public-methods
+""" NTF utils common data structures and functions """
+from copy import deepcopy
+
+from pyosaf.saAis import saAis, SaVersionT, SaSelectionObjectT, eSaAisErrorT
+from pyosaf import saNtf
+from pyosaf.utils import decorate, initialize_decorate, log_err
+
+# Decorate pure saNtf* API's with error-handling retry and exception raising
+# Library Life Cycle API's
+saNtfInitialize = initialize_decorate(saNtf.saNtfInitialize)
+saNtfInitialize_2 = initialize_decorate(saNtf.saNtfInitialize_2)
+saNtfInitialize_3 = initialize_decorate(saNtf.saNtfInitialize_3)
+saNtfSelectionObjectGet = decorate(saNtf.saNtfSelectionObjectGet)
+saNtfDispatch = decorate(saNtf.saNtfDispatch)
+saNtfFinalize = decorate(saNtf.saNtfFinalize)
+# Producer API's
+saNtfObjectCreateDeleteNotificationAllocate = \
+ decorate(saNtf.saNtfObjectCreateDeleteNotificationAllocate)
+saNtfAttributeChangeNotificationAllocate = \
+ decorate(saNtf.saNtfAttributeChangeNotificationAllocate)
+saNtfStateChangeNotificationAllocate = \
+ decorate(saNtf.saNtfStateChangeNotificationAllocate)
+saNtfStateChangeNotificationAllocate_3 = \
+ decorate(saNtf.saNtfStateChangeNotificationAllocate_3)
+saNtfAlarmNotificationAllocate = decorate(saNtf.saNtfAlarmNotificationAllocate)
+saNtfSecurityAlarmNotificationAllocate = \
+ decorate(saNtf.saNtfSecurityAlarmNotificationAllocate)
+saNtfMiscellaneousNotificationAllocate = \
+ decorate(saNtf.saNtfMiscellaneousNotificationAllocate)
+saNtfPtrValAllocate = decorate(saNtf.saNtfPtrValAllocate)
+saNtfArrayValAllocate = decorate(saNtf.saNtfArrayValAllocate)
+saNtfIdentifierAllocate = decorate(saNtf.saNtfIdentifierAllocate)
+saNtfNotificationSend = decorate(saNtf.saNtfNotificationSend)
+saNtfNotificationSendWithId = decorate(saNtf.saNtfNotificationSendWithId)
+saNtfNotificationFree = decorate(saNtf.saNtfNotificationFree)
+saNtfVariableDataSizeGet = decorate(saNtf.saNtfVariableDataSizeGet)
+# Consumer API's
+saNtfLocalizedMessageGet = decorate(saNtf.saNtfLocalizedMessageGet)
+saNtfLocalizedMessageFree = decorate(saNtf.saNtfLocalizedMessageFree)
+saNtfLocalizedMessageFree_2 = decorate(saNtf.saNtfLocalizedMessageFree_2)
+saNtfPtrValGet = decorate(saNtf.saNtfPtrValGet)
+saNtfArrayValGet = decorate(saNtf.saNtfArrayValGet)
+saNtfObjectCreateDeleteNotificationFilterAllocate = \
+ decorate(saNtf.saNtfObjectCreateDeleteNotificationFilterAllocate)
+saNtfAttributeChangeNotificationFilterAllocate = \
+ decorate(saNtf.saNtfAttributeChangeNotificationFilterAllocate)
+saNtfStateChangeNotificationFilterAllocate = \
+ decorate(saNtf.saNtfStateChangeNotificationFilterAllocate)
+saNtfStateChangeNotificationFilterAllocate_2 = \
+ decorate(saNtf.saNtfStateChangeNotificationFilterAllocate_2)
+saNtfAlarmNotificationFilterAllocate = \
+ decorate(saNtf.saNtfAlarmNotificationFilterAllocate)
+saNtfSecurityAlarmNotificationFilterAllocate = \
+ decorate(saNtf.saNtfSecurityAlarmNotificationFilterAllocate)
+saNtfNotificationFilterFree = decorate(saNtf.saNtfNotificationFilterFree)
+# Subscriber API's
+saNtfNotificationSubscribe = decorate(saNtf.saNtfNotificationSubscribe)
+saNtfNotificationSubscribe_3 = decorate(saNtf.saNtfNotificationSubscribe_3)
+saNtfNotificationUnsubscribe = decorate(saNtf.saNtfNotificationUnsubscribe)
+saNtfNotificationUnsubscribe_2 = decorate(saNtf.saNtfNotificationUnsubscribe_2)
+# Reader API's
+saNtfNotificationReadInitialize = \
+ decorate(saNtf.saNtfNotificationReadInitialize)
+saNtfNotificationReadInitialize_2 = \
+ decorate(saNtf.saNtfNotificationReadInitialize_2)
+saNtfNotificationReadInitialize_3 = \
+ decorate(saNtf.saNtfNotificationReadInitialize_3)
+saNtfNotificationReadNext = decorate(saNtf.saNtfNotificationReadNext)
+saNtfNotificationReadNext_3 = decorate(saNtf.saNtfNotificationReadNext_3)
+saNtfNotificationReadFinalize = decorate(saNtf.saNtfNotificationReadFinalize)
+
+
+class NotificationInfo(object):
+ """ This class encapsulates data structures for use by each specific
+ notification type """
+ def __init__(self):
+ # Header info
+ self.event_type = 0
+ self.notification_object = ""
+ self.notifying_object = ""
+ self.ntf_class_id = saNtf.SaNtfClassIdT(0, 0, 0)
+ self.event_time = saAis.SA_TIME_UNKNOWN
+ self.notification_id = None
+ self.additional_text = ""
+ self.additional_info = []
+ # Object create/delete notification info
+ self.object_attributes = []
+ self.source_indicator = \
+ saNtf.eSaNtfSourceIndicatorT.SA_NTF_UNKNOWN_OPERATION
+ # Attribute change notification info
+ self.changed_attributes = []
+ # State change notification info
+ self.state_changes = []
+ # Alarm info
+ self.probable_cause = \
+ saNtf.eSaNtfProbableCauseT.SA_NTF_UNSPECIFIED_REASON
+ self.specific_problems = []
+ self.perceived_severity = saNtf.eSaNtfSeverityT.SA_NTF_SEVERITY_MINOR
+ self.trend = None
+ self.threshold_information = None
+ self.monitored_attrs = []
+ self.proposed_repair_actions = []
+ # Security alarm info
+ self.severity = saNtf.eSaNtfSeverityT.SA_NTF_SEVERITY_MINOR
+ self.security_alarm_detector = None
+ self.service_user = None
+ self.service_provider = None
+
+
+class NotificationFilterInfo(object):
+ """ This class encapsulates the notification filter data structure for use
+ by each specific notification type """
+ def __init__(self):
+ # Header info
+ self.obj_create_del_evt_list = []
+ self.attr_change_evt_list = []
+ self.state_change_evt_list = []
+ self.alarm_evt_list = []
+ self.sec_alarm_evt_list = []
+ self.notification_object_list = []
+ self.notifying_objects_list = []
+ self.ntf_class_id_list = []
+ # Filter info
+ self.source_indicator_list = []
+ self.changed_state_list = []
+ self.probable_cause_list = []
+ self.perceived_severity_list = []
+ self.trend_list = []
+ self.severity_list = []
+
+
+class AdditionalInfo(object):
+ """ This class contains a piece of additional information to be included
+ in a notification """
+ def __init__(self, info_id=None, info_type=None, info_value=None):
+ """ Constructor for AdditionalInfo class
+
+ Args:
+ info_id (SaNtfElementIdT): infoId field of SaNtfAdditionalInfoT
+ info_type (SaNtfValueTypeT): infoType field of SaNtfAdditionalInfoT
+ info_value (Any type of eSaNtfValueTypeT): infoValue field of
+ SaNtfAdditionalInfoT
+ """
+ self.info_id = info_id
+ self.info_type = info_type
+ self.info_value = info_value
+
+
+class StateChange(object):
+ """ This class contains information about a state change event """
+ def __init__(self, state_id=None, new_state=None, old_state_present=False,
+ old_state=None):
+ """ Constructor for StateChange class
+
+ Args:
+ state_id (SaNtfElementIdT): stateId field of SaNtfStateChangeT
+ new_state (int): newState field of SaNtfStateChangeT
+ old_state_present (bool): oldStatePresent field of
+ SaNtfStateChangeT
+ old_state (int): oldState field of SaNtfStateChangeT
+ """
+ self.state_id = state_id
+ self.new_state = new_state
+ self.old_state_present = old_state_present
+ self.old_state = old_state
+
+
+class AttributeChange(object):
+ """ This class contains information about an object's attribute change """
+ def __init__(self, attribute_id=None, attribute_type=None,
+ new_attribute_value=None, old_attribute_present=False,
+ old_attribute_value=None):
+ """ Constructor for AttributeChange class
+
+ Args:
+ attribute_id (SaNtfElementIdT): attributeId field of
+ SaNtfAttributeChangeT
+ attribute_type (SaNtfValueTypeT): attributeType field of
+ SaNtfAttributeChangeT
+ new_attribute_value (Any type of eSaNtfValueTypeT):
+ newAttributeValue field of SaNtfAttributeChangeT
+ old_attribute_present (bool): oldAttributePresent field of
+ SaNtfAttributeChangeT
+ old_attribute_value (Any type of eSaNtfValueTypeT):
+ oldAttributeValue field of SaNtfAttributeChangeT
+ """
+ self.attribute_id = attribute_id
+ self.attribute_type = attribute_type
+ self.new_attribute_value = new_attribute_value
+ self.old_attribute_present = old_attribute_present
+ self.old_attribute_value = old_attribute_value
+
+
+class Attribute(object):
+ """ This class contains information about an object's attribute """
+ def __init__(self, attribute_id=None, attribute_type=None,
+ attribute_value=None):
+ """ Constructor for Attribute class
+
+ Args:
+ attribute_id (SaNtfElementIdT): attributeId field of
+ SaNtfAttributeT
+ attribute_type (SaNtfValueTypeT): attributeType field of
+ SaNtfAttributeT
+ attribute_value (Any type of eSaNtfValueTypeT): attributeValue
+ field of SaNtfAttributeT
+ """
+ self.attribute_id = attribute_id
+ self.attribute_type = attribute_type
+ self.attribute_value = attribute_value
+
+
+class SecurityAlarmDetector(object):
+ """ This class contains information about a security alarm detector """
+ def __init__(self, value=None, value_type=None):
+ """ Constructor for SecurityAlarmDetector class
+
+ Args:
+ value (Any type of eSaNtfValueTypeT): valueType field of
+ SaNtfSecurityAlarmDetectorT
+ value_type (SaNtfValueTypeT): value field of
+ SaNtfSecurityAlarmDetectorT
+ """
+ self.value = value
+ self.value_type = value_type
+
+
+class ServiceUser(object):
+ """ This class contains information about a service user """
+ def __init__(self, value=None, value_type=None):
+ """ Constructor for ServiceUser class
+
+ Args:
+ value (Any type of eSaNtfValueTypeT): valueType field of
+ SaNtfServiceUserT
+ value_type (SaNtfValueTypeT): value field of SaNtfServiceUserT
+ """
+ self.value = value
+ self.value_type = value_type
+
+
+class ServiceProvider(ServiceUser):
+ """ This class contains information about a service provider """
+ pass
+
+
+class ThresholdInformation(object):
+ """ This class contains information about a threshold """
+ def __init__(self, threshold_id=None, threshold_value_type=None,
+ threshold_value=None, threshold_hysteresis=None,
+ observed_value=None, arm_time=None):
+ """ Constructor for ThresholdInformation class
+
+ Args:
+ threshold_id (SaNtfElementIdT): thresholdId field of
+ SaNtfThresholdInformationT
+ threshold_value_type (SaNtfValueTypeT): thresholdValueType field of
+ SaNtfThresholdInformationT
+ threshold_value (Any type of eSaNtfValueTypeT): thresholdValue
+ field of SaNtfThresholdInformationT
+ threshold_hysteresis (SaNtfValueTypeT): thresholdHysteresis
+ field of SaNtfThresholdInformationT
+ observed_value (Any type of eSaNtfValueTypeT): observedValue field
+ of SaNtfThresholdInformationT
+ arm_time (SaTimeT): armTime field of SaNtfThresholdInformationT
+ """
+ self.threshold_id = threshold_id
+ self.threshold_value_type = threshold_value_type
+ self.threshold_value = threshold_value
+ self.threshold_hysteresis = threshold_hysteresis
+ self.observed_value = observed_value
+ self.arm_time = arm_time
+
+
+class SpecificProblem(object):
+ """ This class contains information about a specific problem """
+ def __init__(self, problem_id=None, problem_class_id=None,
+ problem_type=None, problem_value=None):
+ """ Constructor for SpecificProblem class
+
+ Args:
+ problem_id (SaNtfElementIdT): problemId field of
+ SaNtfSpecificProblemT
+ problem_class_id (SaNtfClassIdT): problemClassId field of
+ SaNtfSpecificProblemT
+ problem_type (SaNtfValueTypeT): problemType field of
+ SaNtfSpecificProblemT
+ problem_value (Any type of eSaNtfValueTypeT): problemValue field of
+ SaNtfSpecificProblemT
+ """
+ self.problem_id = problem_id
+ self.problem_class_id = problem_class_id
+ self.problem_type = problem_type
+ self.problem_value = problem_value
+
+
+class ProposedRepairAction(object):
+ """ This class contains information about a proposed repair action """
+ def __init__(self, action_id=None, action_value_type=None,
+ action_value=None):
+ """ Constructor for ProposedRepairAction class
+
+ Args:
+ action_id (SaNtfElementIdT): actionId field of
+ SaNtfProposedRepairActionT
+ action_value_type (SaNtfValueTypeT): actionValueType field of
+ SaNtfProposedRepairActionT
+ action_value (Any type of eSaNtfValueTypeT): actionValue field of
+ SaNtfProposedRepairActionT
+ """
+ self.action_id = action_id
+ self.action_value_type = action_value_type
+ self.action_value = action_value
+
+
+class NtfAgent(object):
+ """ This class manages the life cycle of an NTF agent """
+
+ def __init__(self, version=None):
+ """ Constructor for NtfAgent class
+
+ Args:
+ version (SaVersionT): NTF API version
+ """
+ self.init_version = version if version is not None \
+ else SaVersionT('A', 1, 1)
+ self.version = None
+ self.handle = None
+ self.callbacks = None
+ self.sel_obj = SaSelectionObjectT()
+ self.ntf_notif_function = None
+ self.ntf_notif_discarded_function = None
+
+ def __enter__(self):
+ """ Enter method for NtfAgent class """
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ """ Exit method for NtfAgent class
+
+ Finalize the NTF agent handle
+ """
+ if self.handle is not None:
+ saNtfFinalize(self.handle)
+ self.handle = None
+
+ def __del__(self):
+ """ Destructor for NtfAgent class
+
+ Finalize the NTF agent handle
+ """
+ if self.handle is not None:
+ saNtf.saNtfFinalize(self.handle)
+ self.handle = None
+
+ def _ntf_notif_callback(self, c_subscription_id, c_notif):
+ """ This callback is invoked by NTF to deliver a notification to a
+ subscriber of that notification type.
+
+ Args:
+ c_subscription_id (SaNtfSubscriptionIdT): The subscription id
+ previously provided by the subscriber when subscribing for this
+ type of notification
+ c_notif (SaNtfNotificationsT): The notification delivered by this
+ callback
+ """
+ pass
+
+ def _ntf_notif_discarded_callback(self, c_subscription_id,
+ c_notification_type, c_number_discarded,
+ c_discarded_notification_identifiers):
+ """ This callback is invoked by NTF to notify a subscriber of a
+ particular notification type that one or more notifications of that
+ type have been discarded.
+
+ Args:
+ c_subscription_id (SaNtfSubscriptionIdT): The subscription id
+ previously provided by the subscriber when subscribing for
+ discarded notifications
+ c_notification_type (SaNtfNotificationTypeT): The notification type
+ of the discarded notifications
+ c_number_discarded (SaUint32T): The number of discarded
+ notifications
+ c_discarded_notification_identifiers (SaNtfIdentifierT): The list
+ of notification identifiers of the discarded notifications
+ """
+ pass
+
+ def initialize(self, ntf_notif_func=None, ntf_notif_discarded_func=None):
+ """ Initialize the NTF agent library
+
+ Args:
+ ntf_notif_func (callback): Callback function for subscribed
+ notifications
+ ntf_notif_discarded_func (callback): Callback function for
+ discarded notifications
+
+ Returns:
+ SaAisErrorT: Return code of the saNtfInitialize() API call
+ """
+ self.callbacks = None
+ # Set up callbacks if any
+ if ntf_notif_func is not None or ntf_notif_discarded_func is not None:
+ self.ntf_notif_function = ntf_notif_func
+ self.ntf_notif_discarded_function = ntf_notif_discarded_func
+
+ self.callbacks = saNtf.SaNtfCallbacksT()
+ self.callbacks.saNtfNotificationCallback = \
+ saNtf.SaNtfNotificationCallbackT(self._ntf_notif_callback)
+ self.callbacks.saNtfNotificationDiscardedCallback = \
+ saNtf.SaNtfNotificationDiscardedCallbackT(
+ self._ntf_notif_discarded_callback)
+
+ self.handle = saNtf.SaNtfHandleT()
+ self.version = deepcopy(self.init_version)
+ rc = saNtfInitialize(self.handle, self.callbacks, self.version)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfInitialize FAILED - %s" % eSaAisErrorT.whatis(rc))
+
+ return rc
+
+ def get_handle(self):
+ """ Return the NTF agent handle successfully initialized
+
+ Returns:
+ SaNtfHandleT: NTF agent handle
+ """
+ return self.handle
+
+ def _fetch_sel_obj(self):
+ """ Obtain a selection object (OS file descriptor)
+
+ Returns:
+ SaAisErrorT: Return code of the saNtfSelectionObjectGet() API call
+ """
+ rc = saNtfSelectionObjectGet(self.handle, self.sel_obj)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfSelectionObjectGet FAILED - %s" %
+ eSaAisErrorT.whatis(rc))
+
+ return rc
+
+ def get_selection_object(self):
+ """ Return the selection object associated with the NTF handle
+
+ Returns:
+ SaSelectionObjectT: Selection object associated with the NTF handle
+ """
+ return self.sel_obj
+
+ def dispatch(self, flags):
+ """ Invoke NTF callbacks for queued events
+
+ Args:
+ flags (eSaDispatchFlagsT): Flags specifying dispatch mode
+
+ Returns:
+ SaAisErrorT: Return code of the saNtfDispatch() API call
+ """
+ rc = saNtfDispatch(self.handle, flags)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfDispatch FAILED - %s" % eSaAisErrorT.whatis(rc))
+
+ return rc
+
+ def finalize(self):
+ """ Finalize the NTF agent handle
+
+ Returns:
+ SaAisErrorT: Return code of the saNtfFinalize() API call
+ """
+ rc = eSaAisErrorT.SA_AIS_OK
+ if self.handle:
+ rc = saNtfFinalize(self.handle)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfFinalize 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
diff --git a/python/pyosaf/utils/ntf/producer.py
b/python/pyosaf/utils/ntf/producer.py
new file mode 100644
index 0000000..cea5585
--- /dev/null
+++ b/python/pyosaf/utils/ntf/producer.py
@@ -0,0 +1,711 @@
+############################################################################
+#
+# (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
+#
+############################################################################
+# pylint: disable=too-many-public-methods
+""" NTF producer utilities """
+import ctypes
+
+from pyosaf import saNtf
+from pyosaf.saAis import eSaBoolT, eSaAisErrorT, SaVoidPtr
+from pyosaf.utils import log_warn, log_err, bad_handle_retry
+from pyosaf.utils.ntf import agent as ntf
+
+
+class NtfProducer(ntf.NtfAgent):
+ """ This class provides functions of the NTF Producer interface """
+
+ def __init__(self, version=None):
+ """ Constructor for NtfProducer class """
+ super(NtfProducer, self).__init__(version)
+ self.ntf_info = ntf.NotificationInfo()
+
+ def init(self):
+ """ Initialize the NTF agent
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ # This finalize() is needed for re-init case
+ self.finalize()
+ return self.initialize()
+
+ @staticmethod
+ def _assign_ntf_value(ntf_handle, attr_value, value, value_type):
+ """ Assign the correct sub-field in the given attribute
+
+ Args:
+ ntf_handle (SaNtfNotificationHandleT): Notification handle
+ attr_value (SaNtfValueT): Object attribute value in an object
+ creation or deletion notification
+ value (Any type of eSaNtfValueTypeT): Actual value of the object
+ attribute
+ value_type (SaNtfValueTypeT): Type of the object attribute value
+ """
+ if value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT8:
+ attr_value.uint8Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT8:
+ attr_value.int8Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT16:
+ attr_value.uint16Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT16:
+ attr_value.int16Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT32:
+ attr_value.uint32Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32:
+ attr_value.int32Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_FLOAT:
+ attr_value.floatVal = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT64:
+ attr_value.uint64Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT64:
+ attr_value.int64Val = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_DOUBLE:
+ attr_value.doubleVal = int(value)
+
+ elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_LDAP_NAME or \
+ value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_STRING or \
+ value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_IPADDRESS:
+ len_value = len(value)
+ dest_ptr = SaVoidPtr()
+ rc = ntf.saNtfPtrValAllocate(ntf_handle, len_value + 1, dest_ptr,
+ attr_value)
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ ctypes.memmove(dest_ptr, value, len_value + 1)
+ else:
+ log_warn("saNtfPtrValAllocate FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+
+ def set_event_type(self, event_type):
+ """ Fill in the eventType field in the notification header
+
+ Args:
+ event_type (SaNtfEventTypeT): Event type
+ """
+ self.ntf_info.event_type = event_type
+
+ def set_notification_object(self, notification_object):
+ """ Fill in the notificationObject field in the notification header
+
+ Args:
+ notification_object (str): Notification object's dn
+ """
+ self.ntf_info.notification_object = notification_object
+
+ def set_notifying_object(self, notifying_object):
+ """ Fill in the notifyingObject field in the notification header
+
+ Args:
+ notifying_object (str): Notifying object's dn
+ """
+ self.ntf_info.notifying_object = notifying_object
+
+ def set_class_id(self, notif_class_id):
+ """ Fill in the notificationClassId field in the notification header
+
+ Args:
+ notif_class_id (SaNtfClassIdT): Notification class id
+ """
+ self.ntf_info.ntf_class_id = notif_class_id
+
+ def set_event_time(self, event_time):
+ """ Fill in the eventTime field in the notification header
+
+ Args:
+ event_time (SaTimeT): Event time
+ """
+ self.ntf_info.event_time = event_time
+
+ def set_additional_text(self, additional_text):
+ """ Fill in the additionalText field in the notification header
+
+ Args:
+ additional_text (str): Additional text
+ """
+ self.ntf_info.additional_text = additional_text
+
+ def set_additional_info(self, additional_info):
+ """ Fill in the additionalInfo field in the notification header
+
+ Args:
+ additional_info (list(AdditionalInfo)): List of AdditionalInfo
+ structures
+ """
+ self.ntf_info.additional_info = additional_info
+
+ def set_source_indicator(self, source_indicator):
+ """ Fill in the sourceIndicator field in either object-create/delete
+ notification, attribute-change notification, or state-change
+ notification
+
+ Args:
+ source_indicator (SaNtfSourceIndicatorT): Source indicator of the
+ notification
+ """
+ self.ntf_info.source_indicator = source_indicator
+
+ def set_object_attributes(self, attributes):
+ """ Fill in the objectAttributes field in object-create/delete
+ notification
+
+ Args:
+ attributes (list(Attribute)): List of Attribute structures
+ """
+ self.ntf_info.object_attributes = attributes
+
+ def set_changed_attributes(self, changed_attributes):
+ """ Fill in the changedAttributes field in attribute-change
+ notification
+
+ Args:
+ changed_attributes(list(AttributeChange)): List of AttributeChange
+ structures
+ """
+ self.ntf_info.changed_attributes = changed_attributes
+
+ def set_state_changes(self, state_changes):
+ """ Fill in the changedStates field in state-change notification
+
+ Args:
+ state_changes (list(StateChange)): List of StateChange structures
+ """
+ self.ntf_info.state_changes = state_changes
+
+ def set_probable_cause(self, probable_cause):
+ """ Fill in the probableCause field in either alarm notification or
+ security-alarm notification
+
+ Args:
+ probable_cause (SaNtfProbableCauseT): Probable cause of the alarm
+ """
+ self.ntf_info.probable_cause = probable_cause
+
+ def set_specific_problems(self, specific_problems):
+ """ Fill in the specificProblems field in alarm notification
+
+ Args:
+ specific_problems (list(SpecificProblem)): List of SpecificProblem
+ structures
+ """
+ self.ntf_info.specific_problems = specific_problems
+
+ def set_perceived_severity(self, perceived_severity):
+ """ Fill in the perceivedSeverity field in alarm notification
+
+ Args:
+ perceived_severity (SaNtfSeverityT): Severity of the alarm
+ """
+ self.ntf_info.perceived_severity = perceived_severity
+
+ def set_trend(self, trend):
+ """ Fill in the trend field in alarm notification
+
+ Args:
+ trend (SaNtfSeverityTrendT): Trend of alarm severity
+ """
+ self.ntf_info.trend = trend
+
+ def set_threshold_information(self, threshold_information):
+ """ Fill in the thresholdInformation field in alarm notification
+
+ Args:
+ threshold_information (list(ThresholdInformation)): List of
+ ThresholdInformation structures
+ """
+ self.ntf_info.threshold_information = threshold_information
+
+ def set_monitored_attributes(self, monitored_attributes):
+ """ Fill in the monitoredAttributes field in alarm notification
+
+ Args:
+ monitored_attributes (list(Attribute)): List of monitored
+ Attribute structures
+ """
+ self.ntf_info.monitored_attrs = monitored_attributes
+
+ def set_proposed_repair_actions(self, proposed_repair_action):
+ """ Fill in the proposedRepairActions in alarm notification
+
+ Args:
+ proposed_repair_action (list(ProposedRepairAction)): List of
+ ProposedRepairAction structures
+ """
+ self.ntf_info.proposed_repair_actions = proposed_repair_action
+
+ def set_severity(self, severity):
+ """ Fill in the severity field in security alarm notification
+
+ Args:
+ severity (SaNtfSeverityT): Severity of the security alarm
+ """
+ self.ntf_info.severity = severity
+
+ def set_security_alarm_detector(self, security_alarm_detector):
+ """ Fill in the securityAlarmDetector field in security alarm
+ notification
+
+ Args:
+ security_alarm_detector (SecurityAlarmDetector):
+ A SecurityAlarmDetector structure
+ """
+ self.ntf_info.security_alarm_detector = security_alarm_detector
+
+ def set_service_user(self, service_user):
+ """ Fill in the serviceUser field in security alarm notification
+
+ Args:
+ service_user (ServiceUser): A ServiceUser structure
+ """
+ self.ntf_info.service_user = service_user
+
+ def set_service_provider(self, service_provider):
+ """ Fill in the serviceProvider field in security alarm notification
+
+ Args:
+ service_provider (ServiceProvider): A ServiceProvider structure
+ """
+ self.ntf_info.service_provider = service_provider
+
+ def clear_info(self):
+ """ Reset the NotificationInfo field values """
+ self.ntf_info = ntf.NotificationInfo()
+
+ def _fill_in_header(self, ntf_handle, header):
+ """ Fill in the given notification header with the provided information
+
+ Args:
+ ntf_handle (SaNtfNotificationHandleT): Notification handle
+ header (SaNtfNotificationHeaderT): Notification header
+ """
+ header.eventType.contents.value = self.ntf_info.event_type
+
+ header.notificationObject.contents.value = \
+ self.ntf_info.notification_object
+ header.notificationObject.contents.length = \
+ len(self.ntf_info.notification_object)
+
+ header.notifyingObject.contents.value = self.ntf_info.notifying_object
+ header.notifyingObject.contents.length = \
+ len(self.ntf_info.notifying_object)
+
+ header.notificationClassId.contents.vendorId = \
+ self.ntf_info.ntf_class_id.vendorId
+ header.notificationClassId.contents.majorId = \
+ self.ntf_info.ntf_class_id.majorId
+ header.notificationClassId.contents.minorId = \
+ self.ntf_info.ntf_class_id.minorId
+
+ header.eventTime.contents.value = self.ntf_info.event_time
+
+ header.lengthAdditionalText = len(self.ntf_info.additional_text)
+ ctypes.memmove(header.additionalText,
+ self.ntf_info.additional_text,
+ len(self.ntf_info.additional_text) + 1)
+
+ if self.ntf_info.additional_info:
+ for i, add_info in enumerate(self.ntf_info.additional_info):
+ header.additionalInfo[i].infoId = add_info.info_id
+ header.additionalInfo[i].infoType = add_info.info_type
+
+ self._assign_ntf_value(ntf_handle,
+ header.additionalInfo[i].infoValue,
+ add_info.info_value, add_info.info_type)
+
+ @bad_handle_retry
+ def send_object_create_delete_notification(self):
+ """ Send an SaNtfObjectCreateDeleteNotificationT notification
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ # Create the notification
+ notification = saNtf.SaNtfObjectCreateDeleteNotificationT()
+ rc = ntf.saNtfObjectCreateDeleteNotificationAllocate(
+ self.handle, notification, 0,
+ len(self.ntf_info.additional_text) + 1,
+ len(self.ntf_info.additional_info),
+ len(self.ntf_info.object_attributes),
+ saNtf.saNtf.SA_NTF_ALLOC_SYSTEM_LIMIT)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfObjectCreateDeleteNotificationAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ # Fill in the header
+ self._fill_in_header(notification.notificationHandle,
+ notification.notificationHeader)
+
+ # Fill in the notification
+ notification.sourceIndicator.contents.value = \
+ self.ntf_info.source_indicator
+
+ for i, attribute in enumerate(self.ntf_info.object_attributes):
+ ptr = notification.objectAttributes[i]
+
+ ptr.attributeId = attribute.attribute_id
+ ptr.attributeType = attribute.attribute_type
+
+ self._assign_ntf_value(notification.notificationHandle,
+ ptr.attributeValue,
+ attribute.attribute_value,
+ attribute.attribute_type)
+
+ # Send the notification
+ rc = ntf.saNtfNotificationSend(notification.notificationHandle)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfNotificationSend FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+ else:
+ self.clear_info()
+
+ # Free the notification
+ ntf.saNtfNotificationFree(notification.notificationHandle)
+
+ 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 function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
+
+ @bad_handle_retry
+ def send_attribute_change_notification(self):
+ """ Send an SaNtfAttributeChangeNotificationT notification
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ # Create the notification
+ notification = saNtf.SaNtfAttributeChangeNotificationT()
+
+ rc = ntf.saNtfAttributeChangeNotificationAllocate(
+ self.handle, notification, 0,
+ len(self.ntf_info.additional_text) + 1,
+ len(self.ntf_info.additional_info),
+ len(self.ntf_info.changed_attributes),
+ saNtf.saNtf.SA_NTF_ALLOC_SYSTEM_LIMIT)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfAttributeChangeNotificationAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ # Fill in the header
+ self._fill_in_header(notification.notificationHandle,
+ notification.notificationHeader)
+
+ # Fill in the notification
+ notification.sourceIndicator.contents.value = \
+ self.ntf_info.source_indicator
+
+ for i, changed_attr in enumerate(self.ntf_info.changed_attributes):
+ ptr = notification.changedAttributes[i]
+
+ ptr.attributeId = changed_attr.attribute_id
+ ptr.attributeType = changed_attr.attribute_type
+ self._assign_ntf_value(
+ notification.notificationHandle, ptr.newAttributeValue,
+ changed_attr.new_attribute_value,
+ changed_attr.attribute_type)
+
+ if changed_attr.old_attribute_present:
+ ptr.oldAttributePresent = eSaBoolT.SA_TRUE
+
+ self._assign_ntf_value(notification.notificationHandle,
+ ptr.oldAttributeValue,
+ changed_attr.old_attribute_value,
+ changed_attr.attribute_type)
+ else:
+ ptr.oldAttributePresent = eSaBoolT.SA_FALSE
+
+ # Send the notification
+ rc = ntf.saNtfNotificationSend(notification.notificationHandle)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfNotificationSend FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+
+ else:
+ self.clear_info()
+
+ # Free the notification
+ ntf.saNtfNotificationFree(notification.notificationHandle)
+
+ 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 function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
+
+ @bad_handle_retry
+ def send_state_change_notification(self):
+ """ Send an SaNtfStateChangeNotificationT notification
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ # Create the notification
+ notification = saNtf.SaNtfStateChangeNotificationT()
+
+ rc = ntf.saNtfStateChangeNotificationAllocate(
+ self.handle, notification, 0,
+ len(self.ntf_info.additional_text) + 1,
+ len(self.ntf_info.additional_info),
+ len(self.ntf_info.state_changes),
+ saNtf.saNtf.SA_NTF_ALLOC_SYSTEM_LIMIT)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfStateChangeNotificationAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ # Fill in the header
+ self._fill_in_header(notification.notificationHandle,
+ notification.notificationHeader)
+
+ # Fill in the notification
+ notification.sourceIndicator.contents.value = \
+ self.ntf_info.source_indicator
+
+ for i, state_change in enumerate(self.ntf_info.state_changes):
+ ptr = notification.changedStates[i]
+
+ ptr.stateId = state_change.state_id
+ ptr.newState = state_change.new_state
+
+ if state_change.old_state_present:
+ ptr.oldStatePresent = eSaBoolT.SA_TRUE
+ ptr.oldState = state_change.old_state
+ else:
+ ptr.oldStatePresent = eSaBoolT.SA_FALSE
+
+ # Send the notification
+ rc = ntf.saNtfNotificationSend(notification.notificationHandle)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfNotificationSend FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+ else:
+ self.clear_info()
+
+ # Free the notification
+ ntf.saNtfNotificationFree(notification.notificationHandle)
+
+ 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 function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
+
+ @bad_handle_retry
+ def send_alarm_notification(self):
+ """ Send an SaNtfAlarmNotificationT notification
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ # Create the notification
+ notification = saNtf.SaNtfAlarmNotificationT()
+ rc = ntf.saNtfAlarmNotificationAllocate(
+ self.handle, notification, 0,
+ len(self.ntf_info.additional_text) + 1,
+ len(self.ntf_info.additional_info),
+ len(self.ntf_info.specific_problems),
+ len(self.ntf_info.monitored_attrs),
+ len(self.ntf_info.proposed_repair_actions),
+ saNtf.saNtf.SA_NTF_ALLOC_SYSTEM_LIMIT)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfAlarmNotificationAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ # Fill in the header
+ self._fill_in_header(notification.notificationHandle,
+ notification.notificationHeader)
+
+ # Fill in the notification
+ notification.probableCause.contents.value = \
+ self.ntf_info.probable_cause
+
+ for i, problem in enumerate(self.ntf_info.specific_problems):
+ ptr = notification.specificProblems[i]
+ ptr.problemId = problem.problem_id
+ ptr.problemClassId.vendorId = problem.problem_class_id.vendorId
+ ptr.problemClassId.majorId = problem.problem_class_id.majorId
+ ptr.problemClassId.minorId = problem.problem_class_id.minorId
+ ptr.problemType = problem.problem_type
+ self._assign_ntf_value(
+ notification.notificationHandle, ptr.problemValue,
+ problem.problem_value, problem.problem_type)
+
+ notification.perceivedSeverity.contents.value = \
+ self.ntf_info.perceived_severity
+
+ if self.ntf_info.trend:
+ notification.trend.contents.value = self.ntf_info.trend
+
+ if self.ntf_info.threshold_information:
+ ptr = notification.thresholdInformation.contents
+ ptr.thresholdId = \
+ self.ntf_info.threshold_information.threshold_id
+ ptr.thresholdValueType = \
+ self.ntf_info.threshold_information.threshold_value_type
+
+ self._assign_ntf_value(
+ notification.notificationHandle, ptr.thresholdValue,
+ self.ntf_info.threshold_information.threshold_value,
+ ptr.thresholdValueType)
+ self._assign_ntf_value(
+ notification.notificationHandle, ptr.thresholdHysteresis,
+ self.ntf_info.threshold_information.threshold_hysteresis,
+ ptr.thresholdValueType)
+ self._assign_ntf_value(
+ notification.notificationHandle, ptr.observedValue,
+ self.ntf_info.threshold_information.observed_value,
+ ptr.thresholdValueType)
+ ptr.armTime = self.ntf_info.threshold_information.arm_time
+
+ notification.perceivedSeverity.contents.value = \
+ self.ntf_info.perceived_severity
+
+ for i, attribute in enumerate(self.ntf_info.monitored_attrs):
+ ptr = notification.monitoredAttributes[i]
+
+ ptr.attributeId = attribute.attribute_id
+ ptr.attributeType = attribute.attribute_type
+
+ self._assign_ntf_value(notification.notificationHandle,
+ ptr.attributeValue,
+ attribute.attribute_value,
+ attribute.attribute_type)
+
+ for i, action in enumerate(self.ntf_info.proposed_repair_actions):
+ ptr = notification.proposedRepairActions[i]
+ ptr.actionId = action.action_id
+ ptr.actionValueType = action.action_value_type
+ self._assign_ntf_value(notification.notificationHandle,
+ ptr.actionValue,
+ action.action_value,
+ action.action_value_type)
+
+ # Send the notification
+ rc = ntf.saNtfNotificationSend(notification.notificationHandle)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfNotificationSend FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+ else:
+ self.clear_info()
+
+ # Free the notification
+ ntf.saNtfNotificationFree(notification.notificationHandle)
+
+ 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 function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
+
+ @bad_handle_retry
+ def send_security_alarm_notification(self):
+ """ Send an SaNtfSecurityAlarmNotificationT notification
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ notification = saNtf.SaNtfSecurityAlarmNotificationT()
+ rc = ntf.saNtfSecurityAlarmNotificationAllocate(
+ self.handle, notification, 0,
+ len(self.ntf_info.additional_text) + 1,
+ len(self.ntf_info.additional_info),
+ saNtf.saNtf.SA_NTF_ALLOC_SYSTEM_LIMIT)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfSecurityAlarmNotificationAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ # Fill in the header
+ self._fill_in_header(notification.notificationHandle,
+ notification.notificationHeader)
+
+ # Fill in security alarm-specific fields
+ notification.probableCause.contents.value = \
+ self.ntf_info.probable_cause
+ notification.severity.contents.value = self.ntf_info.severity
+
+ if self.ntf_info.security_alarm_detector:
+ notification.securityAlarmDetector.contents.valueType = \
+ self.ntf_info.security_alarm_detector.value_type
+ self._assign_ntf_value(
+ notification.notificationHandle,
+ notification.securityAlarmDetector.contents.value,
+ self.ntf_info.security_alarm_detector.value,
+ self.ntf_info.security_alarm_detector.value_type)
+
+ if self.ntf_info.service_user:
+ notification.serviceUser.contents.valueType = \
+ self.ntf_info.service_user.value_type
+ self._assign_ntf_value(notification.notificationHandle,
+ notification.serviceUser.contents.value,
+ self.ntf_info.service_user.value,
+ self.ntf_info.service_user.value_type)
+ if self.ntf_info.service_provider:
+ notification.serviceProvider.contents.valueType = \
+ self.ntf_info.service_provider.value_type
+ self._assign_ntf_value(
+ notification.notificationHandle,
+ notification.serviceProvider.contents.value,
+ self.ntf_info.service_provider.value,
+ self.ntf_info.service_provider.value_type)
+
+ # Send the notification
+ rc = ntf.saNtfNotificationSend(notification.notificationHandle)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfNotificationSend FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+ else:
+ self.clear_info()
+
+ # Free the notification
+ ntf.saNtfNotificationFree(notification.notificationHandle)
+
+ 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 function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
diff --git a/python/pyosaf/utils/ntf/reader.py
b/python/pyosaf/utils/ntf/reader.py
new file mode 100644
index 0000000..560ecd8
--- /dev/null
+++ b/python/pyosaf/utils/ntf/reader.py
@@ -0,0 +1,187 @@
+############################################################################
+#
+# (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
+#
+############################################################################
+""" NTF reader utilities """
+from collections import Iterator
+from pyosaf import saNtf
+from pyosaf.saAis import eSaAisErrorT
+from pyosaf.utils import log_err, bad_handle_retry
+from pyosaf.utils.ntf import agent as ntf
+from pyosaf.utils.ntf.subscriber import NtfConsumer
+
+
+class NtfReader(NtfConsumer, Iterator):
+ """ This class provides functions of the NTF Reader interface """
+
+ def __init__(self, version=None):
+ """ Constructor for NtfReader class """
+ super(NtfReader, self).__init__(version)
+ self.read_handle = None
+ self.filter_handles = \
+ saNtf.SaNtfNotificationTypeFilterHandlesT(0, 0, 0, 0, 0)
+ self.search_direction = \
+ saNtf.eSaNtfSearchDirectionT.SA_NTF_SEARCH_OLDER
+ self.search_criteria = saNtf.SaNtfSearchCriteriaT(
+ saNtf.eSaNtfSearchModeT.SA_NTF_SEARCH_ONLY_FILTER, 0, 0)
+
+ def __enter__(self):
+ """ Enter method for NtfReader class """
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ """ Exit method for NtfReader class
+
+ Finalize the NTF agent handle and clean up any allocated resources
+ """
+ if self.read_handle is not None:
+ ntf.saNtfNotificationReadFinalize(self.read_handle)
+ self.read_handle = None
+ if self.handle is not None:
+ ntf.saNtfFinalize(self.handle)
+ self.handle = None
+
+ def __del__(self):
+ """ Destructor for NtfReader class
+
+ Finalize the NTF agent handle and clean up any allocated resources
+ """
+ if self.read_handle is not None:
+ saNtf.saNtfNotificationReadFinalize(self.read_handle)
+ self.read_handle = None
+ if self.handle is not None:
+ saNtf.saNtfFinalize(self.handle)
+ self.handle = None
+
+ def __iter__(self):
+ """ Iterator for NtfReader class """
+ return self
+
+ def next(self):
+ """ Override next() method of Iterator class """
+ return self.__next__()
+
+ def __next__(self):
+ """ Return the next element of the class iterator """
+ notification = saNtf.SaNtfNotificationsT()
+ rc = ntf.saNtfNotificationReadNext(self.read_handle,
+ self.search_direction,
+ notification)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ if rc != eSaAisErrorT.SA_AIS_ERR_NOT_EXIST:
+ log_err("saNtfNotificationReadNext FAILED - %s" %
+ eSaAisErrorT.whatis(rc))
+ raise StopIteration
+
+ return self._parse_notification(notification)
+
+ def init(self):
+ """ Initialize the NTF agent
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ self.finalize()
+ return self.initialize()
+
+ def _parse_notification(self, notification):
+ """ Parse the read-out notification to retrieve its information
+
+ Args:
+ notification (SaNtfNotificationsT): Notification to parse
+
+ Returns:
+ SaNtfNotificationTypeT: Notification type
+ NotificationInfo: A NotificationInfo structure containing
+ information of the parsed notification
+ """
+ _ntf_type = notification.notificationType
+ if _ntf_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+ notification = notification.notification.alarmNotification
+ _ntf_info = self._parse_notification_header(
+ notification.notificationHandle,
+ notification.notificationHeader)
+ self._parse_alarm_ntf(notification, _ntf_info)
+ else:
+ notification = notification.notification.securityAlarmNotification
+ _ntf_info = self._parse_notification_header(
+ notification.notificationHandle,
+ notification.notificationHeader)
+ self._parse_security_alarm_ntf(notification, _ntf_info)
+
+ return _ntf_type, _ntf_info
+
+ def set_search_criteria(self, search_criteria):
+ """ Set the notification search criteria
+
+ Args:
+ search_criteria (SaNtfSearchCriteriaT): Search criteria
+ """
+ self.search_criteria = search_criteria
+
+ @bad_handle_retry
+ def read(self, notification_types=None):
+ """ Start reading NTF notifications with the types specified in the
+ notification_types list. If the list is not provided, all types of
+ notification are read by default.
+
+ Current NTF implementation of this function only supports read filters
+ for alarm and security alarm notification types.
+
+ NOTE: Users have to set the wanted filters criteria via the set of
+ set_filter_*() methods before calling this method. Otherwise, the
+ filters criteria will be set with default values.
+
+ Args:
+ notification_types (list(SaNtfNotificationTypeT)): List of
+ notification types
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ alarm_type = saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM
+ security_alarm_type = \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM
+
+ # Filters for notification types other than SA_NTF_TYPE_ALARM and
+ # SA_NTF_TYPE_SECURITY_ALARM are not supported
+ if notification_types is not None:
+ if alarm_type not in notification_types \
+ and security_alarm_type not in notification_types:
+ return eSaAisErrorT.SA_AIS_ERR_NOT_SUPPORTED
+
+ # Generate the alarm notification filter
+ if notification_types is None or alarm_type in notification_types:
+ self._generate_alarm_filter()
+
+ # Generate the security alarm notification filter
+ if notification_types is None \
+ or security_alarm_type in notification_types:
+ self._generate_security_alarm_filter()
+
+ self.read_handle = saNtf.SaNtfReadHandleT()
+ rc = ntf.saNtfNotificationReadInitialize(self.search_criteria,
+ self.filter_handles,
+ self.read_handle)
+ 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 function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
diff --git a/python/pyosaf/utils/ntf/subscriber.py
b/python/pyosaf/utils/ntf/subscriber.py
new file mode 100644
index 0000000..5eea9da
--- /dev/null
+++ b/python/pyosaf/utils/ntf/subscriber.py
@@ -0,0 +1,923 @@
+############################################################################
+#
+# (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
+#
+############################################################################
+# pylint: disable=unused-argument
+""" NTF subscriber utilities """
+from __future__ import print_function
+import ctypes
+from copy import deepcopy
+
+from pyosaf import saNtf
+from pyosaf.saAis import BYREF, eSaAisErrorT, SaVoidPtr, SaNameT, SaUint16T, \
+ SaStringT
+from pyosaf.utils import bad_handle_retry, log_err, log_warn
+from pyosaf.utils.ntf import agent as ntf
+
+STRING_TYPES = [saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_STRING,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_LDAP_NAME,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_IPADDRESS]
+INT_TYPES = [saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT8,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT8,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT16,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT16,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT32,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_FLOAT,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT64,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT64,
+ saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_DOUBLE]
+
+
+class NtfConsumer(ntf.NtfAgent):
+ """ This class provides functions of the NTF Consumer interface """
+ def __init__(self, version=None):
+ """ Constructor for NtfConsumer class """
+ super(NtfConsumer, self).__init__(version)
+ self.filter_info = ntf.NotificationFilterInfo()
+ self.filter_handles = None
+
+ def __enter__(self):
+ """ Enter method for NtfConsumer class """
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ """ Exit method for NtfConsumer class
+
+ Finalize the NTF agent handle
+ """
+ if self.handle is not None:
+ ntf.saNtfFinalize(self.handle)
+ self.handle = None
+
+ def __del__(self):
+ """ Destructor for NtfConsumer class
+
+ Finalize the NTF agent handle
+ """
+ if self.handle is not None:
+ saNtf.saNtfFinalize(self.handle)
+ self.handle = None
+
+ def set_filter_event_types(self, event_type_list):
+ """ Set data for the eventTypes field in the notification filter header
+ of all notification types
+
+ Args:
+ event_type_list (list(SaNtfEventTypeT)): List of notification event
+ types
+ """
+ for event_type in event_type_list:
+ if event_type <= saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_DELETION:
+ self.filter_info.obj_create_del_evt_list.append(event_type)
+ elif event_type <= saNtf.eSaNtfEventTypeT.SA_NTF_ATTRIBUTE_RESET:
+ self.filter_info.attr_change_evt_list.append(event_type)
+ elif event_type <= \
+ saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_STATE_CHANGE:
+ self.filter_info.state_change_evt_list.append(event_type)
+ elif event_type <= saNtf.eSaNtfEventTypeT.SA_NTF_ALARM_ENVIRONMENT:
+ self.filter_info.alarm_evt_list.append(event_type)
+ elif event_type <= saNtf.eSaNtfEventTypeT.SA_NTF_TIME_VIOLATION:
+ self.filter_info.sec_alarm_evt_list.append(event_type)
+
+ def set_filter_notification_objects(self, notification_object_list):
+ """ Set data for the notificationObjects field in the notification
+ filter header of all notification types
+
+ Args:
+ notification_object_list (list(str)): List of notification
+ objects' dns
+ """
+ self.filter_info.notification_object_list = notification_object_list
+
+ def set_filter_notifying_objects(self, notifying_objects_list):
+ """ Set data for the notifyingObjects field in the notification filter
+ header of all notification types
+
+ Args:
+ notifying_objects_list (list(str)): List of notifying objects' dns
+ """
+ self.filter_info.notifying_objects_list = notifying_objects_list
+
+ def set_filter_ntf_class_ids(self, ntf_class_id_list):
+ """ Set data for the notificationClassIds field in the notification
+ filter header of all notification types
+
+ Args:
+ ntf_class_id_list (list(SaNtfClassIdT)): List of notification
+ class ids
+ """
+ self.filter_info.ntf_class_id_list = ntf_class_id_list
+
+ def set_filter_source_indicators(self, source_indicators):
+ """ Set data for the sourceIndicators field in the notification filter
+ header of either one of object-create/delete, attribute-change,
+ state-change notification types
+
+ Args:
+ source_indicators (list(SaNtfSourceIndicatorT)): List of
+ notification source indicators
+ """
+ self.filter_info.source_indicator_list = source_indicators
+
+ def set_filter_changed_states(self, changed_states):
+ """ Set data for the changedStates field in the notification filter
+ header of state-change notification type
+
+ Args:
+ changed_states (list(StateChange)): List of StateChange structures
+ """
+ self.filter_info.changed_state_list = changed_states
+
+ def set_filter_probable_causes(self, probable_causes):
+ """ Set data for the probableCauses field in the notification filter
+ header of either of alarm or security alarm notification types
+
+ Args:
+ probable_causes (list(SaNtfProbableCauseT)): List of alarm probable
+ causes
+ """
+ self.filter_info.probable_cause_list = probable_causes
+
+ def set_filter_perceived_severities(self, perceived_severities):
+ """ Set data for the perceivedSeverities field in the notification
+ filter header of alarm notification type
+
+ Args:
+ perceived_severities (list(SaNtfSeverityT)): List of alarm
+ severities
+ """
+ self.filter_info.probable_cause_list = perceived_severities
+
+ def set_filter_trends(self, trends):
+ """ Set data for the trends field in the notification filter header of
+ alarm notification type
+
+ Args:
+ trends (list(SaNtfSeverityTrendT)): List of alarm severity trends
+ """
+ self.filter_info.trend_list = trends
+
+ def set_filter_severities(self, severities):
+ """ Set data for the severities field in the notification filter header
+ of security alarm notification type
+
+ Args:
+ severities (list(SaNtfSeverityT)): List of security alarm
+ severities
+ """
+ self.filter_info.severity_list = severities
+
+ def clear_filter_info(self):
+ """ Reset the NotificationInfo filter field values """
+ self.filter_info = ntf.NotificationFilterInfo()
+
+ def _fill_in_filter_header(self, filter_header):
+ """ Fill in the given notification filter header with user-provided
+ data """
+ for i, info in enumerate(self.filter_info.notification_object_list):
+ filter_header.notificationObjects[i] = SaNameT(info)
+ for i, info in enumerate(self.filter_info.notifying_objects_list):
+ filter_header.notifyingObjects[i] = SaNameT(info)
+ for i, info in enumerate(self.filter_info.ntf_class_id_list):
+ filter_header.notificationClassIds[i] = info
+
+ def _generate_object_create_delete_filter(self):
+ """ Allocate memory for the object-create/delete notification filter
+ and fill in the corresponding user-provided data
+
+ Returns:
+ SaAisErrorT: Return code of the
+ saNtfObjectCreateDeleteNotificationFilterAllocate() API call
+ """
+ notification_filter = \
+ saNtf.SaNtfObjectCreateDeleteNotificationFilterT()
+
+ rc = ntf.saNtfObjectCreateDeleteNotificationFilterAllocate(
+ self.handle, notification_filter,
+ len(self.filter_info.obj_create_del_evt_list),
+ len(self.filter_info.notification_object_list),
+ len(self.filter_info.notifying_objects_list),
+ len(self.filter_info.ntf_class_id_list),
+ len(self.filter_info.source_indicator_list))
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfObjectCreateDeleteNotificationFilterAllocate"
+ " FAILED, rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ self.filter_handles.objectCreateDeleteFilterHandle = \
+ notification_filter.notificationFilterHandle
+
+ self._fill_in_filter_header(
+ notification_filter.notificationFilterHeader)
+
+ # Fill in the eventTypes array with user-provided data
+ for i, evt in enumerate(self.filter_info.obj_create_del_evt_list):
+ notification_filter.notificationFilterHeader.eventTypes[i] = \
+ evt
+
+ # Fill in the sourceIndicators array with user-provided data
+ for i, source_indicator in \
+ enumerate(self.filter_info.source_indicator_list):
+ notification_filter.sourceIndicators[i] = source_indicator
+
+ return rc
+
+ def _generate_attribute_change_filter(self):
+ """ Allocate memory for the attribute change notification filter and
+ fill in the corresponding user-provided data
+
+ Returns:
+ SaAisErrorT: Return code of the
+ saNtfAttributeChangeNotificationFilterAllocate() API call
+ """
+ notification_filter = saNtf.SaNtfAttributeChangeNotificationFilterT()
+
+ rc = ntf.saNtfAttributeChangeNotificationFilterAllocate(
+ self.handle, notification_filter,
+ len(self.filter_info.attr_change_evt_list),
+ len(self.filter_info.notification_object_list),
+ len(self.filter_info.notifying_objects_list),
+ len(self.filter_info.ntf_class_id_list),
+ len(self.filter_info.source_indicator_list))
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfAttributeChangeNotificationFilterAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ self.filter_handles.attributeChangeFilterHandle = \
+ notification_filter.notificationFilterHandle
+
+ self._fill_in_filter_header(
+ notification_filter.notificationFilterHeader)
+
+ # Fill in the eventTypes array with user-provided data
+ for i, evt in enumerate(self.filter_info.attr_change_evt_list):
+ notification_filter.notificationFilterHeader.eventTypes[i] = \
+ evt
+
+ # Fill in the sourceIndicators array with user-provided data
+ for i, source_indicator in \
+ enumerate(self.filter_info.source_indicator_list):
+ notification_filter.sourceIndicators[i] = source_indicator
+
+ return rc
+
+ def _generate_state_change_filter(self):
+ """ Allocate memory for the state change notification filter and fill
+ in the corresponding user-provided data
+
+ Returns:
+ SaAisErrorT: Return code of the
+ saNtfStateChangeNotificationFilterAllocate() API call
+ """
+ notification_filter = saNtf.SaNtfStateChangeNotificationFilterT()
+
+ rc = ntf.saNtfStateChangeNotificationFilterAllocate(
+ self.handle, notification_filter,
+ len(self.filter_info.state_change_evt_list),
+ len(self.filter_info.notification_object_list),
+ len(self.filter_info.notifying_objects_list),
+ len(self.filter_info.ntf_class_id_list),
+ len(self.filter_info.source_indicator_list),
+ len(self.filter_info.changed_state_list))
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfStateChangeNotificationFilterAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ self.filter_handles.stateChangeFilterHandle = \
+ notification_filter.notificationFilterHandle
+
+ self._fill_in_filter_header(
+ notification_filter.notificationFilterHeader)
+
+ # Fill in the eventTypes array with user-provided data
+ for i, evt in enumerate(self.filter_info.state_change_evt_list):
+ notification_filter.notificationFilterHeader.eventTypes[i] = \
+ evt
+
+ # Fill in the sourceIndicators array with user-provided data
+ for i, source_indicator in \
+ enumerate(self.filter_info.source_indicator_list):
+ notification_filter.sourceIndicators[i] = source_indicator
+
+ # Fill in the changedStates array with user-provided data
+ for i, state_change in \
+ enumerate(self.filter_info.changed_state_list):
+ notification_filter.changedStates[i].stateId = \
+ state_change.state_id
+ notification_filter.changedStates[i].newState = \
+ state_change.new_state
+ notification_filter.changedStates[i].oldStatePresent = \
+ state_change.old_state_present
+ if notification_filter.changedStates[i].oldStatePresent:
+ notification_filter.changedStates[i].oldState = \
+ state_change.old_state
+
+ return rc
+
+ def _generate_alarm_filter(self):
+ """ Allocate memory for the alarm notification filter and fill in the
+ corresponding user-provided data
+
+ Returns:
+ SaAisErrorT: Return code of the
+ saNtfAlarmNotificationFilterAllocate() API call
+ """
+ notification_filter = saNtf.SaNtfAlarmNotificationFilterT()
+
+ rc = ntf.saNtfAlarmNotificationFilterAllocate(
+ self.handle, notification_filter,
+ len(self.filter_info.alarm_evt_list),
+ len(self.filter_info.notification_object_list),
+ len(self.filter_info.notifying_objects_list),
+ len(self.filter_info.ntf_class_id_list),
+ len(self.filter_info.probable_cause_list),
+ len(self.filter_info.perceived_severity_list),
+ len(self.filter_info.trend_list))
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfAlarmNotificationFilterAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ self.filter_handles.alarmFilterHandle = \
+ notification_filter.notificationFilterHandle
+
+ self._fill_in_filter_header(
+ notification_filter.notificationFilterHeader)
+
+ # Fill in the eventTypes array with user-provided data
+ for i, evt in enumerate(self.filter_info.alarm_evt_list):
+ notification_filter.notificationFilterHeader.eventTypes[i] = \
+ evt
+
+ # Fill in the probableCauses array with user-provided data
+ for i, probable_cause in \
+ enumerate(self.filter_info.probable_cause_list):
+ notification_filter.probableCauses[i] = probable_cause
+
+ # Fill in the perceivedSeverities array with user-provided data
+ for i, perceived_severity in \
+ enumerate(self.filter_info.perceived_severity_list):
+ notification_filter.perceivedSeverities[i] = perceived_severity
+
+ # Fill in the trends array with user-provided data
+ for i, trend in enumerate(self.filter_info.trend_list):
+ notification_filter.trends[i] = trend
+
+ return rc
+
+ def _generate_security_alarm_filter(self):
+ """ Allocate memory for the security alarm notification filter and fill
+ in the corresponding user-provided data
+
+ Returns:
+ SaAisErrorT: Return code of the
+ saNtfSecurityAlarmNotificationFilterAllocate() API call
+ """
+ notification_filter = saNtf.SaNtfSecurityAlarmNotificationFilterT()
+
+ rc = ntf.saNtfSecurityAlarmNotificationFilterAllocate(
+ self.handle, notification_filter,
+ len(self.filter_info.sec_alarm_evt_list),
+ len(self.filter_info.notification_object_list),
+ len(self.filter_info.notifying_objects_list),
+ len(self.filter_info.ntf_class_id_list),
+ len(self.filter_info.probable_cause_list),
+ len(self.filter_info.severity_list), 0, 0, 0)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfAlarmNotificationFilterAllocate FAILED, "
+ "rc = %s" % eSaAisErrorT.whatis(rc))
+ else:
+ self.filter_handles.securityAlarmFilterHandle = \
+ notification_filter.notificationFilterHandle
+
+ self._fill_in_filter_header(
+ notification_filter.notificationFilterHeader)
+
+ # Fill in the eventTypes array with user-provided data
+ for i, evt in enumerate(self.filter_info.sec_alarm_evt_list):
+ notification_filter.notificationFilterHeader.eventTypes[i] = \
+ evt
+
+ # Fill in the probableCauses array with user-provided data
+ for i, probable_cause in \
+ enumerate(self.filter_info.probable_cause_list):
+ notification_filter.probableCauses[i] = probable_cause
+
+ # Fill in the severities array with user-provided data
+ for i, severity in enumerate(self.filter_info.severity_list):
+ notification_filter.severities[i] = severity
+
+ return rc
+
+ def _free_notification_filters(self):
+ """ Free the memory previously allocated for a notification filter """
+ if self.filter_handles.objectCreateDeleteFilterHandle:
+ ntf.saNtfNotificationFilterFree(
+ self.filter_handles.objectCreateDeleteFilterHandle)
+ if self.filter_handles.attributeChangeFilterHandle:
+ ntf.saNtfNotificationFilterFree(
+ self.filter_handles.attributeChangeFilterHandle)
+ if self.filter_handles.stateChangeFilterHandle:
+ ntf.saNtfNotificationFilterFree(
+ self.filter_handles.stateChangeFilterHandle)
+ if self.filter_handles.alarmFilterHandle:
+ ntf.saNtfNotificationFilterFree(
+ self.filter_handles.alarmFilterHandle)
+ if self.filter_handles.securityAlarmFilterHandle:
+ ntf.saNtfNotificationFilterFree(
+ self.filter_handles.securityAlarmFilterHandle)
+
+ @staticmethod
+ def _get_ptr_value(ntf_handle, value):
+ """ Get the correct string value from the given 'value' field in the
+ received notification
+
+ Args:
+ ntf_handle (SaNtfNotificationHandleT): A handle to the internal
+ notification structure
+ value (SaNtfValueT): A 'value' field in the notification structure
+
+ Returns:
+ SaStringT: The value in string format
+ """
+ data_ptr = SaVoidPtr()
+ data_size = SaUint16T()
+ rc = ntf.saNtfPtrValGet(ntf_handle, value, data_ptr, data_size)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_warn("saNtfPtrValGet FAILED - %s" % (eSaAisErrorT.whatis(rc)))
+ return ctypes.cast(data_ptr, SaStringT).value
+
+ def _get_ntf_value(self, ntf_handle, value, value_type):
+ """ Get the correct typed value from a specific 'value' field in the
+ received notification
+
+ Args:
+ ntf_handle (SaNtfNotificationHandleT): A handle to the internal
+ notification structure
+ value (SaNtfValueT): A 'value' field in the notification structure
+ value_type (SaNtfValueTypeT): Value type
+
+ Returns:
+ typed_value: Value of a specific type
+ """
+ if value_type in STRING_TYPES:
+ return self._get_ptr_value(ntf_handle, value)
+ elif value_type in INT_TYPES:
+ return saNtf.unmarshalSaNtfValue(BYREF(value), value_type)
+
+ return "This value type is currently not supported"
+
+ def _parse_notification_header(self, ntf_handle, ntf_header):
+ """ Parse the notification header in the received notification to
+ retrieve information
+
+ Args:
+ ntf_handle (SaNtfNotificationHandleT): A handle to the internal
+ notification structure
+ ntf_header (SaNtfNotificationHeaderT): Notification header
+ structure in the received notification
+
+ Returns:
+ NotificationInfo: A NotificationInfo structure containing
+ information from the notification header
+ """
+ ntf_info = ntf.NotificationInfo()
+ ntf_info.event_type = ntf_header.eventType.contents.value
+ ntf_info.notification_object = \
+ ntf_header.notificationObject.contents.value
+ ntf_info.notifying_object = \
+ ntf_header.notifyingObject.contents.value
+ ntf_info.ntf_class_id = \
+ ntf_header.notificationClassId.contents
+ ntf_info.event_time = ntf_header.eventTime.contents.value
+ ntf_info.notification_id = \
+ ntf_header.notificationId.contents.value
+ ntf_info.additional_text = \
+ ntf_header.additionalText[0:ntf_header.lengthAdditionalText]
+
+ for i in range(ntf_header.numAdditionalInfo):
+ c_add_info = ntf_header.additionalInfo[i]
+ add_info = ntf.AdditionalInfo()
+ add_info.info_id = c_add_info.infoId
+ add_info.info_type = c_add_info.infoType
+ add_info.info_value = self._get_ntf_value(ntf_handle,
+ c_add_info.infoValue,
+ c_add_info.infoType)
+ ntf_info.additional_info.append(add_info)
+
+ return ntf_info
+
+ def _parse_object_create_delete_ntf(self, c_ntf, ntf_info):
+ """ Parse the received object-create/delete notification to retrieve
+ its information
+
+ Args:
+ c_ntf (SaNtfObjectCreateDeleteNotificationT): Object-create/delete
+ notification structure
+ ntf_info (NotificationInfo): NotificationInfo structure with
+ information from the notification
+ """
+ ntf_handle = c_ntf.notificationHandle
+ ntf_info.source_indicator = \
+ c_ntf.sourceIndicator.contents.value
+ for i in range(c_ntf.numAttributes):
+ c_attr = c_ntf.objectAttributes[i]
+ attr = ntf.Attribute()
+ attr.attribute_id = c_attr.attributeId
+ attr.attribute_type = c_attr.attributeType
+ attr.attribute_value = \
+ self._get_ntf_value(ntf_handle, c_attr.attributeValue,
+ c_attr.attributeType)
+ ntf_info.object_attributes.append(attr)
+
+ def _parse_attribute_change_ntf(self, c_ntf, ntf_info):
+ """ Parse the received attribute-change notification to retrieve its
+ information
+
+ Args:
+ c_ntf (SaNtfAttributeChangeNotificationT): Attribute-change
+ notification structure
+ ntf_info (NotificationInfo): NotificationInfo structure with
+ information from the notification
+ """
+ ntf_handle = c_ntf.notificationHandle
+ ntf_info.source_indicator = \
+ c_ntf.sourceIndicator.contents.value
+ for i in range(c_ntf.numAttributes):
+ c_attr = c_ntf.changedAttributes[i]
+ attr = ntf.AttributeChange()
+ attr.attribute_id = c_attr.attributeId
+ attr.attribute_type = c_attr.attributeType
+ attr.new_attribute_value = \
+ self._get_ntf_value(ntf_handle, c_attr.newAttributeValue,
+ c_attr.attributeType)
+ attr.old_attribute_present = c_attr.oldAttributePresent
+ if c_attr.oldAttributePresent:
+ attr.old_attribute_value = \
+ self._get_ntf_value(ntf_handle, c_attr.oldAttributeValue,
+ c_attr.attributeType)
+ ntf_info.changed_attributes.append(attr)
+
+ @staticmethod
+ def _parse_state_change_ntf(c_ntf, ntf_info):
+ """ Parse the received state-change notification to retrieve its
+ information
+
+ Args:
+ c_ntf (SaNtfStateChangeNotificationT): State-change notification
+ structure
+ ntf_info (NotificationInfo): NotificationInfo structure with
+ information from the notification
+ """
+ ntf_info.source_indicator = \
+ c_ntf.sourceIndicator.contents.value
+ for i in range(c_ntf.numStateChanges):
+ c_attr = c_ntf.changedStates[i]
+ attr = ntf.StateChange()
+ attr.state_id = c_attr.stateId
+ attr.new_state = c_attr.newState
+ attr.old_state_present = c_attr.oldStatePresent
+ if c_attr.oldStatePresent:
+ attr.old_state = c_attr.oldState
+ ntf_info.state_changes.append(attr)
+
+ def _parse_alarm_ntf(self, c_ntf, ntf_info):
+ """ Parse the received alarm notification to retrieve its information
+
+ Args:
+ c_ntf (SaNtfAlarmNotificationT): Alarm notification structure
+ ntf_info (NotificationInfo): NotificationInfo structure with
+ information from the notification
+ """
+ ntf_handle = c_ntf.notificationHandle
+ ntf_info.probable_cause = c_ntf.probableCause.contents.value
+
+ for i in range(c_ntf.numSpecificProblems):
+ ntf_info.specific_problems.append(
+ c_ntf.specificProblems[i])
+ ntf_info.perceived_severity = c_ntf.perceivedSeverity.contents.value
+ ntf_info.trend = c_ntf.trend.contents.value
+
+ c_threshold_info = c_ntf.thresholdInformation.contents
+ if c_threshold_info:
+ threshold_info = ntf.ThresholdInformation()
+ c_threshold_info = c_ntf.thresholdInformation.contents
+
+ threshold_info.threshold_id = c_threshold_info.thresholdId
+ threshold_info.threshold_value_type = \
+ c_threshold_info.thresholdValueType
+ threshold_info.threshold_value = \
+ self._get_ntf_value(ntf_handle,
+ c_threshold_info.thresholdValue,
+ c_threshold_info.thresholdValueType)
+ threshold_info.threshold_hysteresis = \
+ self._get_ntf_value(ntf_handle,
+ c_threshold_info.thresholdHysteresis,
+ c_threshold_info.thresholdValueType)
+ threshold_info.observed_value = \
+ self._get_ntf_value(ntf_handle,
+ c_threshold_info.observedValue,
+ c_threshold_info.thresholdValueType)
+ threshold_info.arm_time = c_threshold_info.armTime
+
+ ntf_info.threshold_information = threshold_info
+
+ for i in range(c_ntf.numMonitoredAttributes):
+ c_attr = c_ntf.monitoredAttributes[i]
+ attr = ntf.Attribute()
+ attr.attribute_id = c_attr.attributeId
+ attr.attribute_type = c_attr.attributeType
+ attr.attribute_value = \
+ self._get_ntf_value(ntf_handle, c_attr.attributeValue,
+ c_attr.attributeType)
+ ntf_info.monitored_attrs.append(attr)
+
+ for i in range(c_ntf.numProposedRepairActions):
+ c_action = c_ntf.proposedRepairActions[i]
+ action = ntf.ProposedRepairAction()
+ action.action_id = c_action.actionId
+ action.action_value_type = c_action.actionValueType
+ action.action_value = \
+ self._get_ntf_value(ntf_handle, c_action.actionValue,
+ c_action.actionValueType)
+ ntf_info.proposed_repair_actions.append(action)
+
+ def _parse_security_alarm_ntf(self, c_ntf, ntf_info):
+ """ Parse the received security alarm notification to retrieve its
+ information
+
+ Args:
+ c_ntf (SaNtfSecurityAlarmNotificationT): Security alarm
+ notification structure
+ ntf_info (NotificationInfo): NotificationInfo structure with
+ information from the notification
+ """
+ ntf_handle = c_ntf.notificationHandle
+ ntf_info.probable_cause = c_ntf.probableCause.contents.value
+ ntf_info.severity = c_ntf.severity.contents.value
+ if c_ntf.securityAlarmDetector.contents:
+ ntf_info.security_alarm_detector = ntf.SecurityAlarmDetector()
+ ntf_info.security_alarm_detector.value_type = \
+ c_ntf.securityAlarmDetector.contents.valueType
+ ntf_info.security_alarm_detector.value = self._get_ntf_value(
+ ntf_handle,
+ c_ntf.securityAlarmDetector.contents.value,
+ c_ntf.securityAlarmDetector.contents.valueType)
+ if c_ntf.serviceUser.contents:
+ ntf_info.service_user = ntf.SecurityAlarmDetector()
+ ntf_info.service_user.value_type = \
+ c_ntf.serviceUser.contents.valueType
+ ntf_info.service_user.value = self._get_ntf_value(
+ ntf_handle,
+ c_ntf.serviceUser.contents.value,
+ c_ntf.serviceUser.contents.valueType)
+ if c_ntf.serviceProvider.contents:
+ ntf_info.service_provider = ntf.SecurityAlarmDetector()
+ ntf_info.service_provider.value_type = \
+ c_ntf.serviceProvider.contents.valueType
+ ntf_info.service_provider.value = self._get_ntf_value(
+ ntf_handle,
+ c_ntf.serviceProvider.contents.value,
+ c_ntf.serviceProvider.contents.valueType)
+
+
+class NtfSubscriber(NtfConsumer):
+ """ This class provides functions of the NTF Subscriber interface """
+
+ def _ntf_notif_callback(self, c_subscription_id, c_notif):
+ """ This callback is invoked by NTF to deliver a notification to a
+ subscriber of that notification type.
+
+ Args:
+ c_subscription_id (SaNtfSubscriptionIdT): The subscription id
+ previously provided by the subscriber when subscribing for this
+ type of notification
+ c_notif (SaNtfNotificationsT): The notification delivered by this
+ callback
+ """
+ if not self.ntf_notif_function:
+ return
+
+ subscription_id = c_subscription_id
+ notification_type = c_notif.contents.notificationType
+ if notification_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE:
+ notification = \
+ c_notif.contents.notification.objectCreateDeleteNotification
+ ntf_handle = notification.notificationHandle
+ ntf_header = notification.notificationHeader
+ ntf_info = self._parse_notification_header(ntf_handle, ntf_header)
+ self._parse_object_create_delete_ntf(notification, ntf_info)
+ elif notification_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE:
+ notification = \
+ c_notif.contents.notification.attributeChangeNotification
+ ntf_handle = notification.notificationHandle
+ ntf_header = notification.notificationHeader
+ ntf_info = self._parse_notification_header(ntf_handle, ntf_header)
+ self._parse_attribute_change_ntf(notification, ntf_info)
+
+ elif notification_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE:
+ notification = \
+ c_notif.contents.notification.stateChangeNotification
+ ntf_handle = notification.notificationHandle
+ ntf_header = notification.notificationHeader
+ ntf_info = self._parse_notification_header(ntf_handle, ntf_header)
+ self._parse_state_change_ntf(notification, ntf_info)
+
+ elif notification_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+ notification = c_notif.contents.notification.alarmNotification
+ ntf_handle = notification.notificationHandle
+ ntf_header = notification.notificationHeader
+ ntf_info = self._parse_notification_header(ntf_handle, ntf_header)
+ self._parse_alarm_ntf(notification, ntf_info)
+
+ elif notification_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM:
+ notification = \
+ c_notif.contents.notification.securityAlarmNotification
+ ntf_handle = notification.notificationHandle
+ ntf_header = notification.notificationHeader
+ ntf_info = self._parse_notification_header(ntf_handle, ntf_header)
+ self._parse_security_alarm_ntf(notification, ntf_info)
+
+ else:
+ return
+
+ # Send the ntf info to user's callback function
+ self.ntf_notif_function(subscription_id, notification_type, ntf_info)
+
+ def _ntf_notif_discarded_callback(self, c_subscription_id,
+ c_notification_type, c_number_discarded,
+ c_discarded_notification_identifiers):
+ """ This callback is invoked by NTF to notify a subscriber of a
+ particular notification type that one or more notifications of that
+ type have been discarded.
+
+ Args:
+ c_subscription_id (SaNtfSubscriptionIdT): The subscription id
+ previously provided by the subscriber when subscribing for
+ discarded notifications
+ c_notification_type (SaNtfNotificationTypeT): The notification type
+ of the discarded notifications
+ c_number_discarded (SaUint32T): The number of discarded
+ notifications
+ c_discarded_notification_identifiers (SaNtfIdentifierT): The list
+ of notification identifiers of the discarded notifications
+ """
+ if not self.ntf_notif_discarded_function:
+ return
+
+ # Send all info to user callback
+ self.ntf_notif_discarded_function(c_subscription_id,
+ c_notification_type,
+ c_number_discarded,
+ c_discarded_notification_identifiers)
+
+ @bad_handle_retry
+ def _re_init(self):
+ """ Internal function to re-initialize the NTF agent and fetch a new
+ selection object in case of getting BAD_HANDLE during an operation
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ self.finalize()
+ self.version = deepcopy(self.init_version)
+ self.handle = saNtf.SaNtfHandleT()
+ rc = ntf.saNtfInitialize(self.handle, self.callbacks, self.version)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfInitialize FAILED - %s" % (eSaAisErrorT.whatis(rc)))
+ else:
+ rc = self._fetch_sel_obj()
+
+ return rc
+
+ def init(self, ntf_notif_func=None, ntf_notif_discarded_func=None):
+ """ Initialize the NTF agent and fetch the selection object
+
+ Args:
+ ntf_notif_func (callback): Callback function for subscribed
+ notifications
+ ntf_notif_discarded_func (callback): Callback function for
+ discarded notifications
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ rc = self.initialize(ntf_notif_func, ntf_notif_discarded_func)
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ rc = self._fetch_sel_obj()
+ if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
+ self._re_init()
+ return rc
+
+ @bad_handle_retry
+ def subscribe(self, subscription_id, notification_types=None):
+ """ Subscribe for notifications from NTF with the types specified in
+ the notification_types list. If the list is not provided, all types of
+ notification are subscribed to by default.
+
+ NOTE: Users have to set the wanted filters criteria via the set of
+ set_filter_*() methods before calling this method. Otherwise, the
+ filters criteria will be set with default values.
+
+ Args:
+ subscription_id (SaNtfSubscriptionIdT): Subscription id
+ notification_types (list(SaNtfNotificationTypeT)): List of
+ notification types
+
+ Returns:
+ SaAisErrorT: Return code of the corresponding NTF API call(s)
+ """
+ self.filter_handles = \
+ saNtf.SaNtfNotificationTypeFilterHandlesT(0, 0, 0, 0, 0)
+
+ create_delete = \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE
+ attr_change = \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE
+ state_change = \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE
+ alarm = saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM
+ security_alarm = \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM
+
+ rc = eSaAisErrorT.SA_AIS_OK
+ # Create and allocate the object create delete filter
+ if notification_types is None or create_delete in notification_types:
+ rc = self._generate_object_create_delete_filter()
+
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ # Create and allocate the attribute change filter
+ if notification_types is None or attr_change in notification_types:
+ rc = self._generate_attribute_change_filter()
+
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ # Create and allocate the state change filter
+ if notification_types is None \
+ or state_change in notification_types:
+ rc = self._generate_state_change_filter()
+
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ # Create and allocate the alarm filter
+ if notification_types is None or alarm in notification_types:
+ rc = self._generate_alarm_filter()
+
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ # Create and allocate the security alarm filter
+ if notification_types is None \
+ or security_alarm in notification_types:
+ rc = self._generate_security_alarm_filter()
+
+ if rc == eSaAisErrorT.SA_AIS_OK:
+ # Start subscription
+ rc = ntf.saNtfNotificationSubscribe(self.filter_handles,
+ subscription_id)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ log_err("saNtfNotificationSubscribe FAILED, rc = %s" %
+ eSaAisErrorT.whatis(rc))
+ else:
+ self.clear_filter_info()
+
+ # Free the notification filters
+ self._free_notification_filters()
+
+ if rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
+ init_rc = self._re_init()
+ # If the re-initialization of agent handle succeeds, we still need
+ # to return BAD_HANDLE to the function decorator, so that it 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:
+ rc = init_rc
+
+ return rc
+
+ @staticmethod
+ def unsubscribe(subscription_id):
+ """ Unsubscribe the previous notification subscription
+
+ Args:
+ subscription_id (SaNtfSubscriptionIdT): Subscription id provided in
+ the previous notification subscription
+
+ Returns:
+ SaAisErrorT: Return code of the saNtfNotificationUnsubscribe()
+ API call
+ """
+ return ntf.saNtfNotificationUnsubscribe(subscription_id)
--
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