def take_action(self, alert, action, text, **kwargs): if action == 'invalid': raise InvalidAction( '{} is not a valid action for this status'.format(action)) return alert, action, text
def take_action(self, alert, action, text, **kwargs): if action == 'invalid': raise InvalidAction( f'{action} is not a valid action for this status') return alert, action, text
def take_action(self, alert, action, text, **kwargs): alert.tags.remove('aDouble:Tag') if action == 'invalid': raise InvalidAction('{} is not a valid action for this status'.format(action)) return alert, action, text
def take_action(self, alert, action, text, **kwargs): if action == ACTION_ESCALATE: severity_level = str(alarm_model.Severity[alert.severity]) try: alert.severity = escalate_map.get(severity_level)[0] text = 'alert severity escalated' except TypeError: raise InvalidAction( f'Can not escalate alert severity beyond "{alert.severity}".' ) return alert, action, text
def transition(self, alert, current_status=None, previous_status=None, action=None, **kwargs): current_status = current_status or StateMachine.DEFAULT_STATUS previous_status = previous_status or StateMachine.DEFAULT_STATUS current_severity = alert.severity previous_severity = alert.previous_severity or StateMachine.DEFAULT_PREVIOUS_SEVERITY valid_severities = sorted(StateMachine.Severity, key=StateMachine.Severity.get) if current_severity not in StateMachine.Severity: raise ApiError(f"Severity ({current_severity}) is not one of {', '.join(valid_severities)}", 400) def next_state(rule, severity, status): current_app.logger.info( 'State Transition: Rule #{} STATE={:8s} ACTION={:8s} SET={:8s} ' 'SEVERITY={:13s}-> {:8s} HISTORY={:8s}-> {:8s} => SEVERITY={:8s}, STATUS={:8s}'.format( rule, current_status, action or '', alert.status, previous_severity, current_severity, previous_status, current_status, severity, status )) return severity, status # if an unrecognised action is passed then assume state transition has been handled # by a take_action() plugin and return the current severity and status unchanged if action and action not in ACTION_ALL: return next_state('ACT-1', current_severity, alert.status) # if alert has non-default status then assume state transition has been handled # by a pre_receive() plugin and return the current severity and status, accounting # for auto-closing normal alerts, otherwise unchanged if not action and alert.status != StateMachine.DEFAULT_STATUS: if StateMachine.Severity[current_severity] == StateMachine.NORMAL_SEVERITY_LEVEL: return next_state('SET-1', StateMachine.DEFAULT_NORMAL_SEVERITY, Status.Closed) return next_state('SET-*', current_severity, alert.status) # state transition determined by operator action, if any, or severity changes state = current_status if action == Action.UNACK: if state == Status.Ack: return next_state('UNACK-1', current_severity, previous_status) else: raise InvalidAction(f'invalid action for current {state} status') if action == Action.UNSHELVE: if state == Status.Shelved: # as per ISA 18.2 recommendation 11.7.3 manually unshelved alarms transition to previous status return next_state('UNSHL-1', current_severity, previous_status) else: raise InvalidAction(f'invalid action for current {state} status') if action == Action.EXPIRED: return next_state('EXP-0', current_severity, Status.Expired) if action == Action.TIMEOUT: if previous_status == Status.Ack: return next_state('ACK-0', current_severity, Status.Ack) else: return next_state('OPEN-0', current_severity, Status.Open) if state == Status.Open: if action == Action.OPEN: raise InvalidAction(f'alert is already in {state} status') if action == Action.ACK: return next_state('OPEN-1', current_severity, Status.Ack) if action == Action.SHELVE: return next_state('OPEN-2', current_severity, Status.Shelved) if action == Action.CLOSE: return next_state('OPEN-3', StateMachine.DEFAULT_NORMAL_SEVERITY, Status.Closed) if state == Status.Assign: pass if state == Status.Ack: if action == Action.OPEN: return next_state('ACK-1', current_severity, Status.Open) if action == Action.ACK: raise InvalidAction(f'alert is already in {state} status') if action == Action.SHELVE: return next_state('ACK-2', current_severity, Status.Shelved) if action == Action.CLOSE: return next_state('ACK-3', StateMachine.DEFAULT_NORMAL_SEVERITY, Status.Closed) # re-open ack'ed alerts if the severity actually increases # not just because the previous severity is the default if previous_severity != StateMachine.DEFAULT_PREVIOUS_SEVERITY: if self.trend(previous_severity, current_severity) == TrendIndication.More_Severe: return next_state('ACK-4', current_severity, Status.Open) if state == Status.Shelved: if action == Action.OPEN: return next_state('SHL-1', current_severity, Status.Open) if action == Action.ACK: raise InvalidAction(f'invalid action for current {state} status') if action == Action.SHELVE: raise InvalidAction(f'alert is already in {state} status') if action == Action.CLOSE: return next_state('SHL-2', StateMachine.DEFAULT_NORMAL_SEVERITY, Status.Closed) if state == Status.Blackout: if action == Action.CLOSE: return next_state('BLK-1', StateMachine.DEFAULT_NORMAL_SEVERITY, Status.Closed) if previous_status != Status.Blackout: return next_state('BLK-2', current_severity, previous_status) else: return next_state('BLK-*', current_severity, alert.status) if state == Status.Closed: if action == Action.OPEN: return next_state('CLS-1', previous_severity, Status.Open) if action == Action.ACK: raise InvalidAction(f'invalid action for current {state} status') if action == Action.SHELVE: raise InvalidAction(f'invalid action for current {state} status') if action == Action.CLOSE: raise InvalidAction(f'alert is already in {state} status') if StateMachine.Severity[current_severity] != StateMachine.NORMAL_SEVERITY_LEVEL: if previous_status == Status.Shelved: return next_state('CLS-2', previous_severity, Status.Shelved) else: return next_state('CLS-3', previous_severity, Status.Open) # auto-close normal severity alerts from ANY state if StateMachine.Severity[current_severity] == StateMachine.NORMAL_SEVERITY_LEVEL: return next_state('CLS-*', StateMachine.DEFAULT_NORMAL_SEVERITY, Status.Closed) if state == Status.Expired: if action and action != Action.OPEN: raise InvalidAction(f'invalid action for current {state} status') if StateMachine.Severity[current_severity] != StateMachine.NORMAL_SEVERITY_LEVEL: return next_state('EXP-1', current_severity, Status.Open) return next_state('ALL-*', current_severity, current_status)
def transition(self, alert, current_status=None, previous_status=None, action=None, **kwargs): current_status = current_status or StateMachine.DEFAULT_STATUS previous_status = previous_status or StateMachine.DEFAULT_STATUS current_severity = alert.severity previous_severity = alert.previous_severity or StateMachine.DEFAULT_PREVIOUS_SEVERITY valid_severities = sorted(StateMachine.Severity, key=StateMachine.Severity.get) assert current_severity in StateMachine.Severity, 'Severity is not one of %s' % ', '.join(valid_severities) def next_state(rule, severity, status): current_app.logger.info( 'State Transition: Rule #{} STATE={:8s} ACTION={:8s} SET={:8s} ' 'SEVERITY={:13s}-> {:8s} HISTORY={:8s}-> {:8s} => SEVERITY={:8s}, STATUS={:8s}'.format( rule, current_status, action or '', alert.status, previous_severity, current_severity, previous_status, current_status, severity, status )) return severity, status # if an unrecognised action is passed then assume state transition has been handled # by a take_action() plugin and return the current severity and status unchanged if action and action not in ACTION_ALL: return next_state('ACT-1', current_severity, alert.status) # if alert has non-default status then assume state transition has been handled # by a pre_receive() plugin and return the current severity and status, accounting # for auto-closing normal alerts, otherwise unchanged if not action and alert.status != StateMachine.DEFAULT_STATUS: if StateMachine.Severity[current_severity] == StateMachine.NORMAL_SEVERITY_LEVEL: return next_state('SET-1', StateMachine.DEFAULT_NORMAL_SEVERITY, CLOSED) return next_state('SET-*', current_severity, alert.status) # state transition determined by operator action, if any, or severity changes state = current_status if action == ACTION_UNACK: if state == ACK: return next_state('UNACK-1', current_severity, previous_status) else: raise InvalidAction('invalid action for current {} status'.format(state)) if action == ACTION_UNSHELVE: if state == SHELVED: # as per ISA 18.2 recommendation 11.7.3 manually unshelved alarms transition to previous status return next_state('UNSHL-1', current_severity, previous_status) else: raise InvalidAction('invalid action for current {} status'.format(state)) if state == OPEN: if action == ACTION_OPEN: raise InvalidAction('alert is already in {} status'.format(state)) if action == ACTION_ACK: return next_state('OPEN-1', current_severity, ACK) if action == ACTION_SHELVE: return next_state('OPEN-2', current_severity, SHELVED) if action == ACTION_CLOSE: return next_state('OPEN-3', StateMachine.DEFAULT_NORMAL_SEVERITY, CLOSED) if state == ASSIGN: pass if state == ACK: if action == ACTION_OPEN: return next_state('ACK-1', current_severity, OPEN) if action == ACTION_ACK: raise InvalidAction('alert is already in {} status'.format(state)) if action == ACTION_SHELVE: return next_state('ACK-2', current_severity, SHELVED) if action == ACTION_CLOSE: return next_state('ACK-3', StateMachine.DEFAULT_NORMAL_SEVERITY, CLOSED) # re-open ack'ed alerts if the severity actually increases # not just because the previous severity is the default if previous_severity != StateMachine.DEFAULT_PREVIOUS_SEVERITY: if self.trend(previous_severity, current_severity) == MORE_SEVERE: return next_state('ACK-4', current_severity, OPEN) if state == SHELVED: if action == ACTION_OPEN: return next_state('SHL-1', current_severity, OPEN) if action == ACTION_ACK: raise InvalidAction('invalid action for current {} status'.format(state)) if action == ACTION_SHELVE: raise InvalidAction('alert is already in {} status'.format(state)) if action == ACTION_CLOSE: return next_state('SHL-2', StateMachine.DEFAULT_NORMAL_SEVERITY, CLOSED) if state == BLACKOUT: if action == ACTION_CLOSE: return next_state('BLK-1', StateMachine.DEFAULT_NORMAL_SEVERITY, CLOSED) if previous_status != BLACKOUT: return next_state('BLK-2', current_severity, previous_status) else: return next_state('BLK-*', current_severity, alert.status) if state == CLOSED: if action == ACTION_OPEN: return next_state('CLS-1', previous_severity, OPEN) if action == ACTION_ACK: raise InvalidAction('invalid action for current {} status'.format(state)) if action == ACTION_SHELVE: raise InvalidAction('invalid action for current {} status'.format(state)) if action == ACTION_CLOSE: raise InvalidAction('alert is already in {} status'.format(state)) if StateMachine.Severity[current_severity] != StateMachine.NORMAL_SEVERITY_LEVEL: if previous_status == SHELVED: return next_state('CLS-2', previous_severity, SHELVED) else: return next_state('CLS-3', previous_severity, OPEN) # auto-close normal severity alerts from ANY state if StateMachine.Severity[current_severity] == StateMachine.NORMAL_SEVERITY_LEVEL: return next_state('CLS-*', StateMachine.DEFAULT_NORMAL_SEVERITY, CLOSED) if state == EXPIRED: if StateMachine.Severity[current_severity] != StateMachine.NORMAL_SEVERITY_LEVEL: return next_state('EXP-1', current_severity, OPEN) return next_state('ALL-*', current_severity, current_status)