diff --git a/api-ref/source/api-ref-nfv-vim-v1.rst b/api-ref/source/api-ref-nfv-vim-v1.rst index a86cb03a..c38dd795 100644 --- a/api-ref/source/api-ref-nfv-vim-v1.rst +++ b/api-ref/source/api-ref-nfv-vim-v1.rst @@ -122,6 +122,10 @@ forbidden (403), badMethod (405), overLimit (413), itemNotFound (404) { "href": "http://192.168.204.2:4545/orchestration/system-config-update/", "rel": "system-config-update" + }, + { + "href": "http://192.168.204.2:4545/orchestration/current-strategy/", + "rel": "current-strategy" } ] } @@ -260,6 +264,39 @@ forbidden (403), badMethod (405), overLimit (413), itemNotFound (404) This operation does not accept a request body. +********************************************************************************* +Lists information about all NFV VIM API orchestration current-strategy links +********************************************************************************* + +.. rest_method:: GET /api/orchestration/current-strategy + +**Normal response codes** + +200 + +**Error response codes** + +serviceUnavailable (503), badRequest (400), unauthorized (401), +forbidden (403), badMethod (405), overLimit (413), itemNotFound (404) + +:: + + { + "id": "current-strategy", + "links": [ + { + "href": "http://192.168.204.2:4545/orchestration/current-strategy/", + "rel": "self" + }, + { + "href": "http://192.168.204.2:4545/orchestration/current-strategy/strategy/", + "rel": "strategy" + } + ] + } + +This operation does not accept a request body. + --------------- Patch Strategy --------------- @@ -3781,3 +3818,44 @@ forbidden (403), badMethod (405), overLimit (413) } } +----------------- +Current Strategy +----------------- + +Current Strategy REST API shows the current active strategy +type and its corresponding state. + +**************************************************************** +Shows detailed information about the current active strategy +**************************************************************** + +.. rest_method:: GET /api/orchestration/current-strategy/strategy + +**Normal response codes** + +200 + +**Error response codes** + +serviceUnavailable (503), badRequest (400), unauthorized (401), +forbidden (403), badMethod (405), overLimit (413), itemNotFound (404) + +:: + + { + "strategy": { + "name": "sw-patch" + "state": "applying" + } + } + +The result shows current active strategy name and type. +:: + + { + "strategy": null + } + +The result shows there is no current strategy. + +This operation does not accept a request body. diff --git a/nfv/nfv-client/nfv_client/openstack/sw_update.py b/nfv/nfv-client/nfv_client/openstack/sw_update.py index 0f912975..fd51a3e7 100755 --- a/nfv/nfv-client/nfv_client/openstack/sw_update.py +++ b/nfv/nfv-client/nfv_client/openstack/sw_update.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2023 Wind River Systems, Inc. +# Copyright (c) 2016-2024 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -179,6 +179,22 @@ def _get_strategy_object_from_response(response): return strategy +def _get_current_strategy_from_response(response): + """ + Returns Strategy Type and State + """ + current_strategy = {} + strategy_data = response.get('strategy', None) + if strategy_data is None: + return None + strategy = Strategy() + strategy.name = strategy_data['name'] + strategy.state = strategy_data['state'] + if strategy.name is not None: + current_strategy[strategy.name] = strategy.state + return current_strategy + + def get_strategies(token_id, url, strategy_name, username=None, user_domain_name=None, tenant=None): """ @@ -393,3 +409,26 @@ def abort_strategy(token_id, url, strategy_name, stage_id, username=None, return None return _get_strategy_object_from_response(response) + + +def get_current_strategy(token_id, url, username=None, + user_domain_name=None, tenant=None): + """ + Get The Current Active Strategy Type And State + """ + api_cmd = url + "/api/orchestration/current-strategy/strategy" + + api_cmd_headers = dict() + if username: + api_cmd_headers['X-User'] = username + if tenant: + api_cmd_headers['X-Tenant'] = tenant + if user_domain_name: + api_cmd_headers['X-User-Domain-Name'] = user_domain_name + api_cmd_headers['X-Auth-Token'] = token_id + + response = rest_api.request(token_id, "GET", api_cmd, api_cmd_headers) + if response['strategy'] is not None: + return _get_current_strategy_from_response(response) + + return None diff --git a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/_controller.py b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/_controller.py index 255394d3..a0ace2de 100755 --- a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/_controller.py +++ b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/_controller.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2023 Wind River Systems, Inc. +# Copyright (c) 2015-2021 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -13,6 +13,7 @@ from nfv_vim.api._link import Link from nfv_vim.api.controllers.v1.orchestration.sw_update import FwUpdateAPI from nfv_vim.api.controllers.v1.orchestration.sw_update import KubeRootcaUpdateAPI from nfv_vim.api.controllers.v1.orchestration.sw_update import KubeUpgradeAPI +from nfv_vim.api.controllers.v1.orchestration.sw_update import StrategyAPI from nfv_vim.api.controllers.v1.orchestration.sw_update import SwPatchAPI from nfv_vim.api.controllers.v1.orchestration.sw_update import SwUpgradeAPI from nfv_vim.api.controllers.v1.orchestration.sw_update import SystemConfigUpdateAPI @@ -41,7 +42,8 @@ class OrchestrationDescription(wsme_types.Base): url, 'orchestration/kube-rootca-update', ''), Link.make_link('kube-upgrade', url, 'orchestration/kube-upgrade', ''), - Link.make_link('fw-update', url, 'orchestration/fw-update', '')] + Link.make_link('fw-update', url, 'orchestration/fw-update', ''), + Link.make_link('current-strategy', url, 'orchestration/current-strategy', '')] return description @@ -63,6 +65,8 @@ class OrchestrationAPI(rest.RestController): return KubeRootcaUpdateAPI(), remainder elif 'kube-upgrade' == key: return KubeUpgradeAPI(), remainder + elif 'current-strategy' == key: + return StrategyAPI(), remainder else: pecan.abort(httplib.NOT_FOUND) diff --git a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/__init__.py b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/__init__.py index 4cb570c0..245f1493 100755 --- a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/__init__.py +++ b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/__init__.py @@ -1,8 +1,9 @@ # -# Copyright (c) 2015-2023 Wind River Systems, Inc. +# Copyright (c) 2015-2024 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # +from nfv_vim.api.controllers.v1.orchestration.sw_update._current_strategy import StrategyAPI # noqa: F401 from nfv_vim.api.controllers.v1.orchestration.sw_update._fw_update import FwUpdateAPI # noqa: F401 from nfv_vim.api.controllers.v1.orchestration.sw_update._kube_rootca_update import KubeRootcaUpdateAPI # noqa: F401 from nfv_vim.api.controllers.v1.orchestration.sw_update._kube_upgrade import KubeUpgradeAPI # noqa: F401 diff --git a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_current_strategy.py b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_current_strategy.py new file mode 100644 index 00000000..265ab448 --- /dev/null +++ b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_current_strategy.py @@ -0,0 +1,54 @@ +# +# Copyright (c) 2024 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +import pecan +from pecan import rest +from six.moves import http_client as httplib +from wsme import types as wsme_types +import wsmeext.pecan as wsme_pecan + +from nfv_common import debug +from nfv_vim.api._link import Link +from nfv_vim.api.controllers.v1.orchestration.sw_update._sw_update_strategy import CurrentStrategyAPI + +DLOG = debug.debug_get_logger('nfv_vim.api.current_strategy') + + +class StrategyDescription(wsme_types.Base): + """ + Current Strategy Description + """ + id = wsme_types.text + links = wsme_types.wsattr([Link], name='links') + + @classmethod + def convert(cls): + url = pecan.request.host_url + + description = StrategyDescription() + description.id = "current-strategy" + description.links = [ + Link.make_link('self', url, 'orchestration/current-strategy'), + Link.make_link('strategy', url, 'orchestration/current-strategy/strategy')] + return description + + +class StrategyAPI(rest.RestController): + """ + Current Strategy Rest API + """ + @pecan.expose() + def _lookup(self, key, *remainder): + if 'strategy' == key: + return CurrentStrategyAPI(), remainder + else: + pecan.abort(httplib.NOT_FOUND) + + @wsme_pecan.wsexpose(StrategyDescription) + def get(self): + # NOTE: The reason why convert() is being called for every + # request is because we need to get the host url from + # the request object to make the links. + return StrategyDescription.convert() diff --git a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_defs.py b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_defs.py index 127c8fbd..8af29a19 100755 --- a/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_defs.py +++ b/nfv/nfv-vim/nfv_vim/api/controllers/v1/orchestration/sw_update/_sw_update_defs.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2023 Wind River Systems, Inc. +# Copyright (c) 2015-2024 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -22,6 +22,7 @@ class SwUpdateNames(Constants): SW_PATCH = Constant('sw-patch') SW_UPGRADE = Constant('sw-upgrade') SYSTEM_CONFIG_UPDATE = Constant('system-config-update') + CURRENT_STRATEGY = Constant('current-strategy') @six.add_metaclass(Singleton) @@ -78,7 +79,8 @@ SwUpdateNames = wsme_types.Enum(str, SW_UPDATE_NAME.KUBE_UPGRADE, SW_UPDATE_NAME.SW_PATCH, SW_UPDATE_NAME.SW_UPGRADE, - SW_UPDATE_NAME.SYSTEM_CONFIG_UPDATE) + SW_UPDATE_NAME.SYSTEM_CONFIG_UPDATE, + SW_UPDATE_NAME.CURRENT_STRATEGY) SwUpdateApplyTypes = wsme_types.Enum(str, SW_UPDATE_APPLY_TYPE.SERIAL, SW_UPDATE_APPLY_TYPE.PARALLEL, 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 9642e798..dce7632b 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 @@ -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 # @@ -60,6 +60,8 @@ def _get_sw_update_type_from_path(path): return SW_UPDATE_NAME.KUBE_ROOTCA_UPDATE elif 'kube-upgrade' in split_path: return SW_UPDATE_NAME.KUBE_UPGRADE + elif 'current-strategy' in split_path: + return SW_UPDATE_NAME.CURRENT_STRATEGY else: DLOG.error("Unknown sw_update_type in path: %s" % path) return 'unknown' @@ -382,6 +384,12 @@ class SwUpdateStrategyQueryData(wsme_types.Base): self.convert_strategy_phase(strategy_data['abort_phase']) self.strategy = strategy + def convert_current_strategy(self, strategy_data): + strategy = SwUpdateStrategyData() + strategy.name = strategy_data['name'] + strategy.state = strategy_data['state'] + self.strategy = strategy + class SwUpdateStrategyActionAPI(rest.RestController): """ @@ -1011,3 +1019,40 @@ class KubeUpgradeStrategyAPI(SwUpdateStrategyAPI): auth_context_dict, exc=policy.PolicyForbidden) else: policy.check('admin_in_system_projects', {}, auth_context_dict) + + +class CurrentStrategyAPI(SwUpdateStrategyAPI): + """ + Current Strategy Rest API + """ + @wsme_pecan.wsexpose(SwUpdateStrategyQueryData, status_code=httplib.OK) + def get_all(self): + rpc_request = rpc.APIRequestGetSwUpdateStrategy() + rpc_request.sw_update_type = _get_sw_update_type_from_path( + pecan.request.path) + vim_connection = pecan.request.vim.open_connection() + vim_connection.send(rpc_request.serialize()) + msg = vim_connection.receive(timeout_in_secs=30) + if msg is None: + DLOG.error("No response received.") + return pecan.abort(httplib.INTERNAL_SERVER_ERROR) + + response = rpc.RPCMessage.deserialize(msg) + if rpc.RPC_MSG_TYPE.GET_SW_UPDATE_STRATEGY_RESPONSE != response.type: + DLOG.error("Unexpected message type received, msg_type=%s." + % response.type) + return pecan.abort(httplib.INTERNAL_SERVER_ERROR) + + if rpc.RPC_MSG_RESULT.SUCCESS == response.result: + strategy = json.loads(response.strategy) + query_data = SwUpdateStrategyQueryData() + query_data.convert_current_strategy(strategy) + return query_data + + elif rpc.RPC_MSG_RESULT.NOT_FOUND == response.result: + DLOG.verbose("No strategy exists.") + query_data = SwUpdateStrategyQueryData() + return query_data + + DLOG.error("Unexpected result received, result=%s." % response.result) + return pecan.abort(httplib.INTERNAL_SERVER_ERROR) 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 a6354033..1d0f3cc3 100755 --- a/nfv/nfv-vim/nfv_vim/directors/_sw_mgmt_director.py +++ b/nfv/nfv-vim/nfv_vim/directors/_sw_mgmt_director.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 # @@ -284,6 +284,8 @@ class SwMgmtDirector(object): if self._sw_update is not None: if self._sw_update.sw_update_type == sw_update_type: return self._sw_update.strategy + elif sw_update_type == objects.SW_UPDATE_TYPE.CURRENT_STRATEGY: + return self._sw_update.strategy return None def host_lock_failed(self, host): 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 a5aa0a95..54a613aa 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 @@ -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 # @@ -370,6 +370,8 @@ def vim_sw_update_api_get_strategy(connection, msg): sw_update_type = objects.SW_UPDATE_TYPE.KUBE_UPGRADE elif 'system-config-update' == msg.sw_update_type: sw_update_type = objects.SW_UPDATE_TYPE.SYSTEM_CONFIG_UPDATE + elif 'current-strategy' == msg.sw_update_type: + sw_update_type = objects.SW_UPDATE_TYPE.CURRENT_STRATEGY else: DLOG.error("Invalid message name: %s" % msg.sw_update_type) sw_update_type = 'unknown' diff --git a/nfv/nfv-vim/nfv_vim/objects/_sw_update.py b/nfv/nfv-vim/nfv_vim/objects/_sw_update.py index ceb501f7..378d977e 100755 --- a/nfv/nfv-vim/nfv_vim/objects/_sw_update.py +++ b/nfv/nfv-vim/nfv_vim/objects/_sw_update.py @@ -33,6 +33,7 @@ class SwUpdateTypes(Constants): FW_UPDATE = Constant('fw-update') KUBE_ROOTCA_UPDATE = Constant('kube-rootca-update') KUBE_UPGRADE = Constant('kube-upgrade') + CURRENT_STRATEGY = Constant('current-strategy') @six.add_metaclass(Singleton)