diff --git a/nfv/nfv-client/nfv_client/openstack/sw_update.py b/nfv/nfv-client/nfv_client/openstack/sw_update.py index 536b0b9f..9d3b29c8 100755 --- a/nfv/nfv-client/nfv_client/openstack/sw_update.py +++ b/nfv/nfv-client/nfv_client/openstack/sw_update.py @@ -301,11 +301,16 @@ def create_strategy(token_id, api_cmd_payload['default-instance-action'] = default_instance_action # TODO(jkraitbe): Backend for sw-deploy will continue as old sw-upgrade for now elif sw_update.STRATEGY_NAME_SW_UPGRADE == strategy_name: - # for upgrade: default-instance-action is hardcoded to MIGRATE + # controller-apply-type and default-instance-action passed to strategy + api_cmd_payload['controller-apply-type'] = controller_apply_type + api_cmd_payload['default-instance-action'] = default_instance_action + # required: 'release' passed to strategy as 'release' + api_cmd_payload['release'] = kwargs['release'] if 'start_upgrade' in kwargs and kwargs['start_upgrade']: api_cmd_payload['start-upgrade'] = True if 'complete_upgrade' in kwargs and kwargs['complete_upgrade']: api_cmd_payload['complete-upgrade'] = True + api_cmd_payload['storage-apply-type'] = storage_apply_type api_cmd_payload['worker-apply-type'] = worker_apply_type if max_parallel_worker_hosts is not None: diff --git a/nfv/nfv-client/nfv_client/shell.py b/nfv/nfv-client/nfv_client/shell.py index b15fd4e0..4ec121c2 100755 --- a/nfv/nfv-client/nfv_client/shell.py +++ b/nfv/nfv-client/nfv_client/shell.py @@ -53,7 +53,10 @@ def get_extra_create_args(cmd_area, args): elif sw_update.CMD_NAME_SW_DEPLOY == cmd_area: # TODO(jkraitbe): Args will be updated to use new release parameter # upgrade supports: complete_upgrade - return {'complete_upgrade': args.complete_upgrade} + return { + 'release': args.release, + 'complete_upgrade': args.complete_upgrade + } elif sw_update.CMD_NAME_FW_UPDATE == cmd_area: # no additional kwargs for firmware update return {} @@ -448,14 +451,16 @@ def setup_sw_deploy_parser(commands): # alarm restrictions, defaults to strict create_strategy_cmd = setup_create_cmd( sub_cmds, - [sw_update.APPLY_TYPE_SERIAL], # hard coded to serial + [sw_update.APPLY_TYPE_SERIAL, # hard coded to serial + sw_update.APPLY_TYPE_IGNORE], [sw_update.APPLY_TYPE_SERIAL, # storage supports serial and parallel sw_update.APPLY_TYPE_PARALLEL, sw_update.APPLY_TYPE_IGNORE], [sw_update.APPLY_TYPE_SERIAL, # worker supports serial and parallel sw_update.APPLY_TYPE_PARALLEL, sw_update.APPLY_TYPE_IGNORE], - [sw_update.INSTANCE_ACTION_MIGRATE], # hardcoded to migrate + [sw_update.INSTANCE_ACTION_STOP_START, # instance actions + sw_update.INSTANCE_ACTION_MIGRATE], [sw_update.ALARM_RESTRICTIONS_STRICT, # alarm restrictions sw_update.ALARM_RESTRICTIONS_RELAXED], min_parallel=2, @@ -469,8 +474,10 @@ def setup_sw_deploy_parser(commands): # create_strategy_cmd.add_argument('--start-upgrade', # action='store_true', # help=argparse.SUPPRESS) + # sw-deploy create requires 'release' parameter + create_strategy_cmd.add_argument('release', + help='software release for deployment') - # TODO(jkraitbe): Args will be updated to use new release parameter create_strategy_cmd.add_argument('--complete-upgrade', action='store_true', help=argparse.SUPPRESS) diff --git a/nfv/nfv-client/scripts/sw-manager.completion b/nfv/nfv-client/scripts/sw-manager.completion index 16c267e1..30f9a07b 100755 --- a/nfv/nfv-client/scripts/sw-manager.completion +++ b/nfv/nfv-client/scripts/sw-manager.completion @@ -125,13 +125,19 @@ function _swmanager() case "$action" in create) local createopts=" + --controller-apply-type --storage-apply-type --worker-apply-type --max-parallel-worker-hosts + --instance-action --alarm-restrictions " local createopt=${prev} case "$createopt" in + --controller-apply-type) + COMPREPLY=($(compgen -W "serial ignore" -- ${cur})) + return 0 + ;; --storage-apply-type) COMPREPLY=($(compgen -W "serial parallel ignore" -- ${cur})) return 0 @@ -144,6 +150,10 @@ function _swmanager() COMPREPLY=( $(compgen -- ${cur})) return 0 ;; + --instance-action) + COMPREPLY=($(compgen -W "migrate stop-start" -- ${cur})) + return 0 + ;; --alarm-restrictions) COMPREPLY=($(compgen -W "strict relaxed" -- ${cur})) return 0 diff --git a/nfv/nfv-tests/nfv_unit_tests/tests/test_nfv_client.py b/nfv/nfv-tests/nfv_unit_tests/tests/test_nfv_client.py index 2e6c2dd8..8c466f6a 100755 --- a/nfv/nfv-tests/nfv_unit_tests/tests/test_nfv_client.py +++ b/nfv/nfv-tests/nfv_unit_tests/tests/test_nfv_client.py @@ -251,6 +251,10 @@ class TestCLISwDeployStrategy(TestNFVClientShell, super(TestCLISwDeployStrategy, self).setUp() self.set_strategy('sw-deploy-strategy') + def required_create_fields(self): + """sw-deploy strategy requires 'release' parameter for create""" + return ['starlingx-24.03.1'] + class TestCLIPatchStrategy(TestNFVClientShell, StrategyMixin): diff --git a/nfv/nfv-tests/nfv_unit_tests/tests/test_sw_upgrade_strategy.py b/nfv/nfv-tests/nfv_unit_tests/tests/test_sw_upgrade_strategy.py index a05cbc8f..a453f480 100755 --- a/nfv/nfv-tests/nfv_unit_tests/tests/test_sw_upgrade_strategy.py +++ b/nfv/nfv-tests/nfv_unit_tests/tests/test_sw_upgrade_strategy.py @@ -51,6 +51,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase): worker_apply_type=SW_UPDATE_APPLY_TYPE.IGNORE, max_parallel_worker_hosts=10, alarm_restrictions=SW_UPDATE_ALARM_RESTRICTION.STRICT, + release='starlingx-24.03.1', start_upgrade=False, complete_upgrade=False, nfvi_upgrade=None, @@ -65,6 +66,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase): worker_apply_type=worker_apply_type, max_parallel_worker_hosts=max_parallel_worker_hosts, alarm_restrictions=alarm_restrictions, + release=release, start_upgrade=start_upgrade, complete_upgrade=complete_upgrade, ignore_alarms=[], diff --git a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_strategy.py b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_strategy.py index dce7632b..75ed4bdc 100755 --- a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_strategy.py +++ b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_strategy.py @@ -27,7 +27,6 @@ from nfv_vim import rpc from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SW_UPDATE_ACTION from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SW_UPDATE_ALARM_RESTRICTION_TYPES from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SW_UPDATE_APPLY_TYPE -from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SW_UPDATE_INSTANCE_ACTION from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SW_UPDATE_NAME from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SwUpdateActions from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_defs import SwUpdateAlarmRestrictionTypes @@ -174,12 +173,19 @@ class SwUpgradeStrategyCreateData(wsme_types.Base): """ Software Upgrade Strategy - Create Data """ + controller_apply_type = wsme_types.wsattr(SwUpdateApplyTypes, mandatory=True, + name='controller-apply-type') + release = wsme_types.wsattr(six.text_type, mandatory=True, + name='release') storage_apply_type = wsme_types.wsattr(SwUpdateApplyTypes, mandatory=True, name='storage-apply-type') worker_apply_type = wsme_types.wsattr(SwUpdateApplyTypes, mandatory=True, name='worker-apply-type') max_parallel_worker_hosts = wsme_types.wsattr( int, mandatory=False, name='max-parallel-worker-hosts') + default_instance_action = wsme_types.wsattr(SwUpdateInstanceActionTypes, + mandatory=True, + name='default-instance-action') # Disable support for start-upgrade as it was not completed # start_upgrade = wsme_types.wsattr( # bool, mandatory=False, default=False, name='start-upgrade') @@ -673,7 +679,8 @@ class SwUpgradeStrategyAPI(SwUpdateStrategyAPI): rpc_request = rpc.APIRequestCreateSwUpgradeStrategy() rpc_request.sw_update_type = _get_sw_update_type_from_path( pecan.request.path) - rpc_request.controller_apply_type = SW_UPDATE_APPLY_TYPE.SERIAL + rpc_request.release = request_data.release + rpc_request.controller_apply_type = request_data.controller_apply_type rpc_request.storage_apply_type = request_data.storage_apply_type rpc_request.swift_apply_type = SW_UPDATE_APPLY_TYPE.IGNORE rpc_request.worker_apply_type = request_data.worker_apply_type @@ -686,7 +693,7 @@ class SwUpgradeStrategyAPI(SwUpdateStrategyAPI): "Invalid value for max-parallel-worker-hosts") rpc_request.max_parallel_worker_hosts = \ request_data.max_parallel_worker_hosts - rpc_request.default_instance_action = SW_UPDATE_INSTANCE_ACTION.MIGRATE + rpc_request.default_instance_action = request_data.default_instance_action rpc_request.alarm_restrictions = request_data.alarm_restrictions # rpc_request.start_upgrade = request_data.start_upgrade rpc_request.start_upgrade = False diff --git a/nfv/nfv-vim/nfv_vim/directors/_sw_mgmt_director.py b/nfv/nfv-vim/nfv_vim/directors/_sw_mgmt_director.py index 1d0f3cc3..ae0f8444 100755 --- a/nfv/nfv-vim/nfv_vim/directors/_sw_mgmt_director.py +++ b/nfv/nfv-vim/nfv_vim/directors/_sw_mgmt_director.py @@ -76,7 +76,7 @@ class SwMgmtDirector(object): def create_sw_upgrade_strategy(self, storage_apply_type, worker_apply_type, max_parallel_worker_hosts, - alarm_restrictions, start_upgrade, + alarm_restrictions, release, start_upgrade, complete_upgrade, callback): """ Create Software Upgrade Strategy @@ -94,7 +94,7 @@ class SwMgmtDirector(object): success, reason = self._sw_update.strategy_build( strategy_uuid, storage_apply_type, worker_apply_type, max_parallel_worker_hosts, - alarm_restrictions, start_upgrade, + alarm_restrictions, release, start_upgrade, complete_upgrade, self._ignore_alarms, self._single_controller) diff --git a/nfv/nfv-vim/nfv_vim/events/_vim_sw_update_api_events.py b/nfv/nfv-vim/nfv_vim/events/_vim_sw_update_api_events.py index 54a613aa..de699daf 100755 --- a/nfv/nfv-vim/nfv_vim/events/_vim_sw_update_api_events.py +++ b/nfv/nfv-vim/nfv_vim/events/_vim_sw_update_api_events.py @@ -99,11 +99,13 @@ def vim_sw_update_api_create_strategy(connection, msg): default_instance_action, alarm_restrictions, _vim_sw_update_api_create_strategy_callback) elif 'sw-upgrade' == msg.sw_update_type: + release = msg.release start_upgrade = msg.start_upgrade complete_upgrade = msg.complete_upgrade uuid, reason = sw_mgmt_director.create_sw_upgrade_strategy( storage_apply_type, worker_apply_type, max_parallel_worker_hosts, alarm_restrictions, + release, start_upgrade, complete_upgrade, _vim_sw_update_api_create_strategy_callback) elif 'fw-update' == msg.sw_update_type: diff --git a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py index 466b7b1c..f88161ae 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py @@ -675,3 +675,10 @@ def nfvi_infrastructure_finalize(): """ if _infrastructure_plugin is not None: _infrastructure_plugin.finalize() + + +# todo (vselvara): To be used in the upcoming task +# def nfvi_get_software_release(callback): +# cmd_id = _infrastructure_plugin.invoke_plugin('get_software_release', +# callback=callback) +# return cmd_id diff --git a/nfv/nfv-vim/nfv_vim/objects/_sw_upgrade.py b/nfv/nfv-vim/nfv_vim/objects/_sw_upgrade.py index 751e5f6e..2a5d18c3 100755 --- a/nfv/nfv-vim/nfv_vim/objects/_sw_upgrade.py +++ b/nfv/nfv-vim/nfv_vim/objects/_sw_upgrade.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2016 Wind River Systems, Inc. +# Copyright (c) 2024 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -31,7 +31,7 @@ class SwUpgrade(SwUpdate): def strategy_build(self, strategy_uuid, storage_apply_type, worker_apply_type, max_parallel_worker_hosts, - alarm_restrictions, start_upgrade, + alarm_restrictions, release, start_upgrade, complete_upgrade, ignore_alarms, single_controller): """ Create a software upgrade strategy @@ -45,7 +45,7 @@ class SwUpgrade(SwUpdate): self._strategy = strategy.SwUpgradeStrategy( strategy_uuid, storage_apply_type, worker_apply_type, max_parallel_worker_hosts, - alarm_restrictions, start_upgrade, complete_upgrade, + alarm_restrictions, release, start_upgrade, complete_upgrade, ignore_alarms, single_controller) self._strategy.sw_update_obj = self diff --git a/nfv/nfv-vim/nfv_vim/rpc/_rpc_message_sw_update.py b/nfv/nfv-vim/nfv_vim/rpc/_rpc_message_sw_update.py index b9c15004..29955ac9 100755 --- a/nfv/nfv-vim/nfv_vim/rpc/_rpc_message_sw_update.py +++ b/nfv/nfv-vim/nfv_vim/rpc/_rpc_message_sw_update.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2023 Wind River Systems, Inc. +# Copyright (c) 2015-2024 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -63,6 +63,7 @@ class APIRequestCreateSwUpgradeStrategy(APIRequestCreateSwUpdateStrategy): """ start_upgrade = None complete_upgrade = None + release = None def __init__(self, msg_version=RPC_MSG_VERSION.VERSION_1_0, msg_type=RPC_MSG_TYPE.CREATE_SW_UPGRADE_STRATEGY_REQUEST, @@ -74,11 +75,13 @@ class APIRequestCreateSwUpgradeStrategy(APIRequestCreateSwUpdateStrategy): super(APIRequestCreateSwUpgradeStrategy, self).serialize_payload(msg) msg['start_upgrade'] = self.start_upgrade msg['complete_upgrade'] = self.complete_upgrade + msg['release'] = self.release def deserialize_payload(self, msg): super(APIRequestCreateSwUpgradeStrategy, self).deserialize_payload(msg) self.start_upgrade = msg.get('start_upgrade', None) self.complete_upgrade = msg.get('complete_upgrade', None) + self.release = msg.get('release', None) def __str__(self): return "create-sw-upgrade-strategy request: %s" % self.deserialize_payload diff --git a/nfv/nfv-vim/nfv_vim/strategy/_strategy.py b/nfv/nfv-vim/nfv_vim/strategy/_strategy.py index 7db764f6..2517e385 100755 --- a/nfv/nfv-vim/nfv_vim/strategy/_strategy.py +++ b/nfv/nfv-vim/nfv_vim/strategy/_strategy.py @@ -1709,7 +1709,7 @@ class SwUpgradeStrategy(SwUpdateStrategy): """ def __init__(self, uuid, storage_apply_type, worker_apply_type, max_parallel_worker_hosts, - alarm_restrictions, start_upgrade, complete_upgrade, + alarm_restrictions, release, start_upgrade, complete_upgrade, ignore_alarms, single_controller): super(SwUpgradeStrategy, self).__init__( uuid, @@ -1719,7 +1719,7 @@ class SwUpgradeStrategy(SwUpdateStrategy): SW_UPDATE_APPLY_TYPE.IGNORE, worker_apply_type, max_parallel_worker_hosts, - SW_UPDATE_INSTANCE_ACTION.MIGRATE, + SW_UPDATE_INSTANCE_ACTION.STOP_START, alarm_restrictions, ignore_alarms) @@ -1735,6 +1735,7 @@ class SwUpgradeStrategy(SwUpdateStrategy): # which would only have been for lab use. if start_upgrade: raise Exception("No support for start_upgrade") + self._release = release self._start_upgrade = start_upgrade self._complete_upgrade = complete_upgrade # The following alarms will not prevent a software upgrade operation @@ -2086,6 +2087,7 @@ class SwUpgradeStrategy(SwUpdateStrategy): """ from nfv_vim import strategy from nfv_vim import tables + import re result, result_reason = \ super(SwUpgradeStrategy, self).build_complete(result, result_reason) @@ -2093,6 +2095,19 @@ class SwUpgradeStrategy(SwUpdateStrategy): DLOG.info("Build Complete Callback, result=%s, reason=%s." % (result, result_reason)) + # todo (vselvara): release validation needs to be replaced with validation + # based on results from 'software release' query api in the upcoming story. + release_type = re.compile(r"^[a-z]+[\-]+[\d*]+[\.]+[\d*]+[\.]+[\d*]+$") + if not release_type.match(self._release): + DLOG.warn("Invalid Software Release.") + self._state = strategy.STRATEGY_STATE.BUILD_FAILED + self.build_phase.result = strategy.STRATEGY_PHASE_RESULT.FAILED + self.build_phase.result_reason = 'invalid software release' + self.sw_update_obj.strategy_build_complete( + False, self.build_phase.result_reason) + self.save() + return + if result in [strategy.STRATEGY_RESULT.SUCCESS, strategy.STRATEGY_RESULT.DEGRADED]: @@ -2277,6 +2292,7 @@ class SwUpgradeStrategy(SwUpdateStrategy): self._single_controller = data['single_controller'] self._start_upgrade = data['start_upgrade'] self._complete_upgrade = data['complete_upgrade'] + self._release = data['release'] nfvi_upgrade_data = data['nfvi_upgrade_data'] if nfvi_upgrade_data: self._nfvi_upgrade = nfvi.objects.v1.Upgrade( @@ -2296,6 +2312,7 @@ class SwUpgradeStrategy(SwUpdateStrategy): data['single_controller'] = self._single_controller data['start_upgrade'] = self._start_upgrade data['complete_upgrade'] = self._complete_upgrade + data['release'] = self._release if self._nfvi_upgrade: nfvi_upgrade_data = self._nfvi_upgrade.as_dict() else: diff --git a/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py b/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py index 245c4052..ac18fb94 100755 --- a/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py +++ b/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py @@ -54,6 +54,7 @@ class StrategyStepNames(Constants): QUERY_SW_PATCH_HOSTS = Constant('query-sw-patch-hosts') QUERY_FW_UPDATE_HOST = Constant('query-fw-update-host') QUERY_UPGRADE = Constant('query-upgrade') + QUERY_SOFTWARE_RELEASE = Constant('query-software-release') DISABLE_HOST_SERVICES = Constant('disable-host-services') ENABLE_HOST_SERVICES = Constant('enable-host-services') # kube rootca update steps @@ -2751,6 +2752,35 @@ class FwUpdateAbortHostsStep(strategy.StrategyStep): return data +# class QuerySoftwareReleaseStep(AbstractStrategyStep): +# todo: To be implemented completely in the upcoming task. +# def __init__(self): +# super(QuerySoftwareReleaseStep, self).__init__( +# STRATEGY_STEP_NAME.QUERY_SOFTWARE_RELEASE, timeout_in_secs=60) + +# @coroutine +# def _query_callback(self): +# response = (yield) +# DLOG.debug("%s callback response=%s." % (self._name, response)) + +# if response['completed']: +# if self.strategy is not None: +# self.strategy.nfvi_kube_versions_list = response['result-data'] + +# result = strategy.STRATEGY_STEP_RESULT.SUCCESS +# self.stage.step_complete(result, "") +# else: +# result = strategy.STRATEGY_STEP_RESULT.FAILED +# self.stage.step_complete(result, response['reason']) + +# def apply(self): +# from nfv_vim import nfvi + +# DLOG.info("Step (%s) apply." % self._name) +# nfvi.nfvi_get_kube_version_list(self._query_callback()) +# return strategy.STRATEGY_STEP_RESULT.WAIT, "" + + class QueryUpgradeStep(strategy.StrategyStep): """ Query Upgrade - Strategy Step