42a9cfa882
flake8 2.5.5 fails on ubuntu-focal zuul machines running python3.8 with the following error: AttributeError: 'FlakesChecker' object has no attribute 'CONSTANT' Fixed: E117 over-indented E741 ambiguous variable name F841 local variable is assigned to but never used Per-Line-Suppressed: E402 module level import not at top of file F632 use ==/!= to compare constant literals Global Suppress: W504 line break after binary operator W605 invalid escape sequence The suppressed errors can be fixed by later submissions. Change-Id: I2df3ece427f0c84ce16c1a82f4d9f0c9a5a6982b Partial-Bug: 1895054 Signed-off-by: albailey <Al.Bailey@windriver.com>
360 lines
13 KiB
Python
Executable File
360 lines
13 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 # pylint: disable=import-error
|
|
import threading
|
|
|
|
fm_api_lock = threading.Lock()
|
|
|
|
|
|
class ClientException(Exception):
|
|
pass
|
|
|
|
|
|
class APIException(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 six.PY2 and isinstance(value, str):
|
|
return six.text_type(value.decode('utf-8'))
|
|
else:
|
|
return value
|
|
|
|
|
|
class FaultAPIsBase(object):
|
|
@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
|
|
|
|
|
|
class FaultAPIs(FaultAPIsBase):
|
|
|
|
def set_fault(self, data):
|
|
with fm_api_lock:
|
|
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):
|
|
with fm_api_lock:
|
|
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.clear(buff)
|
|
# resp may be True/False/None after FaultAPIsV2
|
|
# implementation.
|
|
# To keep FaultAPIs the same as before,
|
|
# return False for None case.
|
|
if resp is True:
|
|
return True
|
|
else:
|
|
return False
|
|
except (RuntimeError, SystemError, TypeError):
|
|
return False
|
|
|
|
def get_fault(self, alarm_id, entity_instance_id):
|
|
with fm_api_lock:
|
|
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)
|
|
if resp:
|
|
return self._str_to_alarm(resp)
|
|
except (RuntimeError, SystemError, TypeError):
|
|
pass
|
|
return None
|
|
|
|
def clear_all(self, entity_instance_id):
|
|
with fm_api_lock:
|
|
try:
|
|
resp = fm_core.clear_all(entity_instance_id)
|
|
# resp may be True/False/None after FaultAPIsV2
|
|
# implementation.
|
|
# To keep FaultAPIs the same as before,
|
|
# return False for None case.
|
|
if resp is True:
|
|
return True
|
|
else:
|
|
return False
|
|
except (RuntimeError, SystemError, TypeError):
|
|
return False
|
|
|
|
def get_faults(self, entity_instance_id):
|
|
with fm_api_lock:
|
|
try:
|
|
resp = fm_core.get_by_eid(entity_instance_id)
|
|
if resp:
|
|
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):
|
|
with fm_api_lock:
|
|
try:
|
|
resp = fm_core.get_by_aid(alarm_id)
|
|
if resp:
|
|
data = []
|
|
for i in resp:
|
|
data.append(self._str_to_alarm(i))
|
|
return data
|
|
except (RuntimeError, SystemError, TypeError):
|
|
pass
|
|
return None
|
|
|
|
|
|
class FaultAPIsV2(FaultAPIsBase):
|
|
|
|
# Input: alarm data
|
|
# Return: Success: uuid for the alarm
|
|
# Exception: 1. Input Alarm format is not valid
|
|
# 2. When there is operation failure
|
|
def set_fault(self, data):
|
|
with fm_api_lock:
|
|
self._check_required_attributes(data)
|
|
self._validate_attributes(data)
|
|
buff = self._alarm_to_str(data)
|
|
uuid = fm_core.set(buff)
|
|
if uuid is None:
|
|
raise APIException("Failed to execute set_fault.")
|
|
return uuid
|
|
|
|
# Input: alarm_id, entity_instance_id
|
|
# Return: Success: True
|
|
# Alarm doesn't exist: False
|
|
# Exception: When there is operation failure
|
|
def clear_fault(self, alarm_id, entity_instance_id):
|
|
with fm_api_lock:
|
|
sep = constants.FM_CLIENT_STR_SEP
|
|
buff = (sep + self._check_val(alarm_id) + sep +
|
|
self._check_val(entity_instance_id) + sep)
|
|
resp = fm_core.clear(buff)
|
|
if resp is False:
|
|
# There is operation failure
|
|
raise APIException("Failed to execute clear_fault.")
|
|
elif resp is None:
|
|
# alarm is not found
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
# Input: alarm_id, entity_instance_id
|
|
# Return: Success: Alarm
|
|
# Alarm doesn't exist: None
|
|
# Exception: When there is operation failure
|
|
def get_fault(self, alarm_id, entity_instance_id):
|
|
with fm_api_lock:
|
|
sep = constants.FM_CLIENT_STR_SEP
|
|
buff = (sep + self._check_val(alarm_id) + sep +
|
|
self._check_val(entity_instance_id) + sep)
|
|
resp = fm_core.get(buff)
|
|
if resp is False:
|
|
raise APIException("Failed to execute get_fault.")
|
|
else:
|
|
return self._str_to_alarm(resp) if resp else None
|
|
|
|
# Input: entity_instance_id
|
|
# Return: Success: True
|
|
# Alarm doesn't exist: False
|
|
# Exception: When there is operation failure
|
|
def clear_all(self, entity_instance_id):
|
|
with fm_api_lock:
|
|
resp = fm_core.clear_all(entity_instance_id)
|
|
if resp is False:
|
|
# There is operation failure
|
|
raise APIException("Failed to execute clear_all.")
|
|
elif resp is None:
|
|
# alarm is not found
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
# Input: entity_instance_id
|
|
# Return: Success: Alarm list
|
|
# Alarm doesn't exist: None
|
|
# Exception: When there is operation failure
|
|
def get_faults(self, entity_instance_id):
|
|
with fm_api_lock:
|
|
resp = fm_core.get_by_eid(entity_instance_id)
|
|
if resp is False:
|
|
raise APIException("Failed to execute get_faults.")
|
|
elif resp:
|
|
data = []
|
|
for i in resp:
|
|
data.append(self._str_to_alarm(i))
|
|
return data
|
|
else:
|
|
return None
|
|
|
|
# Input: alarm_id
|
|
# Return: Success: Alarm list
|
|
# Alarm doesn't exist: None
|
|
# Exception: When there is operation failure
|
|
def get_faults_by_id(self, alarm_id):
|
|
with fm_api_lock:
|
|
resp = fm_core.get_by_aid(alarm_id)
|
|
if resp is False:
|
|
raise APIException("Failed to execute get_faults_by_id.")
|
|
elif resp:
|
|
data = []
|
|
for i in resp:
|
|
data.append(self._str_to_alarm(i))
|
|
return data
|
|
else:
|
|
return None
|