NFV API to list current strategy type and state.

This new NFV API will list the current running
Strategy type and its state.

Test Plan:
PASSED: On a DX system, Create a strategy of any type.
API should return the strategy type and state.
PASSED: On a DX system, there are no existing strategies.
API returns none.
PASSED: Create a Strategy of any type, use REST API
to get the current active strategy(sample output in
comments section).
PASSED: Orchestrated k8s upgrade with the changes,
(sample output in the comments section).
PASSED: Performed three consecutive k8s upgrade
v1.24.4 - v1.25.3 - v1.26.1 - v1.27.5

Story: 2011045
Task: 49580

Change-Id: I2e367ccb5f9ff42aa0d912598fb1617a4a7ae0ee
Signed-off-by: Vanathi.Selvaraju <vanathi.selvaraju@windriver.com>
This commit is contained in:
Vanathi.Selvaraju 2024-02-15 16:02:28 -05:00 committed by Vanathi Selvaraju
parent e85f7905c2
commit bac2f0a09e
10 changed files with 237 additions and 9 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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,

View File

@ -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)

View File

@ -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):

View File

@ -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'

View File

@ -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)