nfv/nfv/nfv-vim/nfv_vim/objects/_fw_update.py
Eric MacDonald 615340ce62 Add orchestrated fw update support to vim
This update adds firmware update orchestration support to
the VIM for host device fpga images as described in the
'N3000 FPGA device image update orchestration' feature
specification. See https://review.opendev.org/#/c/713302/

The firmware update orchestration strategy added to the VIM
is modeled after the VIM's existing patch orchestration
and includes strategy create/apply/show/abort/delete.

The strategy can be managed through the existing sw-manager
tool via the VIM's REST API.

Only unlocked hosts with the worker function are included
in the strategy.

The strategy includes a stage for each host or group of hosts
with ordered step sequences of firmware update followed by a
lock and unlock of each updated host.

Change-Id: I4eea7ca3f00782d27cdbb5d5615c6a255ac6966e
Story: 2006740
Task: 39145
Signed-off-by: Eric MacDonald <eric.macdonald@windriver.com>
2020-05-14 01:03:21 +00:00

188 lines
6.6 KiB
Python

#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from nfv_common import debug
from nfv_common.helpers import coroutine
from nfv_vim import alarm
from nfv_vim import event_log
from nfv_vim import nfvi
from nfv_vim.objects._sw_update import SW_UPDATE_ALARM_TYPES
from nfv_vim.objects._sw_update import SW_UPDATE_EVENT_IDS
from nfv_vim.objects._sw_update import SW_UPDATE_TYPE
from nfv_vim.objects._sw_update import SwUpdate
DLOG = debug.debug_get_logger('nfv_vim.objects.fw_update')
class FwUpdate(SwUpdate):
"""
Firmware Update Object
"""
def __init__(self, sw_update_uuid=None, strategy_data=None):
super(FwUpdate, self).__init__(sw_update_type=SW_UPDATE_TYPE.FW_UPDATE,
sw_update_uuid=sw_update_uuid,
strategy_data=strategy_data)
self._fw_update_hosts = list()
def strategy_build(self, strategy_uuid, controller_apply_type,
storage_apply_type, worker_apply_type,
max_parallel_worker_hosts,
default_instance_action, alarm_restrictions,
ignore_alarms,
single_controller):
"""
Create a firmware update strategy
"""
from nfv_vim import strategy
if self._strategy:
reason = "strategy already exists"
return False, reason
self._strategy = strategy.FwUpdateStrategy(
strategy_uuid, controller_apply_type, storage_apply_type,
worker_apply_type, max_parallel_worker_hosts,
default_instance_action,
alarm_restrictions, ignore_alarms,
single_controller)
self._strategy.sw_update_obj = self
self._strategy.build()
self._persist()
return True, ''
def strategy_build_complete(self, success, reason):
"""
Creation of a firmware update strategy complete
"""
DLOG.info("Firmware update strategy build complete.")
pass
@staticmethod
def alarm_type(alarm_type):
"""
Returns ALARM_TYPE corresponding to SW_UPDATE_ALARM_TYPES
"""
ALARM_TYPE_MAPPING = {
SW_UPDATE_ALARM_TYPES.APPLY_INPROGRESS:
alarm.ALARM_TYPE.FW_UPDATE_AUTO_APPLY_INPROGRESS,
SW_UPDATE_ALARM_TYPES.APPLY_ABORTING:
alarm.ALARM_TYPE.FW_UPDATE_AUTO_APPLY_ABORTING,
SW_UPDATE_ALARM_TYPES.APPLY_FAILED:
alarm.ALARM_TYPE.FW_UPDATE_AUTO_APPLY_FAILED,
}
return ALARM_TYPE_MAPPING[alarm_type]
@staticmethod
def event_id(event_id):
"""
Returns EVENT_ID corresponding to SW_UPDATE_EVENT_IDS
"""
EVENT_ID_MAPPING = {
SW_UPDATE_EVENT_IDS.APPLY_START:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_START,
SW_UPDATE_EVENT_IDS.APPLY_INPROGRESS:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_INPROGRESS,
SW_UPDATE_EVENT_IDS.APPLY_REJECTED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_REJECTED,
SW_UPDATE_EVENT_IDS.APPLY_CANCELLED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_CANCELLED,
SW_UPDATE_EVENT_IDS.APPLY_FAILED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_FAILED,
SW_UPDATE_EVENT_IDS.APPLY_COMPLETED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_COMPLETED,
SW_UPDATE_EVENT_IDS.APPLY_ABORT:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_ABORT,
SW_UPDATE_EVENT_IDS.APPLY_ABORTING:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_ABORTING,
SW_UPDATE_EVENT_IDS.APPLY_ABORT_REJECTED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_ABORT_REJECTED,
SW_UPDATE_EVENT_IDS.APPLY_ABORT_FAILED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_ABORT_FAILED,
SW_UPDATE_EVENT_IDS.APPLY_ABORTED:
event_log.EVENT_ID.FW_UPDATE_AUTO_APPLY_ABORTED,
}
return EVENT_ID_MAPPING[event_id]
def nfvi_update(self):
"""
NFVI Update
"""
if self._strategy is None:
if self._alarms:
alarm.clear_sw_update_alarm(self._alarms)
return False
if self.strategy.is_applying():
if not self._alarms:
self._alarms = \
alarm.raise_sw_update_alarm(
self.alarm_type(SW_UPDATE_ALARM_TYPES.APPLY_INPROGRESS))
event_log.sw_update_issue_log(
self.event_id(SW_UPDATE_EVENT_IDS.APPLY_INPROGRESS))
elif self.strategy.is_apply_failed() or self.strategy.is_apply_timed_out():
for fw_update_host in self._fw_update_hosts:
if not self._alarms:
self._alarms = \
alarm.raise_sw_update_alarm(
self.alarm_type(SW_UPDATE_ALARM_TYPES.APPLY_FAILED))
event_log.sw_update_issue_log(
self.event_id(SW_UPDATE_EVENT_IDS.APPLY_FAILED))
break
else:
if self._alarms:
alarm.clear_sw_update_alarm(self._alarms)
return False
elif self.strategy.is_aborting():
if not self._alarms:
self._alarms = \
alarm.raise_sw_update_alarm(
self.alarm_type(SW_UPDATE_ALARM_TYPES.APPLY_ABORTING))
event_log.sw_update_issue_log(
self.event_id(SW_UPDATE_EVENT_IDS.APPLY_ABORTING))
else:
if self._alarms:
alarm.clear_sw_update_alarm(self._alarms)
return False
return True
@coroutine
def nfvi_audit(self):
"""
Audit NFVI layer
"""
while True:
timer_id = (yield)
DLOG.debug("Audit alarms, timer_id=%s." % timer_id)
self.nfvi_alarms_clear()
nfvi.nfvi_get_alarms(self.nfvi_alarms_callback(timer_id))
if not nfvi.nfvi_fault_mgmt_plugin_disabled():
nfvi.nfvi_get_openstack_alarms(self.nfvi_alarms_callback(timer_id))
self._nfvi_audit_inprogress = True
while self._nfvi_audit_inprogress:
timer_id = (yield)
if not self.nfvi_update():
DLOG.info("Audit no longer needed.")
break
DLOG.verbose("Audit firmware update still running, timer_id=%s." %
timer_id)
self._nfvi_timer_id = None