c8159ea6cb
Create fault management REST API service Create fault management client and CLI shell Add a python extension for fault management application APIs Update fault management python APIs to use the python extension Update fault manager to retrieve the SNMP configuration from the config file Story: 2002828 Task: 22747 Depends-On: https://review.openstack.org/#/c/592176/ Change-Id: I888d8d23edf75d05d51594ccca55570ae366c848 Signed-off-by: Tao Liu <tao.liu@windriver.com>
225 lines
8.3 KiB
Python
Executable File
225 lines
8.3 KiB
Python
Executable File
#
|
|
# Copyright (c) 2013-2018 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
# -*- encoding: utf-8 -*-
|
|
#
|
|
#
|
|
# Author:
|
|
#
|
|
|
|
import copy
|
|
from . import constants
|
|
import six
|
|
import fm_core
|
|
|
|
|
|
class ClientException(Exception):
|
|
pass
|
|
|
|
|
|
# Fields explanation:
|
|
#
|
|
# alarm_id: a text string of the alarm identifier
|
|
# alarm_state: see ALARM_STATE
|
|
# entity_type_id: type of the object raising alarm.
|
|
# entity_instance_id: instance information of the object raising alarm.
|
|
# severity: see ALARM_SEVERITY
|
|
# reason_text: free-format string providing description and additional details
|
|
# on the alarm. Optional.
|
|
# alarm_type: see ALARM_TYPE
|
|
# probable_cause: see ALARM_PROBABLE_CAUSE
|
|
# proposed_repair_action:free-format string providing additional details on
|
|
# how to clear the alarm. Optional.
|
|
# service_affecting: true/false, default to false
|
|
# suppression: true/false (allowed/not-allowed), default to false
|
|
# uuid: unique identifier of an active alarm instance, filled by FM system
|
|
# Timestamp: when the alarm has been raised/updated, filled by FM system
|
|
# See CGCS FM Guide for the alarm model specification
|
|
class Fault(object):
|
|
|
|
def __init__(self, alarm_id, alarm_state, entity_type_id,
|
|
entity_instance_id, severity, reason_text,
|
|
alarm_type, probable_cause, proposed_repair_action,
|
|
service_affecting=False, suppression=False,
|
|
uuid=None, timestamp=None):
|
|
self.alarm_id = alarm_id
|
|
self.alarm_state = alarm_state
|
|
self.entity_type_id = self._unicode(entity_type_id)
|
|
self.entity_instance_id = self._unicode(entity_instance_id)
|
|
self.severity = severity
|
|
self.reason_text = self._unicode(reason_text)
|
|
self.alarm_type = alarm_type
|
|
self.probable_cause = probable_cause
|
|
self.proposed_repair_action = self._unicode(proposed_repair_action)
|
|
self.service_affecting = service_affecting
|
|
self.suppression = suppression
|
|
self.uuid = uuid
|
|
self.timestamp = timestamp
|
|
|
|
def as_dict(self):
|
|
return copy.copy(self.__dict__)
|
|
|
|
@staticmethod
|
|
def _unicode(value):
|
|
if isinstance(value, str):
|
|
return six.text_type(value.decode('utf-8'))
|
|
else:
|
|
return value
|
|
|
|
|
|
class FaultAPIs(object):
|
|
|
|
def set_fault(self, data):
|
|
self._check_required_attributes(data)
|
|
self._validate_attributes(data)
|
|
buff = self._alarm_to_str(data)
|
|
try:
|
|
return fm_core.set(buff)
|
|
except (RuntimeError, SystemError, TypeError):
|
|
return None
|
|
|
|
def clear_fault(self, alarm_id, entity_instance_id):
|
|
sep = constants.FM_CLIENT_STR_SEP
|
|
buff = (sep + self._check_val(alarm_id) + sep +
|
|
self._check_val(entity_instance_id) + sep)
|
|
try:
|
|
return fm_core.clear(buff)
|
|
except (RuntimeError, SystemError, TypeError):
|
|
return False
|
|
|
|
def get_fault(self, alarm_id, entity_instance_id):
|
|
sep = constants.FM_CLIENT_STR_SEP
|
|
buff = (sep + self._check_val(alarm_id) + sep +
|
|
self._check_val(entity_instance_id) + sep)
|
|
try:
|
|
resp = fm_core.get(buff)
|
|
return self._str_to_alarm(resp) if resp else None
|
|
except (RuntimeError, SystemError, TypeError):
|
|
return None
|
|
|
|
def clear_all(self, entity_instance_id):
|
|
try:
|
|
return fm_core.clear_all(entity_instance_id)
|
|
except (RuntimeError, SystemError, TypeError):
|
|
return False
|
|
|
|
def get_faults(self, entity_instance_id):
|
|
try:
|
|
resp = fm_core.get_by_eid(entity_instance_id)
|
|
if resp is not None:
|
|
data = []
|
|
for i in resp:
|
|
data.append(self._str_to_alarm(i))
|
|
return data
|
|
except (RuntimeError, SystemError, TypeError):
|
|
pass
|
|
return None
|
|
|
|
def get_faults_by_id(self, alarm_id):
|
|
try:
|
|
resp = fm_core.get_by_aid(alarm_id)
|
|
if resp is not None:
|
|
data = []
|
|
for i in resp:
|
|
data.append(self._str_to_alarm(i))
|
|
return data
|
|
except (RuntimeError, SystemError, TypeError):
|
|
pass
|
|
return None
|
|
|
|
@staticmethod
|
|
def _check_val(data):
|
|
if data is None:
|
|
return " "
|
|
else:
|
|
return data
|
|
|
|
def _alarm_to_str(self, data):
|
|
sep = constants.FM_CLIENT_STR_SEP
|
|
return (sep + self._check_val(data.uuid) + sep + data.alarm_id + sep +
|
|
data.alarm_state + sep + data.entity_type_id + sep +
|
|
data.entity_instance_id + sep +
|
|
self._check_val(data.timestamp) +
|
|
sep + data.severity + sep + self._check_val(data.reason_text) +
|
|
sep + data.alarm_type + sep + data.probable_cause + sep +
|
|
self._check_val(data.proposed_repair_action) + sep +
|
|
str(data.service_affecting) + sep + str(data.suppression) + sep)
|
|
|
|
@staticmethod
|
|
def _str_to_alarm(alarm_str):
|
|
line = alarm_str.split(constants.FM_CLIENT_STR_SEP)
|
|
if len(line) < constants.MAX_ALARM_ATTRIBUTES:
|
|
return None
|
|
else:
|
|
data = Fault(line[constants.FM_ALARM_ID_INDEX],
|
|
line[constants.FM_ALARM_STATE_INDEX],
|
|
line[constants.FM_ENT_TYPE_ID_INDEX],
|
|
line[constants.FM_ENT_INST_ID_INDEX],
|
|
line[constants.FM_SEVERITY_INDEX],
|
|
line[constants.FM_REASON_TEXT_INDEX],
|
|
line[constants.FM_ALARM_TYPE_INDEX],
|
|
line[constants.FM_CAUSE_INDEX],
|
|
line[constants.FM_REPAIR_ACTION_INDEX],
|
|
line[constants.FM_SERVICE_AFFECTING_INDEX],
|
|
line[constants.FM_SUPPRESSION_INDEX],
|
|
line[constants.FM_UUID_INDEX],
|
|
line[constants.FM_TIMESTAMP_INDEX])
|
|
return data
|
|
|
|
@staticmethod
|
|
def _check_required_attributes(data):
|
|
if data.alarm_id is None:
|
|
raise ClientException("Alarm id is is required.")
|
|
if data.alarm_state is None:
|
|
raise ClientException("Alarm state is required.")
|
|
if data.severity is None:
|
|
raise ClientException("Severity is required.")
|
|
if data.alarm_type is None:
|
|
raise ClientException("Alarm type is required.")
|
|
if data.probable_cause is None:
|
|
raise ClientException("Probable Cause is required.")
|
|
if data.entity_type_id is None:
|
|
raise ClientException("Entity type id is required.")
|
|
if data.entity_instance_id is None:
|
|
raise ClientException("Entity instance id is required.")
|
|
|
|
@staticmethod
|
|
def _validate_attributes(data):
|
|
""" Validate the attributes
|
|
only applies to Telco specific attributes"""
|
|
if data.alarm_state not in constants.ALARM_STATE:
|
|
raise ClientException("Invalid Fault State: %s" %
|
|
data.alarm_state)
|
|
if data.severity not in constants.ALARM_SEVERITY:
|
|
raise ClientException("Invalid Fault Severity: %s" %
|
|
data.severity)
|
|
if data.alarm_type not in constants.ALARM_TYPE:
|
|
raise ClientException("Invalid Fault Type: %s" %
|
|
data.alarm_type)
|
|
if data.probable_cause not in constants.ALARM_PROBABLE_CAUSE:
|
|
raise ClientException("Invalid Fault Probable Cause: %s" %
|
|
data.probable_cause)
|
|
|
|
@staticmethod
|
|
def alarm_allowed(alarm_severity, threshold):
|
|
def severity_to_int(severity):
|
|
if severity == 'none':
|
|
return 5
|
|
elif severity == constants.FM_ALARM_SEVERITY_CRITICAL:
|
|
return 4
|
|
elif severity == constants.FM_ALARM_SEVERITY_MAJOR:
|
|
return 3
|
|
elif severity == constants.FM_ALARM_SEVERITY_MINOR:
|
|
return 2
|
|
elif severity == constants.FM_ALARM_SEVERITY_WARNING:
|
|
return 1
|
|
|
|
given = severity_to_int(alarm_severity)
|
|
threshold = severity_to_int(threshold)
|
|
if given < threshold:
|
|
return True
|
|
return False
|