- Refactor the ntfsend and ntfsubscribe python samples to make use of
the new pyosaf utils implementation of enhancement ticket #2602.
- Add a new ntfread sample to demonstrate usage of the new NtfReader
utils.
---
python/samples/ntfread | 411 ++++++++++++++++++++
python/samples/ntfsend | 922 ++++++++++++++++++++++++++++++++------------
python/samples/ntfsubscribe | 795 ++++++++++++++++++++++++--------------
3 files changed, 1591 insertions(+), 537 deletions(-)
create mode 100755 python/samples/ntfread
mode change 100644 => 100755 python/samples/ntfsend
mode change 100644 => 100755 python/samples/ntfsubscribe
diff --git a/python/samples/ntfread b/python/samples/ntfread
new file mode 100755
index 0000000..a70552b
--- /dev/null
+++ b/python/samples/ntfread
@@ -0,0 +1,411 @@
+#! /usr/bin/env python
+############################################################################
+#
+# (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
+"""
+ntfread tool used to read alarm and/or security alarm notifications from NTF
+
+Run ntfread --help/-h for more detail on usage
+"""
+from __future__ import print_function
+import sys
+import argparse
+from datetime import datetime, tzinfo, timedelta
+
+from pyosaf import saNtf
+from pyosaf.saAis import eSaAisErrorT
+from pyosaf.utils.ntf.reader import NtfReader
+
+
+class UTCOffsetTZ(tzinfo):
+ """ Time zone represented as UTC hour-offset """
+ def __init__(self, hour_offset):
+ """ UTCOffsetTZ constructor """
+ self._hour_offset = hour_offset
+ super(UTCOffsetTZ, self).__init__()
+
+ def utcoffset(self, dt):
+ """ Return offset of local time from UTC, in minutes east of UTC """
+ return timedelta(hours=self._hour_offset)
+
+ def dst(self, dt):
+ """ Return the daylight saving time (DST) adjustment, in minutes east
+ of UTC, or None if DST information isn't known
+ """
+ return timedelta(0)
+
+ def tzname(self, dt):
+ """ Return the time zone name represented in UTC hour-offset format as
+ 'UTC+/-offset'
+ """
+ if self._hour_offset > 0:
+ tzname = "UTC+%02d:00" % self._hour_offset
+ elif self._hour_offset < 0:
+ tzname = "UTC-%02d:00" % self._hour_offset
+ else: # hour_offset = 0
+ tzname = "UTC"
+
+ return tzname
+
+
+def satime_to_readable_datetime(sa_time, format_str=None):
+ """ Convert the given SaTimeT time value to readable datetime string
+ representation in ISO 8601 format
+
+ Args:
+ sa_time (SaTimeT): SaTimeT time value
+ format_str (str): Format string for datetime output representation
+
+ Returns:
+ str: Datetime representation in format specified by format_str, or in
+ ISO 8601 format 'YYYY-MM-DDTHH:MM:SS' if format_str not provided
+ """
+ time_sec = sa_time / 10**9 # Convert the time from nsec to sec 1000000000
+
+ # Calculate the UTC offset for time zone information
+ naive_dt = datetime.fromtimestamp(time_sec)
+ utc_offset = (naive_dt - datetime.utcfromtimestamp(time_sec))
+ hour_offset = utc_offset.total_seconds() // 3600
+ utc_offset_tz = UTCOffsetTZ(hour_offset)
+
+ aware_dt = naive_dt.replace(tzinfo=utc_offset_tz)
+
+ if format_str is not None:
+ return aware_dt.strftime(format_str)
+
+ return aware_dt.isoformat(' ')
+
+
+def _validate_ntf_class_id(arg):
+ """ Validate the input NtfClassId with format 'VENDOR_ID.MAJOR_ID.MINOR_ID'
+
+ Args:
+ arg (str): The NtfClassId to validate
+
+ Returns:
+ SaNtfClassIdT: The validated NtfClassId
+ """
+ if arg.count('.') != 2:
+ msg = "%r is not in correct format 'VENDOR_ID.MAJOR_ID.MINOR_ID'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split('.')[0] or not arg.split('.')[1] or not arg.split('.')[2]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate element type
+ try:
+ vendor_id = int(arg.split('.')[0])
+ major_id = int(arg.split('.')[1])
+ minor_id = int(arg.split('.')[2])
+ except ValueError:
+ msg = "%r must consist of all integers" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ return saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+
+
+def print_notification_header(header_info):
+ """ Print information of the header in the received notification
+
+ Args:
+ header_info (NotificationInfo): NotificationInfo structure containing
+ information of the notification header
+ """
+ dt_format_str = "%c %Z"
+ print ('notificationId = %d\n'
+ 'eventType = %s\n'
+ 'notificationObject = "%s"\n'
+ 'notifyingObject = "%s"\n'
+ 'notificationClassId = %d.%d.%d\n'
+ 'eventTime = %d (%s)\n'
+ 'additionalText = "%s"' %
+ (header_info.notification_id,
+ saNtf.eSaNtfEventTypeT.whatis(header_info.event_type),
+ header_info.notification_object,
+ header_info.notifying_object,
+ header_info.ntf_class_id.vendorId,
+ header_info.ntf_class_id.majorId,
+ header_info.ntf_class_id.minorId,
+ header_info.event_time,
+ satime_to_readable_datetime(header_info.event_time, dt_format_str),
+ header_info.additional_text))
+ if header_info.additional_info:
+ print("numAdditionalInfo = %d" % len(header_info.additional_info))
+ for add_info in header_info.additional_info:
+ print ("- Info ID: %d\n"
+ " Info Type: %s (%d)\n"
+ " Info Value: %s" %
+ (add_info.info_id,
+ saNtf.eSaNtfValueTypeT.whatis(add_info.info_type),
+ add_info.info_type,
+ add_info.info_value))
+ print()
+
+
+def print_alarm_notification(notification):
+ """ Print information of the alarm notification found from reading NTF
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the found alarm notification
+ """
+ print("=== %s - Alarm ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("probableCause = %s" %
+ saNtf.eSaNtfProbableCauseT.whatis(notification.probable_cause))
+ print("perceivedSeverity = %s" %
+ saNtf.eSaNtfSeverityT.whatis(notification.perceived_severity))
+
+ if args.verbose:
+ print("trend = %s" %
+ saNtf.eSaNtfSeverityTrendT.whatis(notification.trend))
+ print("thresholdInformation:\n"
+ "- Threshold ID: %d\n"
+ " Threshold Value Type: %s (%d)\n"
+ " Threshold Value: %s\n"
+ " Threshold Hysteresis: %s\n"
+ " Observed Value: %s\n"
+ " Arm Time: %s" %
+ (notification.threshold_information.threshold_id,
+ saNtf.eSaNtfValueTypeT.whatis(
+ notification.threshold_information.threshold_value_type),
+ notification.threshold_information.threshold_value_type,
+ notification.threshold_information.threshold_value,
+ notification.threshold_information.threshold_hysteresis,
+ notification.threshold_information.observed_value,
+ satime_to_readable_datetime(
+ notification.threshold_information.arm_time)))
+ print("numSpecificProblems = %d" % len(notification.specific_problems))
+ for spec_problem in notification.specific_problems:
+ print("- Problem ID: %d\n"
+ " Problem Class ID: %d.%d.%d\n"
+ " Problem Type: %s (%d)\n"
+ " Problem Value: %s" %
+ (spec_problem.problem_id,
+ spec_problem.problem_class_id.vendorId,
+ spec_problem.problem_class_id.majorId,
+ spec_problem.problem_class_id.minorId,
+ saNtf.eSaNtfValueTypeT.whatis(spec_problem.problem_type),
+ spec_problem.problem_type, spec_problem.problem_value))
+ print("numMonitoredAttributes = %d" %
+ len(notification.monitored_attrs))
+ for monitored_attr in notification.monitored_attrs:
+ print("- Attribute ID: %d\n"
+ " Attribute Type: %s (%d)\n"
+ " Attribute Value: %s" %
+ (monitored_attr.attribute_id,
+ saNtf.eSaNtfValueTypeT.whatis(
+ monitored_attr.attribute_type),
+ monitored_attr.attribute_type,
+ monitored_attr.attribute_value))
+ print("numProposedRepairActions = %d" %
+ len(notification.proposed_repair_actions))
+ for repair_action in notification.proposed_repair_actions:
+ print("- Action ID: %d\n"
+ " Action Value Type: %s (%d)\n"
+ " Action Value: %s" %
+ (repair_action.action_id,
+ saNtf.eSaNtfValueTypeT.whatis(
+ repair_action.action_value_type),
+ repair_action.action_value_type,
+ repair_action.action_value))
+
+
+def print_security_alarm_notification(notification):
+ """ Print information of the security alarm notification found from reading
+ NTF
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the found security alarm notification
+ """
+ print("=== %s - Security Alarm ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("probableCause = %s\n"
+ "severity = %s\n"
+ "Security Alarm Detector Type: %s (%d)\n"
+ "Security Alarm Detector Value: %s\n"
+ "Service User Type: %s (%d)\n"
+ "Service User Value: %s\n"
+ "Service Provider Type: %s (%d)\n"
+ "Service Provider Value: %s" %
+ (saNtf.eSaNtfProbableCauseT.whatis(notification.probable_cause),
+ saNtf.eSaNtfSeverityT.whatis(notification.severity),
+ saNtf.eSaNtfValueTypeT.whatis(
+ notification.security_alarm_detector.value_type),
+ notification.security_alarm_detector.value_type,
+ notification.security_alarm_detector.value,
+ saNtf.eSaNtfValueTypeT.whatis(notification.service_user.value_type),
+ notification.service_user.value_type,
+ notification.service_user.value,
+ saNtf.eSaNtfValueTypeT.whatis(
+ notification.service_provider.value_type),
+ notification.service_provider.value_type,
+ notification.service_provider.value))
+
+
+# Define command line arguments for ntfread
+parser = argparse.ArgumentParser(
+ description='A SAF NTF client used to read alarm and/or security alarm '
+ 'notifications from NTF,\nwhich match optionally provided '
+ 'filter argument(s).\nWithout any argument, all alarm and '
+ 'security alarm notifications will be read by default.',
+ formatter_class=argparse.RawTextHelpFormatter)
+
+parser.add_argument('--alarmOnly', '-a', action='store_true',
+ help='read alarm notifications only')
+parser.add_argument('--securityAlarmOnly', '-y', action='store_true',
+ help='read security alarm notifications only')
+parser.add_argument('--searchMode', '-m', metavar='1...7', type=int,
+ choices=range(1, 8),
+ help='numeric value of SaNtfSearchModeT\n'
+ '(SA_NTF_SEARCH_BEFORE_OR_AT_TIME...'
+ 'SA_NTF_SEARCH_ONLY_FILTER)')
+parser.add_argument('--eventTime', '-T', metavar='TIME', type=int,
+ help='notification time (in nanosecond) to search for')
+parser.add_argument('--notificationId', '-i', metavar='NOTIF_ID', type=int,
+ help='notification id to search for')
+parser.add_argument('--alarmEventTypes', '-e', metavar='16384...16389',
+ type=int, nargs='+', choices=range(16384, 16390),
+ help='numeric value of alarm SaNtfEventTypeT\n'
+ '(SA_NTF_ALARM_NOTIFICATIONS_START...'
+ 'SA_NTF_ALARM_ENVIRONMENT)')
+parser.add_argument('--securityAlarmEventTypes', '-E', metavar='20480...20485',
+ type=int, nargs='+', choices=range(20480, 20486),
+ help='numeric value of security alarm SaNtfEventTypeT\n'
+ '(SA_NTF_SECURITY_ALARM_NOTIFICATIONS_START...'
+ 'SA_NTF_TIME_VIOLATION)')
+parser.add_argument('--notificationClassIds', '-c',
+ type=_validate_ntf_class_id,
+ metavar='VENDOR_ID.MAJOR_ID.MINOR_ID', nargs='+',
+ help='notification class identifier\n'
+ 'VENDOR_ID: SaUint32T integer value\n'
+ 'MAJOR_ID: SaUint16T integer value\n'
+ 'MINOR_ID: SaUint16T integer value')
+parser.add_argument('--notificationObjects', '-n', metavar='NOTIFICATION_OBJ',
+ type=str, nargs='+',
+ help='notification object (string value)')
+parser.add_argument('--notifyingObjects', '-N', metavar='NOTIFYING_OBJ',
+ type=str, nargs='+',
+ help='notifying object (string value)')
+parser.add_argument('--probableCauses', '-p', metavar='0...74',
+ type=int, nargs='+', choices=range(75),
+ help='numeric value of SaNtfProbableCauseT\n'
+ '(SA_NTF_ADAPTER_ERROR...SA_NTF_UNSPECIFIED_REASON)')
+parser.add_argument('--perceivedSeverities', '-s', metavar='0...5', type=int,
+ nargs='+', choices=range(6),
+ help='numeric value of alarm SaNtfSeverityT\n'
+ '(clear=0,ind,warn,min,maj,critical=5)')
+parser.add_argument('--trends', '-t', metavar='0...2', type=int,
+ nargs='+', choices=range(3),
+ help='numeric value of SaNtfSeverityTrendT')
+parser.add_argument('--severities', '-S', metavar='0...5', type=int,
+ nargs='+', choices=range(6),
+ help='numeric value of security alarm SaNtfSeverityT\n'
+ '(clear=0,ind,warn,min,maj,critical=5)')
+parser.add_argument('--searchYounger', '-g', action='store_true',
+ help='SA_NTF_SEARCH_YOUNGER\n'
+ '(search in descending chronological order w.r.t '
+ 'previously read notification)')
+parser.add_argument('--verbose', '-v', action='store_true',
+ help='print all information from alarm notifications')
+
+# Parse command line arguments for user input, if any
+args = parser.parse_args()
+
+notification_type = None
+if args.alarmOnly and args.securityAlarmOnly:
+ print ("ERROR: Cannot use both --alarmOnly and --securityAlarmOnly\n")
+ sys.exit(0)
+elif args.alarmOnly:
+ notification_type = saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM
+elif args.securityAlarmOnly:
+ notification_type = \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM
+
+search_mode = args.searchMode
+event_time = args.eventTime if args.eventTime is not None else 0
+notif_id = args.notificationId if args.notificationId is not None else 0
+
+search_criteria = None
+if search_mode is not None:
+ search_criteria = \
+ saNtf.SaNtfSearchCriteriaT(search_mode, event_time, notif_id)
+
+event_types = args.alarmEventTypes
+if args.securityAlarmEventTypes is not None:
+ if event_types is not None:
+ for evt_type in args.securityAlarmEventTypes:
+ event_types.append(evt_type)
+ else:
+ event_types = args.securityAlarmEventTypes
+
+# Initialize an NTF reader
+reader = NtfReader()
+init_rc = reader.init()
+if init_rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: saNtfInitialize FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(init_rc))
+ sys.exit(1)
+
+# Set notification read filter values, if any, provided by the users
+if search_criteria is not None:
+ reader.set_search_criteria(search_criteria)
+if args.searchYounger:
+ reader.set_search_direction(
+ saNtf.eSaNtfSearchDirectionT.SA_NTF_SEARCH_YOUNGER)
+if event_types is not None:
+ reader.set_filter_event_types(event_types)
+if args.notificationClassIds is not None:
+ reader.set_filter_ntf_class_ids(args.notificationClassIds)
+if args.notificationObjects is not None:
+ reader.set_filter_notification_objects(args.notificationObjects)
+if args.notifyingObjects is not None:
+ reader.set_filter_notifying_objects(args.notifyingObjects)
+if args.probableCauses is not None:
+ reader.set_filter_probable_causes(args.probableCauses)
+if args.perceivedSeverities is not None:
+ reader.set_filter_perceived_severities(args.perceivedSeverities)
+if args.trends is not None:
+ reader.set_filter_trends(args.trends)
+if args.severities is not None:
+ reader.set_filter_severities(args.severities)
+
+# Start reading notifications
+if notification_type is not None:
+ rc = reader.read([notification_type])
+else:
+ rc = reader.read()
+
+if rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: Reading notifications FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(rc))
+ sys.exit(1)
+
+# Print out the found notifications
+for notif_type, notif_info in reader:
+ print()
+ if notif_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+ print_alarm_notification(notif_info)
+ else:
+ print_security_alarm_notification(notif_info)
+ print()
+
+# Finalize the reader
+reader.finalize()
diff --git a/python/samples/ntfsend b/python/samples/ntfsend
old mode 100644
new mode 100755
index c31a9ba..f36cbcd
--- a/python/samples/ntfsend
+++ b/python/samples/ntfsend
@@ -1,251 +1,679 @@
#! /usr/bin/env python
-
+############################################################################
+#
+# (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
+#
+############################################################################
+""" ntfsend tool used to send a type of NTF notification
+
+Run ntfsend --help/-h for more detail on usage
+"""
+from __future__ import print_function
+import sys
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)
+from pyosaf import saNtf
+from pyosaf.saAis import eSaAisErrorT
+from pyosaf.utils.ntf import agent as ntf
+from pyosaf.utils.ntf.producer import NtfProducer
+
+NOTIFICATIONS_TYPE_MASK = saNtf.saNtf.SA_NTF_NOTIFICATIONS_TYPE_MASK
+
+
+class InputValidation(object):
+ """ This class consists of methods to validate different types of input
+ argument for the ntfsend tool
+ """
+ @staticmethod
+ def validate_ntf_class_id(arg):
+ """ Validate the input NtfClassId with format
+ 'VENDOR_ID.MAJOR_ID.MINOR_ID'
+
+ Args:
+ arg (str): The NtfClassId to validate
+
+ Returns:
+ SaNtfClassIdT: The validated NtfClassId
+ """
+ if arg.count('.') != 2:
+ msg = "%r is not in correct format " \
+ "'VENDOR_ID.MAJOR_ID.MINOR_ID'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split('.')[0] or not arg.split('.')[1] \
+ or not arg.split('.')[2]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate element type
+ try:
+ vendor_id = int(arg.split('.')[0])
+ major_id = int(arg.split('.')[1])
+ minor_id = int(arg.split('.')[2])
+ except ValueError:
+ msg = "%r must consist of all integers" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ return saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+
+ @staticmethod
+ def validate_id_type_value(arg):
+ """ Validate the input argument with format 'ID,TYPE,VALUE'
+
+ Args:
+ arg (str): The argument to validate
+
+ Returns:
+ tuple: The validated argument as (ID, TYPE, VALUE)
+ """
+ if arg.count(',') != 2:
+ msg = "%r is not in correct format 'ID,TYPE,VALUE'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split(',')[0] or not arg.split(',')[1] \
+ or not arg.split(',')[2]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate element type
+ try:
+ _id = int(arg.split(',')[0])
+ except ValueError:
+ msg = "%r - ID must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ try:
+ _type = int(arg.split(',')[1])
+ if _type not in saNtf.eSaNtfValueTypeT.reverse_lookup:
+ msg = "%r - TYPE is not a valid SaNtfValueTypeT type" % arg
+ raise argparse.ArgumentTypeError(msg)
+ except ValueError:
+ msg = "%r - TYPE must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ _value = arg.split(',')[2]
+
+ return _id, _type, _value
+
+ @staticmethod
+ def validate_type_value(arg):
+ """ Validate the input argument with format 'TYPE,VALUE'
+
+ Args:
+ arg (str): The argument to validate
+
+ Returns:
+ tuple: The validated argument as (TYPE, VALUE)
+ """
+ if arg.count(',') != 1:
+ msg = "%r is not in correct format 'TYPE,VALUE'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split(',')[0] or not arg.split(',')[1]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate TYPE element
+ try:
+ _type = int(arg.split(',')[0])
+ if _type not in saNtf.eSaNtfValueTypeT.reverse_lookup:
+ msg = "%r - TYPE is not a valid SaNtfValueTypeT type" % arg
+ raise argparse.ArgumentTypeError(msg)
+ except ValueError:
+ msg = "%r - TYPE must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ _value = arg.split(',')[1]
+
+ return _type, _value
+
+ @staticmethod
+ def validate_changed_attribute(arg):
+ """ Validate the input changedAttributes argument with format
+ 'ID,TYPE,OLD_PRESENT,OLD_VAL,NEW_VAL'
+
+ Args:
+ arg (str): The changedAttributes argument to validate
+
+ Returns:
+ tuple: The validated changedAttributes argument as
+ (ID, TYPE, OLD_PRESENT, OLD_VALUE, NEW_VALUE)
+ """
+ if arg.count(',') != 4:
+ msg = "%r is not in correct format " \
+ "'ID,TYPE,OLD_PRESENT,OLD_VAL,NEW_VAL'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split(',')[0] or not arg.split(',')[1] \
+ or not arg.split(',')[2] or not arg.split(',')[4]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate element type
+ try:
+ _id = int(arg.split(',')[0])
+ except ValueError:
+ msg = "%r - ID must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ try:
+ _type = int(arg.split(',')[1])
+ if _type not in saNtf.eSaNtfValueTypeT.reverse_lookup:
+ msg = "%r - TYPE is not a valid SaNtfValueTypeT type" % arg
+ raise argparse.ArgumentTypeError(msg)
+ except ValueError:
+ msg = "%r - TYPE must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ if arg.split(',')[2] not in ['True', 'False']:
+ msg = "%r - OLD_PRESENT must be either 'True' or 'False'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ _old_present = True if arg.split(',')[2] == 'True' else False
+
+ _old_value = arg.split(',')[3]
+ if _old_present and not _old_value:
+ msg = "%r - OLD_VAL is missing for OLD_PRESENT=True" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ _new_value = arg.split(',')[4]
+
+ return _id, _type, _old_present, _old_value, _new_value
+
+ @staticmethod
+ def validate_changed_state(arg):
+ """ Validate the input changedStates argument with format
+ 'ID,OLD_PRESENT,OLD_STATE,NEW_STATE'
+
+ Args:
+ arg (str): The changedStates argument to validate
+
+ Returns:
+ tuple: The validated changedStates argument as
+ (ID, OLD_PRESENT, OLD_STATE, NEW_STATE)
+ """
+ if arg.count(',') != 3:
+ msg = "%r is not in correct format " \
+ "'ID,OLD_PRESENT,OLD_STATE,NEW_STATE'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split(',')[0] or not arg.split(',')[1] \
+ or not arg.split(',')[3]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate element type
+ try:
+ _id = int(arg.split(',')[0])
+ except ValueError:
+ msg = "%r - ID must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ if arg.split(',')[1] not in ['True', 'False']:
+ msg = "%r - OLD_PRESENT must be either 'True' or 'False'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ _old_present = True if arg.split(',')[1] == 'True' else False
+
+ if _old_present:
+ try:
+ if not arg.split(',')[2]:
+ msg = "%r - OLD_STATE is missing for " \
+ "OLD_PRESENT=True" % arg
+ raise argparse.ArgumentTypeError(msg)
+ _old_state = int(arg.split(',')[2])
+ except ValueError:
+ msg = "%r - OLD_STATE must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+ else:
+ _old_state = arg.split(',')[2]
+
+ try:
+ _new_state = int(arg.split(',')[3])
+ except ValueError:
+ msg = "%r - NEW_STATE must be an integer" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ return _id, _old_present, _old_state, _new_state
+
+ @staticmethod
+ def validate_specific_problem(arg):
+ """ Validate the input specificProblems argument with format
+ 'ID,TYPE,VALUE[,VENDOR_ID.MAJOR_ID.MINOR_ID]'
+
+ Args:
+ arg (str): The specificProblems argument to validate
+
+ Returns:
+ tuple: The validated specificProblems argument as
+ (ID, TYPE, VALUE, SaNtfClassIdT) if problemClassId is provided,
+ or (ID, TYPE, VALUE, None) if problemClassId is not provided
+ """
+ if arg.count(',') < 2 or arg.count(',') > 3:
+ msg = "%r is not in correct format " \
+ "'ID,TYPE,VALUE[,VENDOR_ID.MAJOR_ID.MINOR_ID]'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split(',')[0] or not arg.split(',')[1] \
+ or not arg.split(',')[2]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ arg_list = arg.split(',')
+ # Validate the required ID,TYPE,VALUE part
+ required_part = ','.join(arg_list[:3])
+ _id, _type, _value = \
+ InputValidation.validate_id_type_value(required_part)
+
+ # Validate the problemClassId part, if provided
+ if len(arg_list) == 4 and arg_list[3]:
+ _class_id = InputValidation.validate_ntf_class_id(arg_list[3])
+ else:
+ _class_id = None
+
+ return _id, _type, _value, _class_id
+
+ @staticmethod
+ def validate_threshold_information(arg):
+ """ Validate the input thresholdInformation argument with format
+ 'ID,TYPE,THRES_VALUE,HYST,OBSRV_VALUE[,ARM_TIME]'
+
+ Args:
+ arg (str): The thresholdInformation argument to validate
+
+ Returns:
+ tuple: The validated thresholdInformation argument as
+ (ID, TYPE, THRES_VALUE, HYST, OBSRV_VALUE, ARM_TIME) if
+ armTime is provided, or
+ (ID, TYPE, THRES_VALUE, HYST, OBSRV_VALUE, CURRENT_TIME) if
+ armTime is not provided
+ """
+ if arg.count(',') < 4 or arg.count(',') > 5:
+ msg = "%r is not in correct format " \
+ "'ID,TYPE,THRES_VALUE,HYST,OBSRV_VALUE[,ARM_TIME]'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split(',')[0] or not arg.split(',')[1] \
+ or not arg.split(',')[2] or not arg.split(',')[3] \
+ or not arg.split(',')[4]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ arg_list = arg.split(',')
+ # Validate the required ID,TYPE,VALUE part
+ required_part = ','.join(arg_list[:3])
+ _id, _type, _thres_value = \
+ InputValidation.validate_id_type_value(required_part)
+
+ _thres_hyst = arg_list[3]
+ _obsrv_value = arg_list[4]
+
+ if len(arg_list) == 6 and arg_list[5]:
+ _arm_time = arg_list[5]
+ else:
+ _arm_time = int(time.time() * 10**9)
+
+ return _id, _type, _thres_value, _thres_hyst, _obsrv_value, _arm_time
+
+
+def fill_notification_header():
+ """ Fill the notification header with user-provided or default values """
+ producer.set_event_type(event_type)
+ if args.notificationObject is not None:
+ producer.set_notification_object(args.notificationObject)
+ if args.notifyingObject is not None:
+ producer.set_notifying_object(args.notifyingObject)
+ if args.notificationClassId is not None:
+ producer.set_class_id(args.notificationClassId)
+ if args.eventTime is not None:
+ producer.set_event_time(args.eventTime)
+ if args.additionalText is not None:
+ producer.set_additional_text(args.additionalText)
+ if additional_info:
+ producer.set_additional_info(additional_info)
+
+
+def send_notification(notif_type_desc):
+ """ Send notification(s) of a specific type
+
+ Args:
+ notif_type_desc (str): Type of notification to send
+ """
+ ntf_send = {'Object Create/Delete Notification':
+ producer.send_object_create_delete_notification,
+ 'Attribute Change Notification':
+ producer.send_attribute_change_notification,
+ 'State Change Notification':
+ producer.send_state_change_notification,
+ 'Alarm Notification':
+ producer.send_alarm_notification,
+ 'Security Alarm Notification':
+ producer.send_security_alarm_notification}
+
+ repeat_count = 0
+ if args.burstTimeout:
+ print("*** Send burst of %d notifications every %4.3f seconds ***\n" %
+ (args.repeatSends, (args.burstTimeout / 1000000.0)))
+ while True:
+ try:
+ # Send the notification for 'repeatSends' times
+ for _ in range(args.repeatSends):
+ send_rc = ntf_send[notif_type_desc]()
+ if send_rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: ntfsend FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(send_rc))
+ sys.exit(1)
+ repeat_count += 1
+ print("Send %s successfully! send_count=%d" %
+ (notif_type_desc, repeat_count))
+ print()
+ # Keep sending the same notification forever if burstTimeout is set
+ if not args.burstTimeout:
+ break
+ time.sleep(args.burstTimeout / 1000000.0)
+ except KeyboardInterrupt:
+ sys.exit(0)
+
+
+# Define command line arguments for ntfsend
+parser = argparse.ArgumentParser(
+ description='A SAF NTF client used to send notifications.\nWithout any '
+ 'argument, a default alarm notification will be sent.',
+ formatter_class=argparse.RawTextHelpFormatter)
+
+parser.add_argument('--notificationType', '-T', metavar='0x1000...0x5000',
+ default='0x4000', choices=['0x1000', '0x2000', '0x3000',
+ '0x4000', '0x5000'],
+ help='hexadecimal value of SaNtfNotificationTypeT\n'
+ '(obj_create_delete=0x1000,attr_change,state_change,'
+ 'alarm,sec_alarm=0x5000)')
+parser.add_argument('--eventType', '-e', metavar='4096...20485',
+ type=int, default=16384,
+ choices=sorted(saNtf.eSaNtfEventTypeT.reverse_lookup)[:22],
+ help='numeric value of SaNtfEventTypeT\n'
+ '(SA_NTF_OBJECT_NOTIFICATIONS_START...'
+ 'SA_NTF_TIME_VIOLATION)')
+parser.add_argument('--eventTime', '-E', metavar='TIME', type=int,
+ help='numeric value of SaTimeT in nanosecond')
+parser.add_argument('--notificationClassId', '-c',
+ type=InputValidation.validate_ntf_class_id,
+ metavar='VENDOR_ID.MAJOR_ID.MINOR_ID',
+ help='notification class identifier\n'
+ 'VENDOR_ID: SaUint32T integer value\n'
+ 'MAJOR_ID: SaUint16T integer value\n'
+ 'MINOR_ID: SaUint16T integer value')
+parser.add_argument('--notificationObject', '-n', metavar='NOTIFICATION_OBJ',
+ type=str, help='notification object (string value)')
+parser.add_argument('--notifyingObject', '-N', metavar='NOTIFYING_OBJ',
+ type=str, help='notifying object (string value)')
+parser.add_argument('--additionalText', '-a', metavar='TEXT', type=str,
+ help='additional text (string value)')
+parser.add_argument('--additionalInfo', '-i', metavar='ID,TYPE,VALUE',
+ type=InputValidation.validate_id_type_value, nargs='+',
+ help='additional information\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: additional info value')
+parser.add_argument('--sourceIndicator', '-I', metavar='1...3',
+ type=int, choices=range(1, 4),
+ help='numeric value of SaNtfSourceIndicatorT\n'
+ '(SA_NTF_OBJECT_OPERATION...'
+ 'SA_NTF_UNKNOWN_OPERATION)')
+parser.add_argument('--objectAttributes', metavar='ID,TYPE,VALUE',
+ type=InputValidation.validate_id_type_value, nargs='+',
+ help='object create/delete attributes\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: object attribute value')
+parser.add_argument('--changedAttributes',
+ metavar='ID,TYPE,OLD_PRESENT,OLD_VALUE,NEW_VALUE',
+ type=InputValidation.validate_changed_attribute, nargs='+',
+ help='changed attributes of AttributeChange notification\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'OLD_PRESENT: boolean value (True or False)\n'
+ 'OLD_VALUE: old attribute value '
+ '(ignored if OLD_PRESENT=False)\n'
+ 'NEW_VALUE: new attribute value')
+parser.add_argument('--changedStates',
+ metavar='ID,OLD_PRESENT,OLD_STATE,NEW_STATE',
+ type=InputValidation.validate_changed_state, nargs='+',
+ help='changed states of StateChange notification\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'OLD_PRESENT: boolean value (True or False)\n'
+ 'OLD_STATE: SaUint16T integer value '
+ '(ignored if OLD_PRESENT=False)\n'
+ 'NEW_STATE: SaUint16T integer value')
+parser.add_argument('--probableCause', '-p', metavar='0...74',
+ type=int, choices=range(75),
+ help='numeric value of SaNtfProbableCauseT\n'
+ '(SA_NTF_ADAPTER_ERROR...SA_NTF_UNSPECIFIED_REASON)')
+parser.add_argument('--perceivedSeverity', '-s', metavar='0...5',
+ type=int, choices=range(6),
+ help='numeric value of SaNtfSeverityT\n'
+ '(SA_NTF_SEVERITY_CLEARED...'
+ 'SA_NTF_SEVERITY_CRITICAL)')
+parser.add_argument('--trend', '-t', metavar='0...2', type=int,
+ default=1, choices=range(3),
+ help='numeric value of SaNtfSeverityTrendT\n'
+ '(SA_NTF_TREND_MORE_SEVERE...'
+ 'SA_NTF_TREND_LESS_SEVERE)')
+parser.add_argument('--monitoredAttributes', metavar='ID,TYPE,VALUE',
+ type=InputValidation.validate_id_type_value, nargs='+',
+ help='monitored attributes of alarm notification\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: monitored attribute value')
+parser.add_argument('--specificProblems',
+ metavar='ID,TYPE,VALUE[,VENDOR_ID.MAJOR_ID.MINOR_ID]',
+ type=InputValidation.validate_specific_problem, nargs='+',
+ help='specific problems of alarm notification '
+ '(the problemClassId is optional)\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: specific problem value\n'
+ 'VENDOR_ID: SaUint32T integer value\n'
+ 'MAJOR_ID: SaUint16T integer value\n'
+ 'MINOR_ID: SaUint16T integer value')
+parser.add_argument('--thresholdInformation',
+ metavar='ID,TYPE,THRES_VALUE,HYST,OBSRV_VALUE[,ARM_TIME]',
+ type=InputValidation.validate_threshold_information,
+ help='threshold information of alarm notification '
+ '(the armTime is optional)\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'THRES_VALUE: threshold value\n'
+ 'HYST: threshold hysteresis value\n'
+ 'OBSRV_VALUE: observed value\n'
+ 'ARM_TIME: arm time value in nanosecond')
+parser.add_argument('--proposedRepairActions', metavar='ID,TYPE,VALUE',
+ type=InputValidation.validate_id_type_value, nargs='+',
+ help='proposed repair actions of alarm notification\n'
+ 'ID: SaNtfElementIdT integer value\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: proposed repair action value')
+parser.add_argument('--severity', '-S', metavar='1...5',
+ type=int, choices=range(1, 6),
+ help='numeric value of SaNtfSeverityT for security alarm\n'
+ '(SA_NTF_SEVERITY_INDETERMINATE...'
+ 'SA_NTF_SEVERITY_CRITICAL)')
+parser.add_argument('--securityAlarmDetector', metavar='TYPE,VALUE',
+ type=InputValidation.validate_type_value,
+ help='security alarm detector of security alarm '
+ 'notification\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: security alarm detector value')
+parser.add_argument('--serviceUser', metavar='TYPE,VALUE',
+ type=InputValidation.validate_type_value,
+ help='service user of security alarm notification\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: service user value')
+parser.add_argument('--serviceProvider', metavar='TYPE,VALUE',
+ type=InputValidation.validate_type_value,
+ help='service provider of security alarm notification\n'
+ 'TYPE: numeric value of SaNtfValueTypeT\n'
+ 'VALUE: service provider value')
+parser.add_argument('--repeatSends', '-r', metavar='NUM', default=1, type=int,
+ help='send the same notification 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)\n'
+ 'between each burst, will continue forever')
+
+# Parse command line arguments for user input, if any
+# Default values will be used otherwise
+args = parser.parse_args()
+
+notification_type = int(args.notificationType, 0)
+event_type = args.eventType
+if (event_type & NOTIFICATIONS_TYPE_MASK) != notification_type:
+ print("ERROR: Either eventType or notificationType is missing, or they "
+ "do not correspond with each other\n")
+ sys.exit(0)
+
+additional_info = []
+if args.additionalInfo is not None:
+ for add_info in args.additionalInfo:
+ info_id = add_info[0]
+ info_type = add_info[1]
+ info_value = add_info[2]
+ additional_info.append(
+ ntf.AdditionalInfo(info_id, info_type, info_value))
+
+# Initialize an NTF producer
+producer = NtfProducer()
+init_rc = producer.init()
+if init_rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: saNtfInitialize FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(init_rc))
+ sys.exit(1)
+
+# Fill the notification header with user-provided or default values
+fill_notification_header()
+
+if notification_type \
+ == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE:
+ if args.sourceIndicator is not None:
+ producer.set_source_indicator(args.sourceIndicator)
+ if args.objectAttributes is not None:
+ obj_attributes = []
+ for obj_attr in args.objectAttributes:
+ attr_id = obj_attr[0]
+ attr_type = obj_attr[1]
+ attr_value = obj_attr[2]
+ obj_attributes.append(
+ ntf.Attribute(attr_id, attr_type, attr_value))
+ producer.set_object_attributes(obj_attributes)
+ # Send object create/delete notification
+ send_notification("Object Create/Delete Notification")
+
+elif notification_type \
+ == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE:
+ if args.sourceIndicator is not None:
+ producer.set_source_indicator(args.sourceIndicator)
+ if args.changedAttributes is not None:
+ changed_attributes = []
+ for ch_attr in args.changedAttributes:
+ ch_attr_id = ch_attr[0]
+ ch_attr_type = ch_attr[1]
+ old_attr_present = ch_attr[2]
+ old_attr_value = ch_attr[3]
+ new_attr_value = ch_attr[4]
+ changed_attributes.append(
+ ntf.AttributeChange(ch_attr_id, ch_attr_type, new_attr_value,
+ old_attr_present, old_attr_value))
+ producer.set_changed_attributes(changed_attributes)
+ # Send attribute change notification
+ send_notification("Attribute Change Notification")
+
+elif notification_type \
+ == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE:
+ if args.sourceIndicator is not None:
+ producer.set_source_indicator(args.sourceIndicator)
+ if args.changedStates is not None:
+ state_changes = []
+ for ch_state in args.changedStates:
+ state_id = ch_state[0]
+ old_state_present = ch_state[1]
+ old_state = ch_state[2]
+ new_state = ch_state[3]
+ state_changes.append(ntf.StateChange(state_id, new_state,
+ old_state_present, old_state))
+ producer.set_state_changes(state_changes)
+ # Send state change notification
+ send_notification("State Change Notification")
+
+elif notification_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+ if args.probableCause is not None:
+ producer.set_probable_cause(args.probableCause)
+ if args.perceivedSeverity is not None:
+ producer.set_perceived_severity(args.perceivedSeverity)
+ if args.trend is not None:
+ producer.set_trend(args.trend)
+ if args.monitoredAttributes is not None:
+ monitored_attrs = []
+ for mon_attr in args.monitoredAttributes:
+ mon_attr_id = mon_attr[0]
+ mon_attr_type = mon_attr[1]
+ mon_attr_value = mon_attr[2]
+ monitored_attrs.append(
+ ntf.Attribute(mon_attr_id, mon_attr_type, mon_attr_value))
+ producer.set_monitored_attributes(monitored_attrs)
+ if args.specificProblems is not None:
+ specific_problems = []
+ for problem in args.specificProblems:
+ prob_id = problem[0]
+ prob_type = problem[1]
+ prob_value = problem[2]
+ prob_class_id = problem[3]
+ specific_problems.append(
+ ntf.SpecificProblem(prob_id, prob_class_id,
+ prob_type, prob_value))
+ producer.set_specific_problems(specific_problems)
+ if args.thresholdInformation is not None:
+ threshold_id = args.thresholdInformation[0]
+ threshold_type = args.thresholdInformation[1]
+ threshold_value = args.thresholdInformation[2]
+ threshold_hysteresis = args.thresholdInformation[3]
+ observed_value = args.thresholdInformation[4]
+ arm_time = args.thresholdInformation[5]
+ threshold_info = \
+ ntf.ThresholdInformation(threshold_id, threshold_type,
+ threshold_value, threshold_hysteresis,
+ observed_value, arm_time)
+ producer.set_threshold_information(threshold_info)
+ if args.proposedRepairActions is not None:
+ proposed_repair_actions = []
+ for repair_action in args.proposedRepairActions:
+ action_id = repair_action[0]
+ action_type = repair_action[1]
+ action_value = repair_action[2]
+ proposed_repair_actions.append(
+ ntf.ProposedRepairAction(action_id, action_type, action_value))
+ producer.set_proposed_repair_actions(proposed_repair_actions)
+ # Send alarm notification
+ send_notification("Alarm Notification")
+
+elif notification_type \
+ == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM:
+ if args.probableCause is not None:
+ producer.set_probable_cause(args.probableCause)
+ if args.severity is not None:
+ producer.set_severity(args.severity)
+ if args.securityAlarmDetector is not None:
+ sec_alarm_detector = \
+ ntf.SecurityAlarmDetector(args.securityAlarmDetector[1],
+ args.securityAlarmDetector[0])
+ producer.set_security_alarm_detector(sec_alarm_detector)
+ if args.serviceUser is not None:
+ srv_user = ntf.ServiceUser(args.serviceUser[1], args.serviceUser[0])
+ producer.set_service_user(srv_user)
+ if args.serviceProvider is not None:
+ srv_provider = ntf.ServiceProvider(args.serviceProvider[1],
+ args.serviceProvider[0])
+ producer.set_service_provider(srv_provider)
+ # Send security alarm notification
+ send_notification("Security Alarm Notification")
diff --git a/python/samples/ntfsubscribe b/python/samples/ntfsubscribe
old mode 100644
new mode 100755
index b885815..dc78825
--- a/python/samples/ntfsubscribe
+++ b/python/samples/ntfsubscribe
@@ -1,307 +1,522 @@
#! /usr/bin/env python
-
+############################################################################
+#
+# (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
+"""
+ntfsubscribe tool used to subscribe for incoming notifications from NTF
+
+Run ntfsubscribe --help/-h for more detail on usage
+"""
+from __future__ import print_function
+import sys
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,
- header.additionalText[0: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)
+from datetime import datetime, tzinfo, timedelta
+
+from pyosaf import saNtf
+from pyosaf.saAis import eSaAisErrorT, eSaDispatchFlagsT
+from pyosaf.utils.ntf import agent as ntf
+from pyosaf.utils.ntf.subscriber import NtfSubscriber
+
+
+class UTCOffsetTZ(tzinfo):
+ """ Time zone represented as UTC hour-offset """
+ def __init__(self, hour_offset):
+ """ UTCOffsetTZ constructor """
+ self._hour_offset = hour_offset
+ super(UTCOffsetTZ, self).__init__()
+
+ def utcoffset(self, dt):
+ """ Return offset of local time from UTC, in minutes east of UTC """
+ return timedelta(hours=self._hour_offset)
+
+ def dst(self, dt):
+ """ Return the daylight saving time (DST) adjustment, in minutes east
+ of UTC, or None if DST information isn't known
+ """
+ return timedelta(0)
+
+ def tzname(self, dt):
+ """ Return the time zone name represented in UTC hour-offset format as
+ 'UTC+/-offset'
+ """
+ if self._hour_offset > 0:
+ tzname = "UTC+%02d:00" % self._hour_offset
+ elif self._hour_offset < 0:
+ tzname = "UTC-%02d:00" % self._hour_offset
+ else: # hour_offset = 0
+ tzname = "UTC"
+
+ return tzname
+
+
+def satime_to_readable_datetime(sa_time, format_str=None):
+ """ Convert the given SaTimeT time value to readable datetime string
+ representation in ISO 8601 format
+
+ Args:
+ sa_time (SaTimeT): SaTimeT time value
+ format_str (str): Format string for datetime output representation
+
+ Returns:
+ str: Datetime representation in format specified by format_str, or in
+ ISO 8601 format 'YYYY-MM-DDTHH:MM:SS' if format_str not provided
+ """
+ time_sec = sa_time / 10**9 # Convert the time from nsec to sec 1000000000
+
+ # Calculate the UTC offset for time zone information
+ naive_dt = datetime.fromtimestamp(time_sec)
+ utc_offset = (naive_dt - datetime.utcfromtimestamp(time_sec))
+ hour_offset = utc_offset.total_seconds() // 3600
+ utc_offset_tz = UTCOffsetTZ(hour_offset)
+
+ aware_dt = naive_dt.replace(tzinfo=utc_offset_tz)
+
+ if format_str is not None:
+ return aware_dt.strftime(format_str)
+
+ return aware_dt.isoformat(' ')
+
+
+def _validate_ntf_class_id(arg):
+ """ Validate the NtfClassId filter argument with format
+ 'VENDOR_ID.MAJOR_ID.MINOR_ID'
+
+ Args:
+ arg (str): The NtfClassId to validate
+
+ Returns:
+ SaNtfClassIdT: The validated NtfClassId
+ """
+ if arg.count('.') != 2:
+ msg = "%r is not in correct format " \
+ "'VENDOR_ID.MAJOR_ID.MINOR_ID'" % arg
+ raise argparse.ArgumentTypeError(msg)
+ if not arg.split('.')[0] or not arg.split('.')[1] \
+ or not arg.split('.')[2]:
+ msg = "%r does not have enough required values" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ # Validate element type
+ try:
+ vendor_id = int(arg.split('.')[0])
+ major_id = int(arg.split('.')[1])
+ minor_id = int(arg.split('.')[2])
+ except ValueError:
+ msg = "%r must consist of all integers" % arg
+ raise argparse.ArgumentTypeError(msg)
+
+ return saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
+
+
+def print_notification_header(notif_info):
+ """ Print information of the header in the received notification
+
+ Args:
+ notif_info (NotificationInfo): NotificationInfo structure containing
+ information of the notification header
+ """
+ dt_format_str = "%c %Z"
+ print ('notificationId = %d\n'
+ 'eventType = %s\n'
+ 'notificationObject = "%s"\n'
+ 'notifyingObject = "%s"\n'
+ 'notificationClassId = %d.%d.%d\n'
+ 'eventTime = %d (%s)\n'
+ 'additionalText = "%s"' %
+ (notif_info.notification_id,
+ saNtf.eSaNtfEventTypeT.whatis(notif_info.event_type),
+ notif_info.notification_object,
+ notif_info.notifying_object,
+ notif_info.ntf_class_id.vendorId,
+ notif_info.ntf_class_id.majorId,
+ notif_info.ntf_class_id.minorId,
+ notif_info.event_time,
+ satime_to_readable_datetime(notif_info.event_time, dt_format_str),
+ notif_info.additional_text))
+ if notif_info.additional_info:
+ print("numAdditionalInfo = %d" % len(notif_info.additional_info))
+ for add_info in notif_info.additional_info:
+ print ("- Info ID: %d\n"
+ " Info Type: %s (%d)\n"
+ " Info Value: %s" %
+ (add_info.info_id,
+ saNtf.eSaNtfValueTypeT.whatis(add_info.info_type),
+ add_info.info_type,
+ add_info.info_value))
+ print()
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)
+ """ Print information of the received object create/delete notification
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the received object create/delete notification
+ """
+ print("=== %s - Object Create/Delete ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("sourceIndicator = %s" %
+ saNtf.eSaNtfSourceIndicatorT.whatis(notification.source_indicator))
+ print("numAttributes = %d" % len(notification.object_attributes))
+ for obj_attr in notification.object_attributes:
+ print("- Attribute ID: %d\n"
+ " Attribute Type: %s (%d)\n"
+ " Attribute Value: %s" %
+ (obj_attr.attribute_id,
+ saNtf.eSaNtfValueTypeT.whatis(obj_attr.attribute_type),
+ obj_attr.attribute_type, obj_attr.attribute_value))
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)
+ """ Print information of the received attribute change notification
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the received attribute change notification
+ """
+ print("=== %s - Attribute Change ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("sourceIndicator = %s" %
+ saNtf.eSaNtfSourceIndicatorT.whatis(notification.source_indicator))
+ print("numAttributes = %d" % len(notification.changed_attributes))
+ for changed_attr in notification.changed_attributes:
+ print("- Attribute ID: %d\n"
+ " Attribute Type: %s (%d)\n"
+ " Old Attribute Present: %s\n"
+ " New Attribute Value: %s" %
+ (changed_attr.attribute_id,
+ saNtf.eSaNtfValueTypeT.whatis(changed_attr.attribute_type),
+ changed_attr.attribute_type,
+ bool(changed_attr.old_attribute_present),
+ changed_attr.new_attribute_value))
+ if changed_attr.old_attribute_present:
+ print(" Old Attribute Value: %s" %
+ changed_attr.old_attribute_value)
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:
+ """ Print information of the received state change notification
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the received state change notification
+ """
+ print("=== %s - State Change ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("sourceIndicator = %s" %
+ saNtf.eSaNtfSourceIndicatorT.whatis(notification.source_indicator))
+ print("numStateChanges = %d" % len(notification.state_changes))
+ for changed_state in notification.state_changes:
+ print("- State ID: %d\n"
+ " Old State Present: %s\n"
+ " New State: %s" %
+ (changed_state.state_id, bool(changed_state.old_state_present),
+ changed_state.new_state))
+ if changed_state.old_state_present:
+ print(" Old State: %s" % changed_state.old_state)
- 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_alarm_notification(notification):
+ """ Print information of the received alarm notification
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the received alarm notification
+ """
+ print("=== %s - Alarm ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("probableCause = %s" %
+ saNtf.eSaNtfProbableCauseT.whatis(notification.probable_cause))
+ print("perceivedSeverity = %s" %
+ saNtf.eSaNtfSeverityT.whatis(notification.perceived_severity))
+
+ if args.verbose:
+ print("trend = %s" %
+ saNtf.eSaNtfSeverityTrendT.whatis(notification.trend))
+ print("thresholdInformation:\n"
+ "- Threshold ID: %d\n"
+ " Threshold Value Type: %s (%d)\n"
+ " Threshold Value: %s\n"
+ " Threshold Hysteresis: %s\n"
+ " Observed Value: %s\n"
+ " Arm Time: %s" %
+ (notification.threshold_information.threshold_id,
+ saNtf.eSaNtfValueTypeT.whatis(
+ notification.threshold_information.threshold_value_type),
+ notification.threshold_information.threshold_value_type,
+ notification.threshold_information.threshold_value,
+ notification.threshold_information.threshold_hysteresis,
+ notification.threshold_information.observed_value,
+ satime_to_readable_datetime(
+ notification.threshold_information.arm_time)))
+ print("numSpecificProblems = %d" % len(notification.specific_problems))
+ for spec_problem in notification.specific_problems:
+ print("- Problem ID: %d\n"
+ " Problem Class ID: %d.%d.%d\n"
+ " Problem Type: %s (%d)\n"
+ " Problem Value: %s" %
+ (spec_problem.problem_id,
+ spec_problem.problem_class_id.vendorId,
+ spec_problem.problem_class_id.majorId,
+ spec_problem.problem_class_id.minorId,
+ saNtf.eSaNtfValueTypeT.whatis(spec_problem.problem_type),
+ spec_problem.problem_type, spec_problem.problem_value))
+ print("numMonitoredAttributes = %d" %
+ len(notification.monitored_attrs))
+ for monitored_attr in notification.monitored_attrs:
+ print("- Attribute ID: %d\n"
+ " Attribute Type: %s (%d)\n"
+ " Attribute Value: %s" %
+ (monitored_attr.attribute_id,
+ saNtf.eSaNtfValueTypeT.whatis(
+ monitored_attr.attribute_type),
+ monitored_attr.attribute_type,
+ monitored_attr.attribute_value))
+ print("numProposedRepairActions = %d" %
+ len(notification.proposed_repair_actions))
+ for repair_action in notification.proposed_repair_actions:
+ print("- Action ID: %d\n"
+ " Action Value Type: %s (%d)\n"
+ " Action Value: %s" %
+ (repair_action.action_id,
+ saNtf.eSaNtfValueTypeT.whatis(
+ repair_action.action_value_type),
+ repair_action.action_value_type,
+ repair_action.action_value))
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)
+ """ Print information of the received security alarm notification
+
+ Args:
+ notification (NotificationInfo): NotificationInfo structure containing
+ information of the received security alarm notification
+ """
+ print("=== %s - Security Alarm ===" %
+ satime_to_readable_datetime(notification.event_time))
+ print_notification_header(notification)
+ print("probableCause = %s\n"
+ "severity = %s\n"
+ "Security Alarm Detector Type: %s (%d)\n"
+ "Security Alarm Detector Value: %s\n"
+ "Service User Type: %s (%d)\n"
+ "Service User Value: %s\n"
+ "Service Provider Type: %s (%d)\n"
+ "Service Provider Value: %s" %
+ (saNtf.eSaNtfProbableCauseT.whatis(notification.probable_cause),
+ saNtf.eSaNtfSeverityT.whatis(notification.severity),
+ saNtf.eSaNtfValueTypeT.whatis(
+ notification.security_alarm_detector.value_type),
+ notification.security_alarm_detector.value_type,
+ notification.security_alarm_detector.value,
+ saNtf.eSaNtfValueTypeT.whatis(notification.service_user.value_type),
+ notification.service_user.value_type,
+ notification.service_user.value,
+ saNtf.eSaNtfValueTypeT.whatis(
+ notification.service_provider.value_type),
+ notification.service_provider.value_type,
+ notification.service_provider.value))
+
+
+def print_received_notification(subscription_id, notif_type, notif_info):
+ """ Test callback for subscribed notifications, which simply prints
+ information of every received notification
+
+ Args:
+ subscription_id (SaNtfSubscriptionIdT): The subscription id previously
+ provided by the subscriber when subscribing for this type of
+ notification
+ notif_type (SaNtfNotificationTypeT): Type of the received notification
+ notif_info (NotificationInfo): NotificationInfo structure containing
+ information of the received notification
+ """
+ print("\nSubscription ID: %d" % subscription_id)
+ if notif_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE:
+ print_object_create_delete_notification(notif_info)
+ elif notif_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE:
+ print_attribute_change_notification(notif_info)
+ elif notif_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE:
+ print_state_change_notification(notif_info)
+ elif notif_type == saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM:
+ print_alarm_notification(notif_info)
+ elif notif_type == \
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM:
+ print_security_alarm_notification(notif_info)
+ print()
+
+
+# Define command line arguments for ntfsubscribe
+parser = argparse.ArgumentParser(
+ description='A SAF NTF client used to subscribe for incoming '
+ 'notifications matching optionally provided filter '
+ 'argument(s).\nIf not specified, all types of notification '
+ 'will be subscribed to by default.',
+ formatter_class=argparse.RawTextHelpFormatter)
+
+parser.add_argument('--subscriptionId', '-i', metavar='ID', type=int,
+ default=1, help='id for the notification subscription')
+parser.add_argument('--timeout', '-t', metavar='TIME', type=int,
+ help='timeout (sec) to wait for notification')
+parser.add_argument('--verbose', '-v', action='store_true',
+ help='print all information from alarm notifications')
+parser.add_argument('--objectCreateDelete', '-o', action='store_true',
+ help='subscribe for objectCreateDelete notifications only')
+parser.add_argument('--attributeChange', '-c', action='store_true',
+ help='subscribe for attributeChange notifications only')
+parser.add_argument('--stateChange', '-s', action='store_true',
+ help='subscribe for stateChange notifications only')
+parser.add_argument('--alarm', '-a', action='store_true',
+ help='subscribe for alarm notifications only')
+parser.add_argument('--securityAlarm', '-y', action='store_true',
+ help='subscribe for securityAlarm notifications only')
+parser.add_argument('--eventTypes', '-e', metavar='4096...20485',
+ type=int, nargs='+',
+ choices=sorted(saNtf.eSaNtfEventTypeT.reverse_lookup)[:22],
+ help='numeric value of SaNtfEventTypeT\n'
+ '(SA_NTF_OBJECT_NOTIFICATIONS_START...'
+ 'SA_NTF_TIME_VIOLATION)')
+parser.add_argument('--notificationClassIds', '-C',
+ type=_validate_ntf_class_id,
+ metavar='VENDOR_ID.MAJOR_ID.MINOR_ID', nargs='+',
+ help='notification class identifier\n'
+ 'VENDOR_ID: SaUint32T integer value\n'
+ 'MAJOR_ID: SaUint16T integer value\n'
+ 'MINOR_ID: SaUint16T integer value')
+parser.add_argument('--notificationObjects', '-n', metavar='NOTIFICATION_OBJ',
+ type=str, nargs='+',
+ help='notification object (string value)')
+parser.add_argument('--notifyingObjects', '-N', metavar='NOTIFYING_OBJ',
+ type=str, nargs='+',
+ help='notifying object (string value)')
+parser.add_argument('--sourceIndicators', '-I', metavar='1...3',
+ type=int, nargs='+', choices=range(1, 4),
+ help='numeric value of SaNtfSourceIndicatorT\n'
+ '(SA_NTF_OBJECT_OPERATION...'
+ 'SA_NTF_UNKNOWN_OPERATION)')
+parser.add_argument('--changedStateIds', metavar='STATE_ID',
+ type=int, nargs='+',
+ help='changed state id of StateChange notification')
+parser.add_argument('--probableCauses', '-p', metavar='0...74',
+ type=int, nargs='+', choices=range(75),
+ help='numeric value of SaNtfProbableCauseT\n'
+ '(SA_NTF_ADAPTER_ERROR...SA_NTF_UNSPECIFIED_REASON)')
+parser.add_argument('--perceivedSeverities', '-r', metavar='0...5', type=int,
+ nargs='+', choices=range(6),
+ help='numeric value of alarm SaNtfSeverityT\n'
+ '(clear=0,ind,warn,min,maj,critical=5)')
+parser.add_argument('--trends', '-T', metavar='0...2', type=int,
+ nargs='+', choices=range(3),
+ help='numeric value of SaNtfSeverityTrendT')
+parser.add_argument('--severities', '-S', metavar='0...5', type=int,
+ nargs='+', choices=range(6),
+ help='numeric value of security alarm SaNtfSeverityT\n'
+ '(clear=0,ind,warn,min,maj,critical=5)')
+
+# Parse command line arguments for user input, if any
+# Default values will be used otherwise
+args = parser.parse_args()
+
+notif_type_subscriptions = []
+
+if args.objectCreateDelete:
+ notif_type_subscriptions.append(
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_OBJECT_CREATE_DELETE)
+if args.attributeChange:
+ notif_type_subscriptions.append(
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ATTRIBUTE_CHANGE)
+if args.stateChange:
+ notif_type_subscriptions.append(
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_STATE_CHANGE)
+if args.alarm:
+ notif_type_subscriptions.append(
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_ALARM)
+if args.securityAlarm:
+ notif_type_subscriptions.append(
+ saNtf.eSaNtfNotificationTypeT.SA_NTF_TYPE_SECURITY_ALARM)
+
+# Initialize an NTF subscriber
+subscriber = NtfSubscriber()
+rc = subscriber.init(print_received_notification)
+if rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: saNtfInitialize FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(rc))
+ sys.exit(1)
+
+# Set notification subscribe filter values, if any, provided by the users
+if args.eventTypes is not None:
+ subscriber.set_filter_event_types(args.eventTypes)
+if args.notificationClassIds is not None:
+ subscriber.set_filter_ntf_class_ids(args.notificationClassIds)
+if args.notificationObjects is not None:
+ subscriber.set_filter_notification_objects(args.notificationObjects)
+if args.notifyingObjects is not None:
+ subscriber.set_filter_notifying_objects(args.notifyingObjects)
+if args.sourceIndicators is not None:
+ subscriber.set_filter_source_indicators(args.sourceIndicators)
+if args.changedStateIds is not None:
+ state_changes = []
+ for state_id in args.changedStateIds:
+ state_changes.append(ntf.StateChange(state_id, 0, False, 0))
+ subscriber.set_filter_changed_states(state_changes)
+if args.probableCauses is not None:
+ subscriber.set_filter_probable_causes(args.probableCauses)
+if args.perceivedSeverities is not None:
+ subscriber.set_filter_perceived_severities(args.perceivedSeverities)
+if args.trends is not None:
+ subscriber.set_filter_trends(args.trends)
+if args.severities is not None:
+ subscriber.set_filter_severities(args.severities)
+
+# Subscribe for user-specified notification types or all types by default
+if notif_type_subscriptions:
+ rc = subscriber.subscribe(args.subscriptionId, notif_type_subscriptions)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: saNtfNotificationSubscribe FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(rc))
+ sys.exit(1)
+else:
+ rc = subscriber.subscribe(args.subscriptionId)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: saNtfNotificationSubscribe FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(rc))
+ sys.exit(1)
+
+# Obtain the subscriber selection object to poll for incoming notifications
+select_obj = subscriber.get_selection_object().value
+
+# Poll forever for notifications unless a timeout is specified
+while True:
+ try:
+ read_evt, _, _ = select.select([select_obj], [], [], args.timeout)
+ if select_obj in read_evt:
+ rc = subscriber.dispatch(eSaDispatchFlagsT.SA_DISPATCH_ALL)
+ if rc != eSaAisErrorT.SA_AIS_OK:
+ print("ERROR: saNtfDispatch FAILED, rc = %s\n" %
+ eSaAisErrorT.whatis(rc))
+ sys.exit(1)
+ elif not read_evt:
+ print("Poll timeout!")
+ sys.exit(1)
+ except KeyboardInterrupt:
+ sys.exit(0)