From 656f8f0ba5631a2f7880ff2a40dbc6e717bb4093 Mon Sep 17 00:00:00 2001 From: sushanthakumar Date: Thu, 25 Jun 2020 01:50:40 +0530 Subject: [PATCH 1/2] Oceanstore alert model filling --- delfin/alert_manager/alert_processor.py | 4 +- delfin/alert_manager/trap_receiver.py | 3 +- .../drivers/huawei/oceanstor/alert_handler.py | 110 ++++++++++++++++ .../huawei/oceanstor/test_alert_handler.py | 119 ++++++++++++++++++ 4 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 delfin/drivers/huawei/oceanstor/alert_handler.py create mode 100644 delfin/tests/unit/drivers/huawei/oceanstor/test_alert_handler.py diff --git a/delfin/alert_manager/alert_processor.py b/delfin/alert_manager/alert_processor.py index 9b947696e..2f88d04b3 100644 --- a/delfin/alert_manager/alert_processor.py +++ b/delfin/alert_manager/alert_processor.py @@ -30,8 +30,8 @@ def __init__(self): def process_alert_info(self, alert): """Fills alert model using driver manager interface.""" - storage = db.storage_get(context, alert['storage_id']) - + ctxt = context.RequestContext() + storage = db.storage_get(ctxt, alert['storage_id']) # Fill storage specific info alert['storage_name'] = storage['name'] alert['vendor'] = storage['vendor'] diff --git a/delfin/alert_manager/trap_receiver.py b/delfin/alert_manager/trap_receiver.py index 5411fbb24..acb001d4f 100644 --- a/delfin/alert_manager/trap_receiver.py +++ b/delfin/alert_manager/trap_receiver.py @@ -34,7 +34,8 @@ # Currently static mib file list is loaded # Mechanism to be changed to load all mib file -MIB_LOAD_LIST = ['SNMPv2-MIB', 'IF_MIB', 'EMCGATEWAY-MIB', 'FCMGMT-MIB'] +MIB_LOAD_LIST = ['SNMPv2-MIB', 'IF_MIB', 'EMCGATEWAY-MIB', 'FCMGMT-MIB', + 'ISM-HUAWEI-MIB'] AUTH_PROTOCOL_MAP = {"sha": config.usmHMACSHAAuthProtocol, "md5": config.usmHMACMD5AuthProtocol} diff --git a/delfin/drivers/huawei/oceanstor/alert_handler.py b/delfin/drivers/huawei/oceanstor/alert_handler.py new file mode 100644 index 000000000..9403b3fbd --- /dev/null +++ b/delfin/drivers/huawei/oceanstor/alert_handler.py @@ -0,0 +1,110 @@ +# Copyright 2020 The SODA Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from oslo_log import log + +from delfin import exception +from delfin.i18n import _ + +LOG = log.getLogger(__name__) + + +class AlertHandler(object): + """Alert handling functions for huawei oceanstor driver""" + default_me_category = 'storage-subsystem' + + def __init__(self): + pass + + """ + Alert model contains below fields + category : Type of the reported notification + occur_time : Time of occurrence of alert. When trap does not contain it, + it will be filled with receive time + match_key : This info uniquely identifies the fault point. Several infos + such as source system id, location, alarm id together can be + used to construct this + me_dn : Unique id at resource module (management system) side. me stands + for management element here + me_name : Unique name at resource module (management system) side + native_me_dn : Unique id of the device at source system that reports the + alarm + location : Alarm location information. It helps to locate the lowest unit + where fault is originated(Name-value pairs) + ex: Location = subtrack, No = 1, Slot No = 5. + shelf Id = 1, board type = ADSL + event_type : Basic classification of the alarm. Probable values such as + status, configuration, topology .... + alarm_id : Identification of alarm + alarm_name : Name of the alarm, might need translation from alarm id + severity : Severity of alarm. Helps admin to decide on action to be taken + Probable values: Critical, Major, Minor, Warning, Info + device_alert_sn : Sequence number of alert generated. This will be helpful + during alert clearing process + manufacturer : Vendor of the device + Product_name : Name of the product + probable_cause : Probable reason for alert generation + clear_type : Alarm clearance type such as manual, automatic, reset clear + me_category : Resource category of the device generating the alarm + Probable value: Network,Server,Storage.. + """ + + def parse_alert(self, context, alert): + """Parse alert data got from alert manager and fill the alert model.""" + + try: + alert_model = {} + # These information are sourced from device registration info + alert_model['me_dn'] = alert['storage_id'] + alert_model['me_name'] = alert['storage_name'] + alert_model['manufacturer'] = alert['vendor'] + alert_model['product_name'] = alert['model'] + + # Fill default values for alert attributes + alert_model['category'] = alert['hwIsmReportingAlarmFaultCategory'] + alert_model['location'] = alert['hwIsmReportingAlarmLocationInfo'] + alert_model['event_type'] = alert['hwIsmReportingAlarmFaultType'] + alert_model['severity'] = alert['hwIsmReportingAlarmFaultLevel'] + alert_model['probable_cause'] \ + = alert['hwIsmReportingAlarmAdditionInfo'] + alert_model['me_category'] = self.default_me_category + alert_model['occur_time'] = alert['hwIsmReportingAlarmFaultTime'] + alert_model['alarm_id'] = alert['hwIsmReportingAlarmAlarmID'] + alert_model['alarm_name'] = alert['hwIsmReportingAlarmFaultTitle'] + alert_model['device_alert_sn'] = \ + alert['hwIsmReportingAlarmSerialNo'] + + # Trap info does not have clear_type + # Below fields filling to be updated + alert_model['clear_type'] = "" + alert_model['match_key'] = "" + alert_model['native_me_dn'] = "" + return alert_model + except Exception: + msg = (_("Failed to build alert model as some attributes missing " + "in alert message.")) + raise exception.InvalidResults(msg) + + def add_trap_config(self, context, storage_id, trap_config): + """Config the trap receiver in storage system.""" + pass + + def remove_trap_config(self, context, storage_id, trap_config): + """Remove trap receiver configuration from storage system.""" + pass + + def clear_alert(self, context, storage_id, alert): + """Clear alert from storage system.""" + pass diff --git a/delfin/tests/unit/drivers/huawei/oceanstor/test_alert_handler.py b/delfin/tests/unit/drivers/huawei/oceanstor/test_alert_handler.py new file mode 100644 index 000000000..4cfd4520e --- /dev/null +++ b/delfin/tests/unit/drivers/huawei/oceanstor/test_alert_handler.py @@ -0,0 +1,119 @@ +# Copyright 2020 The SODA Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from oslo_utils import importutils + +from delfin import exception + + +class AlertHandlerTestCase(unittest.TestCase): + ALERT_HANDLER_CLASS = 'delfin.drivers.huawei.oceanstor.alert_handler' \ + '.AlertHandler' + + def _get_alert_handler(self): + alert_handler_class = importutils.import_class( + self.ALERT_HANDLER_CLASS) + alert_handler = alert_handler_class() + return alert_handler + + def _get_fake_alert_info(self): + alert_info = {'storage_id': 'abcd-1234-56789', + 'storage_name': 'storage1', 'vendor': 'fake vendor', + 'model': 'fake model', + 'hwIsmReportingAlarmLocationInfo': 'location1', + 'hwIsmReportingAlarmFaultTitle': 'Trap Test Alarm', + 'hwIsmReportingAlarmFaultType': 'equipmentFault', + 'hwIsmReportingAlarmFaultLevel': 'criticalAlarm', + 'hwIsmReportingAlarmAlarmID': '4294967294', + 'hwIsmReportingAlarmSerialNo': '4294967295', + 'hwIsmReportingAlarmAdditionInfo': 'This is just for ' + 'testing.Please ' + 'ignore it', + 'hwIsmReportingAlarmFaultCategory': 'faultAlarm', + 'hwIsmReportingAlarmLocationAlarmID': '230584300921369', + 'hwIsmReportingAlarmFaultTime': '2020-6-25,1:42:26.0'} + + return alert_info + + def _get_fake_incomplete_alert_info(self): + + # hwIsmReportingAlarmFaultCategory is missing here + alert_info = {'storage_id': 'abcd-1234-56789', + 'storage_name': 'storage1', 'vendor': 'fake vendor', + 'model': 'fake model', + 'hwIsmReportingAlarmLocationInfo': 'location1', + 'hwIsmReportingAlarmFaultTitle': 'Trap Test Alarm', + 'hwIsmReportingAlarmFaultType': 'equipmentFault', + 'hwIsmReportingAlarmFaultLevel': 'criticalAlarm', + 'hwIsmReportingAlarmAlarmID': '4294967294', + 'hwIsmReportingAlarmSerialNo': '4294967295', + 'hwIsmReportingAlarmAdditionInfo': 'This is just for ' + 'testing.Please ' + 'ignore it', + 'hwIsmReportingAlarmLocationAlarmID': '230584300921369', + 'hwIsmReportingAlarmFaultTime': '2020-6-25,1:42:26.0'} + + return alert_info + + def test_parse_alert_with_all_necessary_info(self): + """ Success flow with all necessary parameters""" + alert_handler_inst = self._get_alert_handler() + alert = self._get_fake_alert_info() + + expected_alert_model = {'me_dn': alert['storage_id'], + 'me_name': alert['storage_name'], + 'manufacturer': alert['vendor'], + 'product_name': alert['model'], + 'category': + alert['hwIsmReportingAlarmFaultCategory'], + 'location': + alert['hwIsmReportingAlarmLocationInfo'], + 'event_type': + alert['hwIsmReportingAlarmFaultType'], + 'severity': + alert['hwIsmReportingAlarmFaultLevel'], + 'probable_cause': + alert['hwIsmReportingAlarmAdditionInfo'], + 'me_category': 'storage-subsystem', + 'alarm_id': + alert['hwIsmReportingAlarmAlarmID'], + 'alarm_name': + alert['hwIsmReportingAlarmFaultTitle'], + 'device_alert_sn': + alert['hwIsmReportingAlarmSerialNo'], + 'occur_time': + alert['hwIsmReportingAlarmFaultTime'], + 'clear_type': '', + 'match_key': '', + 'native_me_dn': '' + } + context = {} + alert_model = alert_handler_inst.parse_alert(context, alert) + + # Verify that all other fields are matching + self.assertDictEqual(expected_alert_model, alert_model) + + def test_parse_alert_without_mandatory_info(self): + """ Error flow with some mandatory parameters missing""" + alert_handler_inst = self._get_alert_handler() + context = {} + alert = self._get_fake_incomplete_alert_info() + self.assertRaisesRegex(exception.InvalidResults, + "Failed to build alert " + "model as some " + "attributes missing in " + "alert message", + alert_handler_inst.parse_alert, context, alert) From 8d35194d95d054c88f21146a7c731cd2955d63d8 Mon Sep 17 00:00:00 2001 From: sushanthakumar Date: Thu, 25 Jun 2020 15:30:55 +0530 Subject: [PATCH 2/2] Review comment fix --- delfin/drivers/huawei/oceanstor/alert_handler.py | 9 +++++---- delfin/drivers/huawei/oceanstor/oceanstor.py | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/delfin/drivers/huawei/oceanstor/alert_handler.py b/delfin/drivers/huawei/oceanstor/alert_handler.py index 9403b3fbd..8c5e628b4 100644 --- a/delfin/drivers/huawei/oceanstor/alert_handler.py +++ b/delfin/drivers/huawei/oceanstor/alert_handler.py @@ -85,26 +85,27 @@ def parse_alert(self, context, alert): alert_model['alarm_name'] = alert['hwIsmReportingAlarmFaultTitle'] alert_model['device_alert_sn'] = \ alert['hwIsmReportingAlarmSerialNo'] - - # Trap info does not have clear_type - # Below fields filling to be updated alert_model['clear_type'] = "" alert_model['match_key'] = "" alert_model['native_me_dn'] = "" return alert_model - except Exception: + except Exception as e: + LOG.error(e) msg = (_("Failed to build alert model as some attributes missing " "in alert message.")) raise exception.InvalidResults(msg) def add_trap_config(self, context, storage_id, trap_config): """Config the trap receiver in storage system.""" + # Currently not implemented pass def remove_trap_config(self, context, storage_id, trap_config): """Remove trap receiver configuration from storage system.""" + # Currently not implemented pass def clear_alert(self, context, storage_id, alert): + # Currently not implemented """Clear alert from storage system.""" pass diff --git a/delfin/drivers/huawei/oceanstor/oceanstor.py b/delfin/drivers/huawei/oceanstor/oceanstor.py index 3d1004639..651a07a0e 100644 --- a/delfin/drivers/huawei/oceanstor/oceanstor.py +++ b/delfin/drivers/huawei/oceanstor/oceanstor.py @@ -14,7 +14,7 @@ from oslo_log import log from delfin.common import constants -from delfin.drivers.huawei.oceanstor import rest_client, consts +from delfin.drivers.huawei.oceanstor import rest_client, consts, alert_handler from delfin.drivers import driver from delfin import exception @@ -179,7 +179,7 @@ def remove_trap_config(self, context, trap_config): pass def parse_alert(self, context, alert): - pass + return alert_handler.AlertHandler().parse_alert(context, alert) def clear_alert(self, context, alert): pass