opensaf.spec.in                     |    3 +
 python/pyosaf/saNtf.py              |   27 +
 python/pyosaf/utils/Makefile.am     |    3 +-
 python/pyosaf/utils/ntf/Makefile.am |   22 +
 python/pyosaf/utils/ntf/__init__.py |  657 ++++++++++++++++++++++++++++++++++++
 python/samples/README               |   11 +
 python/samples/ntfsend              |  251 +++++++++++++
 python/samples/ntfsubscribe         |  307 ++++++++++++++++
 8 files changed, 1280 insertions(+), 1 deletions(-)


Add high-level bindings and sample applications for NTF. A known issue
is that the assignment of additionalText is not working.

Verify by using the ntfsend and ntfsubscribe sample applications.

diff --git a/opensaf.spec.in b/opensaf.spec.in
--- a/opensaf.spec.in
+++ b/opensaf.spec.in
@@ -1524,6 +1524,9 @@ fi
 %{python_sitelib}/pyosaf/utils/log/*.py
 %{python_sitelib}/pyosaf/utils/log/*.pyc
 %{python_sitelib}/pyosaf/utils/log/*.pyo
+%{python_sitelib}/pyosaf/utils/ntf/*.py
+%{python_sitelib}/pyosaf/utils/ntf/*.pyc
+%{python_sitelib}/pyosaf/utils/ntf/*.pyo
 %{python_sitelib}/pyosaf/utils/immoi/*.py
 %{python_sitelib}/pyosaf/utils/immoi/*.pyc
 %{python_sitelib}/pyosaf/utils/immoi/*.pyo
diff --git a/python/pyosaf/saNtf.py b/python/pyosaf/saNtf.py
--- a/python/pyosaf/saNtf.py
+++ b/python/pyosaf/saNtf.py
@@ -176,6 +176,33 @@ eSaNtfValueTypeT = Enumeration((
        'SA_NTF_VALUE_ARRAY',
 ))
 
+SaNtfValueTypeMap = {
+       eSaNtfValueTypeT.SA_NTF_VALUE_UINT8: SaUint8T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_INT8: SaInt8T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_UINT16: SaUint16T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_INT16: SaInt16T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_UINT32: SaUint32T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_INT32: SaInt32T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_FLOAT: SaFloatT,
+       eSaNtfValueTypeT.SA_NTF_VALUE_UINT64: SaUint64T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_INT64: SaInt64T,
+       eSaNtfValueTypeT.SA_NTF_VALUE_DOUBLE: SaDoubleT,
+       eSaNtfValueTypeT.SA_NTF_VALUE_LDAP_NAME: SaStringT,
+       eSaNtfValueTypeT.SA_NTF_VALUE_STRING: SaStringT,
+       eSaNtfValueTypeT.SA_NTF_VALUE_IPADDRESS: SaStringT,
+       eSaNtfValueTypeT.SA_NTF_VALUE_BINARY: SaAnyT,
+       eSaNtfValueTypeT.SA_NTF_VALUE_ARRAY: SaAnyT
+}
+
+def unmarshalSaNtfValue(void_ptr, value_type):
+       """Convert void pointer to an instance of value type.
+       """
+       val_ptr = SaNtfValueTypeMap.get(value_type)
+       if val_ptr and void_ptr:
+               if val_ptr == SaNameT:
+                       return cast(void_ptr, POINTER(val_ptr))[0].value
+               return cast(void_ptr, POINTER(val_ptr))[0]
+       return None
 class _ptrVal(Structure):
        _fields_ = [('dataOffset', SaUint16T),
                ('dataSize', SaUint16T)]
diff --git a/python/pyosaf/utils/Makefile.am b/python/pyosaf/utils/Makefile.am
--- a/python/pyosaf/utils/Makefile.am
+++ b/python/pyosaf/utils/Makefile.am
@@ -25,4 +25,5 @@ SUBDIRS = \
        immom \
        clm \
        log \
-       immoi
+       immoi \
+       ntf
diff --git a/python/pyosaf/utils/ntf/Makefile.am 
b/python/pyosaf/utils/ntf/Makefile.am
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/ntf/Makefile.am
@@ -0,0 +1,22 @@
+#      -*- OpenSAF  -*-
+#
+# (C) Copyright 2011 The OpenSAF Foundation
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Oracle
+#
+
+include $(top_srcdir)/Makefile.common
+
+MAINTAINERCLEANFILES = Makefile.in
+
+pkgpyosafutilsntf_PYTHON = \
+       __init__.py
diff --git a/python/pyosaf/utils/ntf/__init__.py 
b/python/pyosaf/utils/ntf/__init__.py
new file mode 100644
--- /dev/null
+++ b/python/pyosaf/utils/ntf/__init__.py
@@ -0,0 +1,657 @@
+############################################################################
+#
+# (C) Copyright 2015 The OpenSAF Foundation
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson
+#
+############################################################################
+
+'''
+    NTF common utilities
+'''
+
+from pyosaf import saNtf, saAis
+import ctypes
+
+from pyosaf.utils import decorate
+
+saNtfInitialize                 = decorate(saNtf.saNtfInitialize)
+saNtfLocalizedMessageFree       = decorate(saNtf.saNtfLocalizedMessageFree)
+saNtfStateChangeNotificationFilterAllocate = 
decorate(saNtf.saNtfStateChangeNotificationFilterAllocate)
+saNtfNotificationUnsubscribe    = decorate(saNtf.saNtfNotificationUnsubscribe)
+saNtfNotificationReadInitialize = 
decorate(saNtf.saNtfNotificationReadInitialize)
+saNtfInitialize_2               = decorate(saNtf.saNtfInitialize_2)
+saNtfNotificationReadInitialize_2 = 
decorate(saNtf.saNtfNotificationReadInitialize_2)
+saNtfNotificationSubscribe      = decorate(saNtf.saNtfNotificationSubscribe)
+saNtfInitialize_3               = 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 = saAis.SaSelectionObjectT()
+CALLBACKS = saNtf.SaNtfCallbacksT()
+
+
+class AdditionalInfo(object):
+    ''' Represents 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):
+    ''' Contains information about a state change event'''
+
+    def __init__(self):
+        pass
+
+
+class AttributeChange(object):
+    ''' Contains information about a change in an attribute'''
+
+    def __init__(self):
+        pass
+
+
+class Attribute(object):
+    ''' Contains information about the value and value type of an attribute'''
+
+    def __init__(self):
+        pass
+
+
+class SecurityAlarmDetector(object):
+    ''' Represents an instance of a security alarm detector'''
+
+    def __init__(self, value=None, value_type=None):
+        self.value = value
+        self.value_type = value_type
+
+
+class ServiceUser(object):
+    ''' Represents a service user'''
+
+    def __init__(self, value=None, value_type=None):
+        self.value = value
+        self.value_type = value_type
+
+
+class ServiceProvider(object):
+    ''' Represents 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
+
+def initialize(notification_callback=None):
+    ''' Initializes the NTF library'''
+
+    # Initialize the NTF API
+    version = saAis.SaVersionT('A', 1, 1)
+
+    # Assign default values for callbacks
+    CALLBACKS.saNtfNotificationCallback = \
+                    saNtf.SaNtfNotificationCallbackT(dummy_func)
+    CALLBACKS.saNtfNotificationDiscardedCallback = \
+                    saNtf.SaNtfNotificationDiscardedCallbackT(dummy_func)
+
+    # Override the notification subscribe callback if it's passed
+    if notification_callback:
+        CALLBACKS.saNtfNotificationCallback = \
+                    saNtf.SaNtfNotificationCallbackT(notification_callback)
+
+    # Initialize the API
+    saNtfInitialize(HANDLE, CALLBACKS, version)
+
+    # Get the selection object
+    saNtfSelectionObjectGet(HANDLE, SELECTION_OBJECT)
+
+
+def assign_ntf_value_to_attribute(attr_value_field, value, value_type):
+    ''' Assigns the correct sub-field in the given attribute
+
+        e.g. attr_value_field.uint8Val = ...
+
+    '''
+
+    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
+
+    elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT64:
+        attr_value_field.uint64Val = value
+
+    elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT64:
+        attr_value_field.int64Val = value
+
+    elif value_type == saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_DOUBLE:
+        attr_value_field.doubleVal = value
+
+
+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):
+    ''' Fills in the given notification header with the provided values'''
+
+    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)
+
+    ##
+    ## FIXME: this fails to copy the value of the additional_text variable into
+    ##        header.additionalText.
+
+    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 in range(0, len(additional_info)):
+
+            header.additionalInfo[i].infoId = additional_info[i].info_id
+            header.additionalInfo[i].infoType = additional_info[i].info_type
+
+            dest_ptr = (ctypes.c_char * len(additional_info[i].info_value))()
+
+            saNtf.saNtfPtrValAllocate(notification_handle,
+                                      len(additional_info[i].info_value) + 1,
+                                      dest_ptr,
+                                      header.additionalInfo[i].infoValue)
+
+            ctypes.memmove(ctypes.addressof(dest_ptr),
+                           additional_info[i].info_value,
+                           len(additional_info[i].info_value) + 1)
+
+    else:
+        header.additionalInfo = None
+
+
+def send_object_create_notification(vendor_id, major_id, minor_id,
+                                    additional_text="",
+                                    notification_object="",
+                                    notifying_object="",
+                                    attributes=[],
+                                    event_time=saAis.saAis.SA_TIME_UNKNOWN,
+                                    additional_info=[]):
+    ''' Sends a notification for a created object'''
+
+    _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)
+
+
+def send_object_delete_notification(vendor_id,
+                                    major_id,
+                                    minor_id,
+                                    additional_text="",
+                                    notification_object="",
+                                    notifying_object="",
+                                    attributes=[],
+                                    event_time=saAis.saAis.SA_TIME_UNKNOWN,
+                                    additional_info=[]):
+    ''' Sends a notification for a deleted object'''
+
+    _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=[],
+        event_time=saAis.saAis.SA_TIME_UNKNOWN,
+        additional_info=[]):
+    ''' Sends an object create delete notification'''
+
+    # Create the notification
+    notification = saNtf.SaNtfObjectCreateDeleteNotificationT()
+
+    saNtfObjectCreateDeleteNotificationAllocate(
+        HANDLE,
+        notification,
+        0,
+        len(additional_text) + 1,
+        len(additional_info),
+        len(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 in range(0, 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)
+
+
+    # Send the notification
+    saNtfNotificationSend(notification.notificationHandle)
+
+    # Free the notification
+    saNtfNotificationFree(notification.notificationHandle)
+
+
+def send_state_change_notification(vendor_id,
+                                   major_id,
+                                   minor_id,
+                                   additional_text="",
+                                   notification_object="",
+                                   notifying_object="",
+                                   event_time=saAis.saAis.SA_TIME_UNKNOWN,
+                                   additional_info=[],
+                                   state_changes=[]):
+    ''' Sends a state change notification'''
+
+    event_type = saNtf.eSaNtfEventTypeT.SA_NTF_OBJECT_STATE_CHANGE
+
+    # Create the notification
+    notification = saNtf.SaNtfStateChangeNotificationT()
+
+    saNtfStateChangeNotificationAllocate(
+        HANDLE,
+        notification,
+        0,
+        len(additional_text) + 1,
+        len(additional_info),
+        len(state_changes),
+        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 state changes
+
+    for i in range(0, len(state_changes)):
+
+        notification.changedStates[i].stateId = state_changes[i].state_id
+
+        if state_changes[i].old_state_present:
+            notification.changedStates[i].oldStatePresent = 
saAis.eSaBoolT.SA_TRUE
+            notification.changedStates[i].oldState = state_changes[i].old_state
+
+        else:
+            notification.changedStates[i].oldStatePresent = 
saAis.eSaBoolT.SA_FALSE
+
+        notification.changedStates[i].newState = state_changes[i].new_state
+
+    # Send the alarm notification
+    saNtfNotificationSend(notification.notificationHandle)
+
+    # Free the alarm notification
+    saNtfNotificationFree(notification.notificationHandle)
+
+
+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.saAis.SA_TIME_UNKNOWN,
+                                       additional_info=[],
+                                       changed_attributes=[]):
+    ''' Sends an attribute_change notification'''
+
+    # 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 in range(0, len(changed_attributes)):
+
+        ptr = notification.changedAttributes[i]
+
+        ptr.attributeId = changed_attributes[i].attribute_id
+        ptr.attributeType = changed_attributes[i].attribute_type
+
+        if changed_attributes[i].old_attribute_present:
+            ptr.oldAttributePresent = saAis.eSaBoolT.SA_TRUE
+
+            assign_ntf_value_to_attribute(ptr.oldAttributeValue,
+                                          
changed_attributes[i].old_attribute_value,
+                                          changed_attributes[i].attribute_type)
+
+        else:
+            ptr.oldAttributePresent = saAis.eSaBoolT.SA_FALSE
+
+        assign_ntf_value_to_attribute(ptr.newAttributeValue,
+                                      
changed_attributes[i].new_attribute_value,
+                                      changed_attributes[i].attribute_type)
+
+    # Send the alarm notification
+    saNtfNotificationSend(notification.notificationHandle)
+
+    # Free the alarm notification
+    saNtfNotificationFree(notification.notificationHandle)
+
+
+def send_security_alarm_notification(vendor_id, major_id, minor_id, severity,
+                                     alarm_detector,
+                                     user,
+                                     provider,
+                                     additional_text="",
+                                     notification_object="",
+                                     notifying_object="",
+                                     
event_type=saNtf.eSaNtfEventTypeT.SA_NTF_INTEGRITY_VIOLATION,
+                                     event_time=saAis.saAis.SA_TIME_UNKNOWN,
+                                     additional_info=[],
+                                     
probable_cause=saNtf.eSaNtfProbableCauseT.SA_NTF_SOFTWARE_ERROR):
+
+    ''' Sends a security alarm notification'''
+
+    # 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)
+
+    assign_ntf_value_to_attribute(notification.serviceProvider,
+                                  provider.value,
+                                  provider.value_type)
+
+    # Send the alarm notification
+    saNtfNotificationSend(notification.notificationHandle)
+
+    # Free the alarm 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.saAis.SA_TIME_UNKNOWN,
+                            additional_info=[]):
+    ''' Sends an alarm notification'''
+
+    # 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
+
+    # Send the alarm notification
+    saNtfNotificationSend(notification.notificationHandle)
+
+    # Free the alarm notification
+    saNtfNotificationFree(notification.notificationHandle)
+
+
+def subscribe_for_notifications(notification_types=None):
+    ''' Subscribes 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
+    '''
+
+    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()
+
+        saNtfAlarmNotificationFilterAllocate(HANDLE, notification_filter,
+                                             0, 0, 0, 0, 0, 0, 0)
+
+        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)
+
+        filter_handles.stateChangeFilterHandle = 
notification_filter.notificationFilterHandle
+
+        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:
+
+        notification_filter = saNtf.SaNtfSecurityAlarmNotificationFilterT()
+
+        saNtfSecurityAlarmNotificationFilterAllocate(HANDLE,
+                                                     notification_filter,
+                                                     0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+        filter_handles.securityAlarmFilterHandle = 
notification_filter.notificationFilterHandle
+
+        filters.append(notification_filter.notificationFilterHandle)
+
+    # Create a unique subscription id
+    sub_id = saNtf.SaNtfSubscriptionIdT(1)
+
+    # Start subscription
+    saNtfNotificationSubscribe(filter_handles, sub_id)
+
+    # Free up the filters
+    for filter_handle in filters:
+        saNtfNotificationFilterFree(filter_handle)
+
+
+def dispatch(mode=saAis.eSaDispatchFlagsT.SA_DISPATCH_ALL):
+    ''' Invokes NTF callbacks for queued events. The default is to dispatch all
+        available events
+    '''
+
+    saNtfDispatch(HANDLE, mode)
+
diff --git a/python/samples/README b/python/samples/README
--- a/python/samples/README
+++ b/python/samples/README
@@ -74,6 +74,17 @@ interface-handler:
         netifaces library to do so. Run 'interface-handler --help' for
         specific options and arguments.
 
+ntfsend:
+        The ntfsend sample application is a copy of the ntfsend tool,
+        implemented in Python. It sends notifications through NTF. Run
+        'ntfsend --help' for specific options and arguments.
+
+ntfsubscribe:
+       The ntfsubscribe sample application is a copy of the
+       ntfsubscribe tool, implemented in Python. It listens for
+       notifications and logs received notifications in the
+       terminal. Run 'ntfsubscribe --help'.
+
 Logging for all apps/utils goes to /var/log/opensaf/saflog/saLogSystem*.log
 
 The IMM OI samples use the classes defined in the classes.xml file. Load it 
with immcfg -f classes.xml before trying them. 
diff --git a/python/samples/ntfsend b/python/samples/ntfsend
new file mode 100755
--- /dev/null
+++ b/python/samples/ntfsend
@@ -0,0 +1,251 @@
+#! /usr/bin/env python
+
+import argparse
+import time
+
+from pyosaf import saNtf, saAis
+from pyosaf.utils import ntf
+
+
+def construct_additional_info(additional_info_string):
+    ''' Constructs an AdditionalInfo instance from the given string.
+
+        The string must be of the format ID,TYPE,VALUE
+    '''
+
+    info_id = int(additional_info_string.split(',')[0])
+    info_type = int(additional_info_string.split(',')[1])
+    info_value = ','.join(additional_info_string.split(',')[2:])
+
+    return ntf.AdditionalInfo(info_id, info_type, info_value)
+
+
+if __name__ == '__main__':
+
+    # Parse command line arguments
+    parser = argparse.ArgumentParser(
+        description='ntfsend is a SAF NTF client used to send a notificaiton.')
+
+    parser.add_argument('--notificationType', '-T', metavar='0x1000...0x5000',
+                        default='0x4000',
+                        help='numeric value of SaNtfNotificationTypeT'
+                        
'(obj_create_del=0x1000,attr_ch,state_ch,al,sec_al=0x5000)')
+    parser.add_argument('--eventType', '-e', metavar='4096...24589',
+                        help='numeric value of SaNtfEventTypeT'
+                        
'(SA_NTF_OBJECT_NOTIFICATIONS_START...SA_NTF_HPI_EVENT_OTHER)')
+    parser.add_argument('--eventTime', '-E', metavar='TIME',
+                        default=saAis.saAis.SA_TIME_UNKNOWN,
+                        help='numeric value of SaTimeT')
+    parser.add_argument('--notificationClassId', '-c', metavar='VE,MA,MI',
+                        default='162,1,1',
+                        help='vendorid, majorid, minorid')
+    parser.add_argument('--notificationObject', '-n', metavar='NOT_OBJ',
+                        default="",
+                        help='notification object (string value)')
+    parser.add_argument('--notifyingObject', '-N', metavar='NOTIFY_OBJ',
+                        default="",
+                        help='notififying object (string value)')
+    parser.add_argument('--additionalText', '-a', metavar='TEXT',
+                        default="",
+                        help='additional text (string value)')
+    parser.add_argument('--probableCause', '-p', metavar='0..74',
+                        help='numeric value SaNtfProbableCauseT'
+                        'SA_NTF_ADAPTER_ERROR to SA_NTF_UNSPECIFIED_REASON')
+    parser.add_argument('--perceivedSeverity', '-s', metavar='0...5',
+                        type=int, default='4',
+                        help='severity numeric value'
+                        '(clear=0,ind,warn,min,maj,crit=5)')
+    parser.add_argument('--repeatSends', '-r', metavar='NUM',
+                        default=1, type=int,
+                        help='send the same notifification NUM times')
+    parser.add_argument('--burstTimeout', '-b', metavar='TIME',
+                        default=0, type=int,
+                        help='send burst of NUM repeatSends '
+                        '[default: 1] and sleep TIME (usec)'
+                        'between each burst, will continue for ever')
+    parser.add_argument('--additionalInfo', '-i', metavar='ID,TYPE,VALUE',
+                        help='additional information'
+                        'ID: SaNtfElementIdT integer value'
+                        'TYPE: numeric value SaNtfValueTypeT, only '
+                        'SA_NTF_VALUE_STRING=11 is supported')
+
+    args = parser.parse_args()
+
+    # Fill in arguments
+    vendor_id = int(args.notificationClassId.split(',')[0])
+    major_id = int(args.notificationClassId.split(',')[1])
+    minor_id = int(args.notificationClassId.split(',')[2])
+
+    event_time = int(args.eventTime)
+
+    severity = int(args.perceivedSeverity)
+
+    additional_text = args.additionalText
+    notification_object = args.notificationObject
+    notifying_object = args.notifyingObject
+
+    # Initialize the NTF library
+    ntf.initialize()
+
+    # Send the notification
+    ntf_type = int(args.notificationType, 0)
+
+    if ntf_type == 
saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE:
+
+        # Create sample attributes
+        attributes = []
+
+        attr1 = ntf.Attribute()
+
+        attr1.attribute_id = 1
+        attr1.attribute_type = saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT16
+        attr1.attribute_value = 23
+
+        attributes.append(attr1)
+
+        attr2 = ntf.Attribute()
+
+        attr2.attribute_id = 2
+        attr2.attribute_type = saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32
+        attr2.attribute_value = -3
+
+        attributes.append(attr2)
+
+        # Create sample additional info
+        additional_info = []
+        if args.additionalInfo:
+            
additional_info.append(construct_additional_info(args.additionalInfo))
+
+        # Send the notification
+        for i in range(0, args.repeatSends):
+            ntf.send_object_create_notification(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)
+
+            time.sleep(args.burstTimeout)
+
+    elif ntf_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM:
+
+        # Create security alarm sample fields
+
+        detector = ntf.SecurityAlarmDetector(
+            value=15,
+            value_type=saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32
+        )
+
+        user = ntf.ServiceUser(
+            value=-2,
+            value_type=saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT16
+        )
+
+        provider = ntf.ServiceProvider(
+            value=128,
+            value_type=saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_UINT32
+        )
+
+        # Send the notification
+        for i in range(0, args.repeatSends):
+            ntf.send_security_alarm_notification(vendor_id, major_id, 
minor_id, severity,
+                                                 detector, user, provider,
+                                                 
additional_text=additional_text,
+                                                 
notification_object=notification_object,
+                                                 
notifying_object=notifying_object,
+                                                 event_time=event_time)
+
+            time.sleep(args.burstTimeout)
+
+    elif ntf_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+
+        for i in range(0, args.repeatSends):
+            ntf.send_alarm_notification(vendor_id, major_id, minor_id, 
severity,
+                                        additional_text=additional_text,
+                                        
notification_object=notification_object,
+                                        notifying_object=notifying_object,
+                                        event_time=event_time)
+
+            time.sleep(args.burstTimeout)
+
+    elif ntf_type == 
saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE:
+
+        # Fill in sample attribute changes
+
+        attr0 = ntf.AttributeChange()
+
+        attr0.attribute_id = 0
+        attr0.attribute_type = saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32
+        attr0.old_attribute_present = saAis.eSaBoolT.SA_FALSE
+        attr0.new_attribute_value = 1
+
+        attr1 = ntf.AttributeChange()
+
+        attr1.attribute_id = 1
+        attr1.attribute_type = saNtf.eSaNtfValueTypeT.SA_NTF_VALUE_INT32
+        attr1.old_attribute_present = saAis.eSaBoolT.SA_TRUE
+        attr1.old_attribute_value = 8
+        attr1.new_attribute_value = -4
+
+        changed_attributes = [attr0, attr1]
+
+        # Send the notification
+        for i in range(0, args.repeatSends):
+            ntf.send_attribute_change_notification(vendor_id, major_id, 
minor_id,
+                                                   
additional_text=additional_text,
+                                                   
notification_object=notification_object,
+                                                   
notifying_object=notifying_object,
+                                                   event_time=event_time,
+                                                   
changed_attributes=changed_attributes)
+
+            time.sleep(args.burstTimeout)
+
+    elif ntf_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE:
+
+        # Fill in sample state changes
+        changes = []
+
+        change0 = ntf.StateChange()
+
+        change0.state_id = 1
+        change0.old_state_present = False
+        change0.new_state = 0
+
+        change1 = ntf.StateChange()
+
+        change1.state_id = 2
+        change1.old_state_present = False
+        change1.new_state = 5
+
+        change2 = ntf.StateChange()
+
+        change2.state_id = 1
+        change2.old_state_present = True
+        change2.old_state = 0
+        change2.new_state = 1
+
+        change3 = ntf.StateChange()
+
+        change3.state_id = 2
+        change3.old_state_present = True
+        change3.old_state = 5
+        change3.new_state = 10
+
+        changes.append(change0)
+        changes.append(change1)
+        changes.append(change2)
+        changes.append(change3)
+
+        # Send the notification
+        for i in range(0, args.repeatSends):
+            ntf.send_state_change_notification(vendor_id, major_id, minor_id,
+                                               additional_text=additional_text,
+                                               
notification_object=notification_object,
+                                               
notifying_object=notifying_object,
+                                               event_time=event_time,
+                                               state_changes=changes)
+
+            time.sleep(args.burstTimeout)
diff --git a/python/samples/ntfsubscribe b/python/samples/ntfsubscribe
new file mode 100755
--- /dev/null
+++ b/python/samples/ntfsubscribe
@@ -0,0 +1,307 @@
+#! /usr/bin/env python
+
+import select
+import ctypes
+import datetime
+import argparse
+
+from pyosaf import saNtf, saAis
+from pyosaf.utils import ntf
+
+def SaNameT_to_string(name):
+    ''' Converts an instance of SaNameT to a Python string'''
+
+    return ctypes.create_string_buffer(name.value, name.length).value
+
+def p_char_to_string(p_char, length):
+    ''' Converts a char pointer with a missing NULL pointer to a string with 
the
+        given length'''
+
+    return ctypes.create_string_buffer(p_char, length).value
+
+def SaTimeT_to_date_string(sa_time):
+    ''' Returns a string representation for the given SaTimeT instance'''
+
+    milli_seconds = sa_time / 1000000
+
+    return datetime.datetime.fromtimestamp(milli_seconds/1000).isoformat()
+
+def print_notification_header(header):
+    ''' Prints the given notification header'''
+
+    class_id = header.notificationClassId.contents
+
+    print '''eventType = %s
+notificationObject = "%s"
+notifyingObject = "%s"
+notificationClassId = %d.%d.%d (0x0)
+additionalText = "%s"''' % (
+    saNtf.eSaNtfEventTypeT.whatis(header.eventType.contents.value),
+    SaNameT_to_string(header.notificationObject.contents),
+    SaNameT_to_string(header.notifyingObject.contents),
+    class_id.vendorId,
+    class_id.majorId,
+    class_id.minorId,
+    p_char_to_string(header.additionalText, header.lengthAdditionalText)
+)
+
+
+def print_alarm_notification(notification):
+    ''' Prints the given alarm notification'''
+
+    header = notification.notificationHeader
+
+    print '===  %s - Alarm  ===' % 
SaTimeT_to_date_string(header.eventTime.contents.value)
+
+    print_notification_header(header)
+
+    print 'probableCause = %s' % \
+       
saNtf.eSaNtfProbableCauseT.whatis(notification.probableCause.contents.value)
+    print 'perceivedSeverity = %s' % \
+       
saNtf.eSaNtfSeverityT.whatis(notification.perceivedSeverity.contents.value)
+
+
+def print_object_create_delete_notification(notification):
+    ''' Prints the given object create delete notification'''
+
+    header = notification.notificationHeader
+
+    print '===  %s - Object Create/Delete  ===' % 
SaTimeT_to_date_string(header.eventTime.contents.value)
+
+    print_notification_header(header)
+
+    print 'sourceIndicator = %s' % \
+       
saNtf.eSaNtfSourceIndicatorT.whatis(notification.sourceIndicator.contents.value)
+
+    print
+
+    print 'numAttributes: %d' % notification.numAttributes
+
+    for i in range(0, notification.numAttributes):
+
+        c_attribute = notification.objectAttributes[i]
+
+        print '- Attribute ID: %d -' % c_attribute.attributeId
+        print ' Attribute Type: (%d) %s' % (
+           c_attribute.attributeType,
+           saNtf.eSaNtfValueTypeT.whatis(c_attribute.attributeType)
+        )
+
+        print ' Attribute Value: %d' % \
+           saNtf.unmarshalSaNtfValue(saAis.BYREF(c_attribute.attributeValue),
+                                     c_attribute.attributeType)
+
+
+def print_attribute_change_notification(notification):
+    ''' Prints the given attribute change notification'''
+
+    header = notification.notificationHeader
+
+    print '===  %s - Attribute Change  ===' % 
SaTimeT_to_date_string(header.eventTime.contents.value)
+
+    print_notification_header(header)
+
+    print 'sourceIndicator = %s' % \
+       
saNtf.eSaNtfSourceIndicatorT.whatis(notification.sourceIndicator.contents.value)
+
+    print
+
+    print 'numAttributes: %d' % notification.numAttributes
+
+    for i in range(0, notification.numAttributes):
+
+        c_attribute = notification.changedAttributes[i]
+
+        print '''- Attribute ID: %d -
+ Attribute Type: (%d) %s''' % (
+    c_attribute.attributeId,
+    c_attribute.attributeType,
+    saNtf.eSaNtfValueTypeT.whatis(c_attribute.attributeType)
+)
+
+        if c_attribute.oldAttributePresent:
+            print ''' Old Attribute Present: Yes
+ Old Attribute Value: %s''' % \
+    saNtf.unmarshalSaNtfValue(saAis.BYREF(c_attribute.oldAttributeValue),
+                              c_attribute.attributeType)
+        else:
+            print ' Old Attribute Present: No'
+
+        print ' Attribute Value: %s' % \
+           
saNtf.unmarshalSaNtfValue(saAis.BYREF(c_attribute.newAttributeValue),
+                                     c_attribute.attributeType)
+
+
+def print_state_change_notification(notification):
+    ''' Prints the given state change notification'''
+
+    header = notification.notificationHeader
+
+    print '===  %s - State Change  ===' % 
SaTimeT_to_date_string(header.eventTime.contents.value)
+
+    print_notification_header(header)
+
+    print 'sourceIndicator = %s' % \
+       
saNtf.eSaNtfSourceIndicatorT.whatis(notification.sourceIndicator.contents.value)
+
+    print
+
+    i = 0
+    for c_state in notification.changedStates:
+
+        if i == notification.numStateChanges:
+            break
+
+        i = i + 1
+
+        print '- State ID: %d -' % c_state.stateId
+
+        if c_state.oldStatePresent:
+            print ' Old State Present: Yes'
+            print ' Old State: %s' % c_state.oldState
+        else:
+            print ' Old State Present: No'
+
+        print ' New State: %s' % c_state.newState
+
+
+def print_security_alarm_notification(notification):
+    ''' Prints the given security alarm notification'''
+
+    header = notification.notificationHeader
+
+    print '===  %s - Security Alarm  ===' % 
SaTimeT_to_date_string(header.eventTime.contents.value)
+
+    print_notification_header(header)
+
+    print'''probableCause = %s
+severity = %s
+Security Alarm Detector Type: %d
+Security Alarm Detector Value: %d
+Service User Type: %d
+Service User Value: %d
+Service Provider Type: %d
+Service Provider Value: %d
+''' % (
+    
saNtf.eSaNtfProbableCauseT.whatis(notification.probableCause.contents.value),
+    saNtf.eSaNtfSeverityT.whatis(notification.severity.contents.value),
+    notification.securityAlarmDetector.contents.valueType,
+    
saNtf.unmarshalSaNtfValue(saAis.BYREF(notification.securityAlarmDetector.contents.value),
+                              
notification.securityAlarmDetector.contents.valueType),
+    notification.serviceUser.contents.valueType,
+    
saNtf.unmarshalSaNtfValue(saAis.BYREF(notification.serviceUser.contents.value),
+                              notification.serviceUser.contents.valueType),
+    notification.serviceProvider.contents.valueType,
+    
saNtf.unmarshalSaNtfValue(saAis.BYREF(notification.serviceProvider.contents.value),
+                              notification.serviceProvider.contents.valueType)
+)
+
+
+def notification_received(subscription_id, c_p_notification):
+    ''' Handle received notifications'''
+
+    notification_type = c_p_notification.contents.notificationType
+
+    print
+
+    if notification_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+        notification = c_p_notification.contents.notification.alarmNotification
+
+        print_alarm_notification(notification)
+
+    elif notification_type == 
saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE:
+        notification = 
c_p_notification.contents.notification.objectCreateDeleteNotification
+
+        print_object_create_delete_notification(notification)
+
+    elif notification_type == 
saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE:
+        notification = 
c_p_notification.contents.notification.attributeChangeNotification
+
+        print_attribute_change_notification(notification)
+
+    elif notification_type == 
saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE:
+        notification = 
c_p_notification.contents.notification.stateChangeNotification
+
+        print_state_change_notification(notification)
+
+    elif notification_type == 
saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM:
+        notification = 
c_p_notification.contents.notification.securityAlarmNotification
+
+        print_security_alarm_notification(notification)
+
+
+if __name__ == '__main__':
+
+    # Parse the parameters
+    parser = argparse.ArgumentParser(
+        description='ntfsubscribe is a SAF NTF client used to subscribe for 
all incoming notifications.')
+
+    parser.add_argument('--timeout', '-t', metavar='TIME',
+                        default=1,
+                        help='timeout (sec) waiting for notification')
+
+    parser.add_argument('--alarm', '-a',
+                        dest='alarm', action='store_true',
+                        help='subscribe for only alarm notifications')
+
+    parser.add_argument('--objectCreateDelete', '-o',
+                        dest='object_create_delete', action='store_true',
+                        help='subscribe for only objectCreateDelete 
notifications')
+
+    parser.add_argument('--attributeChange', '-c',
+                        dest='attribute_change', action='store_true',
+                        help='subscribe for only attributeChange 
notifications')
+
+    parser.add_argument('--stateChange', '-s',
+                        dest='state_change', action='store_true',
+                        help='subscribe for only stateChange notifications')
+
+    parser.add_argument('--securityAlarm', '-y',
+                        dest='security_alarm', action='store_true',
+                        help='subscribe for only securityAlarm notifications')
+
+    args = parser.parse_args()
+
+    print args.timeout
+
+    # Initialize the NTF library
+    ntf.initialize(notification_callback=notification_received)
+
+    # Subscribe for notifications
+    subscriptions = []
+
+    if args.object_create_delete:
+        
subscriptions.append(saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE)
+
+    if args.alarm:
+        subscriptions.append(saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM)
+
+    if args.attribute_change:
+        
subscriptions.append(saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE)
+
+    if args.state_change:
+        
subscriptions.append(saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE)
+
+    if args.security_alarm:
+        
subscriptions.append(saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM)
+
+    if subscriptions == []:
+        ntf.subscribe_for_notifications()
+    else:
+        ntf.subscribe_for_notifications(notification_types=subscriptions)
+
+    # Get selection object for the implementer
+    selection_object = ntf.SELECTION_OBJECT.value
+
+    # Wait for next OI event or one second timeout
+    inputs = [selection_object]
+    outputs = []
+
+    # Loop and wait for notifications
+    while True:
+
+        readable, writable, exceptional = \
+        select.select(inputs, outputs, inputs, args.timeout)
+
+        if selection_object in readable:
+            ntf.dispatch(saAis.eSaDispatchFlagsT.SA_DISPATCH_ALL)

------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to