Adding upgrade strategy commands

dcmanager strategy-config
dcmanager upgrade-strategy

This change refactors the existing sw-update code so that
patch and upgrades share common functionality.

This adds the strategy 'type' to the CLI output so that a
user can differentiate between which strategy type is
being orchestrated.

patch-strategy-config is generic to all update types, so a new
strategy-config CLI command is now registered.

Change-Id: Icd33eb26f907e8e250ebddbba7d2cebea3592ac7
Depends-On: https://review.opendev.org/#/c/721620
Story: 2007403
Task: 39654
Signed-off-by: albailey <Al.Bailey@windriver.com>
This commit is contained in:
albailey 2020-04-14 15:00:01 -05:00
parent 19f027179c
commit c640a51440
12 changed files with 592 additions and 206 deletions

View File

@ -20,23 +20,22 @@
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import six
import keystoneauth1.identity.generic as auth_plugin
from keystoneauth1 import session as ks_session
import osprofiler.profiler
from dcmanagerclient.api import httpclient
from dcmanagerclient.api.v1 import alarm_manager as am
from dcmanagerclient.api.v1 import fw_update_manager as fum
from dcmanagerclient.api.v1 import strategy_step_manager as ssm
from dcmanagerclient.api.v1 import subcloud_deploy_manager as sdm
from dcmanagerclient.api.v1 import subcloud_group_manager as gm
from dcmanagerclient.api.v1 import subcloud_manager as sm
from dcmanagerclient.api.v1 import sw_update_manager as sum
from dcmanagerclient.api.v1 import sw_patch_manager as spm
from dcmanagerclient.api.v1 import sw_update_options_manager as suom
import osprofiler.profiler
import six
from dcmanagerclient.api.v1 import sw_upgrade_manager as supm
_DEFAULT_DCMANAGER_URL = "http://localhost:8119/v1.0"
@ -102,11 +101,13 @@ class Client(object):
self.subcloud_deploy_manager = sdm.subcloud_deploy_manager(
self.http_client)
self.alarm_manager = am.alarm_manager(self.http_client)
self.sw_update_manager = sum.sw_update_manager(self.http_client)
self.fw_update_manager = fum.fw_update_manager(self.http_client)
self.sw_patch_manager = spm.sw_patch_manager(self.http_client)
self.sw_update_options_manager = \
suom.sw_update_options_manager(self.http_client)
self.strategy_step_manager = sum.strategy_step_manager(
self.http_client)
self.sw_upgrade_manager = supm.sw_upgrade_manager(self.http_client)
self.strategy_step_manager = \
ssm.strategy_step_manager(self.http_client)
def authenticate(dcmanager_url=None, username=None,

View File

@ -0,0 +1,32 @@
# Copyright (c) 2017 Ericsson AB.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.api.v1.sw_update_manager import sw_update_manager
SW_UPDATE_TYPE_FIRMWARE = 'firmware'
class fw_update_manager(sw_update_manager):
def __init__(self, http_client):
super(fw_update_manager, self).__init__(
http_client,
update_type=SW_UPDATE_TYPE_FIRMWARE)

View File

@ -0,0 +1,87 @@
# Copyright (c) 2017 Ericsson AB.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2017-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.api import base
from dcmanagerclient.api.base import get_json
class StrategyStep(base.Resource):
resource_name = 'strategy_step'
def __init__(self, manager, cloud, stage, state, details,
started_at, finished_at, created_at, updated_at):
self.manager = manager
self.cloud = cloud
self.stage = stage
self.state = state
self.details = details
self.started_at = started_at
self.finished_at = finished_at
self.created_at = created_at
self.updated_at = updated_at
class strategy_step_manager(base.ResourceManager):
def __init__(self, http_client):
super(strategy_step_manager, self).__init__(http_client)
self.resource_class = StrategyStep
self.steps_url = '/sw-update-strategy/steps'
self.response_key = 'strategy-steps'
def list_strategy_steps(self):
return self._strategy_step_list(self.steps_url)
def strategy_step_detail(self, cloud_name):
url = '{}/{}'.format(self.steps_url, cloud_name)
return self._strategy_step_detail(url)
def build_from_json(self, json_object):
return self.resource_class(
self,
cloud=json_object['cloud'],
stage=json_object['stage'],
state=json_object['state'],
details=json_object['details'],
started_at=json_object['started-at'],
finished_at=json_object['finished-at'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at'])
def _strategy_step_list(self, url):
resp = self.http_client.get(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_response_key = get_json(resp)
json_objects = json_response_key[self.response_key]
resource = []
for json_object in json_objects:
resource.append(self.build_from_json(json_object))
return resource
def _strategy_step_detail(self, url):
resp = self.http_client.get(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
resource = list()
resource.append(self.build_from_json(json_object))
return resource

View File

@ -0,0 +1,31 @@
# Copyright (c) 2017 Ericsson AB.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.api.v1.sw_update_manager import sw_update_manager
SW_UPDATE_TYPE_PATCH = 'patch'
class sw_patch_manager(sw_update_manager):
def __init__(self, http_client):
super(sw_patch_manager, self).__init__(
http_client,
update_type=SW_UPDATE_TYPE_PATCH)

View File

@ -26,13 +26,21 @@ from dcmanagerclient.api import base
from dcmanagerclient.api.base import get_json
# todo(abailey): Update SwUpdateStrategy based on 'subcloud group'
class SwUpdateStrategy(base.Resource):
resource_name = 'sw_update_strategy'
def __init__(self, manager, subcloud_apply_type, max_parallel_subclouds,
stop_on_failure, state,
created_at, updated_at):
def __init__(self,
manager,
strategy_type,
subcloud_apply_type,
max_parallel_subclouds,
stop_on_failure,
state,
created_at,
updated_at):
self.manager = manager
self.strategy_type = strategy_type
self.subcloud_apply_type = subcloud_apply_type
self.max_parallel_subclouds = max_parallel_subclouds
self.stop_on_failure = stop_on_failure
@ -41,169 +49,94 @@ class SwUpdateStrategy(base.Resource):
self.updated_at = updated_at
class StrategyStep(base.Resource):
resource_name = 'strategy_step'
def __init__(self, manager, cloud, stage, state, details,
started_at, finished_at, created_at, updated_at):
self.manager = manager
self.cloud = cloud
self.stage = stage
self.state = state
self.details = details
self.started_at = started_at
self.finished_at = finished_at
self.created_at = created_at
self.updated_at = updated_at
class sw_update_manager(base.ResourceManager):
resource_class = SwUpdateStrategy
"""sw_update_managea
def create_patch_strategy(self, **kwargs):
sw_update_manager is an abstract class that is used by subclasses to
manage API actions for specific update strategy types such as software
patches and firmware updates.
"""
def __init__(self, http_client,
update_type,
resource_class=SwUpdateStrategy,
url='sw-update-strategy'):
super(sw_update_manager, self).__init__(http_client)
self.resource_class = resource_class
self.update_type = update_type
# create_url is typically /<foo>/
self.create_url = '/{}/'.format(url)
# get_url is typically /<foo>
self.get_url = '/{}'.format(url)
# delete_url is typically /<foo> (same as get)
self.delete_url = '/{}'.format(url)
# actions_url is typically /<foo>/actions
self.actions_url = '/{}/actions'.format(url)
def create_sw_update_strategy(self, **kwargs):
data = kwargs
data.update({'type': 'patch'})
url = '/sw-update-strategy/'
return self.sw_update_create(url, data)
data.update({'type': self.update_type})
return self._sw_update_create(self.create_url, data)
def patch_strategy_detail(self):
url = '/sw-update-strategy'
return self.sw_update_detail(url)
def update_sw_strategy_detail(self):
return self._sw_update_detail(self.get_url)
def delete_patch_strategy(self):
url = '/sw-update-strategy'
return self.sw_update_delete(url)
def delete_sw_update_strategy(self):
return self._sw_update_delete(self.delete_url)
def apply_patch_strategy(self):
def apply_sw_update_strategy(self):
data = {'action': 'apply'}
url = '/sw-update-strategy/actions'
return self.sw_update_action(url, data)
return self._sw_update_action(self.actions_url, data)
def abort_patch_strategy(self):
def abort_sw_update_strategy(self):
data = {'action': 'abort'}
url = '/sw-update-strategy/actions'
return self.sw_update_action(url, data)
return self._sw_update_action(self.actions_url, data)
def sw_update_create(self, url, data):
def _build_from_json(self, json_object):
return self.resource_class(
self,
strategy_type=json_object['type'],
subcloud_apply_type=json_object['subcloud-apply-type'],
max_parallel_subclouds=json_object['max-parallel-subclouds'],
stop_on_failure=json_object['stop-on-failure'],
state=json_object['state'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at'])
def _sw_update_create(self, url, data):
data = json.dumps(data)
resp = self.http_client.post(url, data)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
resource = list()
resource.append(
self.resource_class(
self,
subcloud_apply_type=json_object['subcloud-apply-type'],
max_parallel_subclouds=json_object['max-parallel-subclouds'],
stop_on_failure=json_object['stop-on-failure'],
state=json_object['state'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at']))
resource.append(self._build_from_json(json_object))
return resource
def sw_update_delete(self, url):
def _sw_update_delete(self, url):
resp = self.http_client.delete(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
resource = list()
resource.append(
self.resource_class(
self,
subcloud_apply_type=json_object['subcloud-apply-type'],
max_parallel_subclouds=json_object['max-parallel-subclouds'],
stop_on_failure=json_object['stop-on-failure'],
state=json_object['state'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at']))
resource.append(self._build_from_json(json_object))
return resource
def sw_update_detail(self, url):
def _sw_update_detail(self, url):
resp = self.http_client.get(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
resource = list()
resource.append(
self.resource_class(
self,
subcloud_apply_type=json_object['subcloud-apply-type'],
max_parallel_subclouds=json_object['max-parallel-subclouds'],
stop_on_failure=json_object['stop-on-failure'],
state=json_object['state'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at']))
resource.append(self._build_from_json(json_object))
return resource
def sw_update_action(self, url, data):
def _sw_update_action(self, url, data):
data = json.dumps(data)
resp = self.http_client.post(url, data)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
resource = list()
resource.append(
self.resource_class(
self,
subcloud_apply_type=json_object['subcloud-apply-type'],
max_parallel_subclouds=json_object['max-parallel-subclouds'],
stop_on_failure=json_object['stop-on-failure'],
state=json_object['state'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at']))
return resource
class strategy_step_manager(base.ResourceManager):
resource_class = StrategyStep
def list_strategy_steps(self):
url = '/sw-update-strategy/steps'
return self.strategy_step_list(url)
def strategy_step_detail(self, cloud_name):
url = '/sw-update-strategy/steps/%s' % cloud_name
return self._strategy_step_detail(url)
def strategy_step_list(self, url):
resp = self.http_client.get(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_response_key = get_json(resp)
json_objects = json_response_key['strategy-steps']
resource = []
for json_object in json_objects:
resource.append(
self.resource_class(
self,
cloud=json_object['cloud'],
stage=json_object['stage'],
state=json_object['state'],
details=json_object['details'],
started_at=json_object['started-at'],
finished_at=json_object['finished-at'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at'],
))
return resource
def _strategy_step_detail(self, url):
resp = self.http_client.get(url)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
resource = list()
resource.append(
self.resource_class(
self,
cloud=json_object['cloud'],
stage=json_object['stage'],
state=json_object['state'],
details=json_object['details'],
started_at=json_object['started-at'],
finished_at=json_object['finished-at'],
created_at=json_object['created-at'],
updated_at=json_object['updated-at'],
))
resource.append(self._build_from_json(json_object))
return resource

View File

@ -0,0 +1,32 @@
# Copyright (c) 2017 Ericsson AB.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.api.v1.sw_update_manager import sw_update_manager
SW_UPDATE_TYPE_UPGRADE = 'upgrade'
class sw_upgrade_manager(sw_update_manager):
def __init__(self, http_client):
super(sw_upgrade_manager, self).__init__(
http_client,
update_type=SW_UPDATE_TYPE_UPGRADE)

View File

@ -0,0 +1,59 @@
# Copyright (c) 2017 Ericsson AB.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.commands.v1 import sw_update_manager
class FwUpdateManagerMixin(object):
"""This Mixin provides the update manager used for firmware updates."""
def get_sw_update_manager(self):
dcmanager_client = self.app.client_manager.fw_update_manager
return dcmanager_client.fw_update_manager
class CreateFwUpdateStrategy(FwUpdateManagerMixin,
sw_update_manager.CreateSwUpdateStrategy):
"""Create a firmware update strategy."""
pass
class ShowFwUpdateStrategy(FwUpdateManagerMixin,
sw_update_manager.ShowSwUpdateStrategy):
"""Show the details of a firmware update strategy for a subcloud."""
pass
class DeleteFwUpdateStrategy(FwUpdateManagerMixin,
sw_update_manager.DeleteSwUpdateStrategy):
"""Delete firmware update strategy from the database."""
pass
class ApplyFwUpdateStrategy(FwUpdateManagerMixin,
sw_update_manager.ApplySwUpdateStrategy):
"""Apply a firmware update strategy."""
pass
class AbortFwUpdateStrategy(FwUpdateManagerMixin,
sw_update_manager.AbortSwUpdateStrategy):
"""Abort a firmware update strategy."""
pass

View File

@ -0,0 +1,59 @@
# Copyright (c) 2017 Ericsson AB.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2017-2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.commands.v1 import sw_update_manager
class SwPatchManagerMixin(object):
"""This Mixin provides the update manager used for sw patch."""
def get_sw_update_manager(self):
dcmanager_client = self.app.client_manager.sw_patch_manager
return dcmanager_client.sw_patch_manager
class CreatePatchUpdateStrategy(SwPatchManagerMixin,
sw_update_manager.CreateSwUpdateStrategy):
"""Create a patch update strategy."""
pass
class ShowPatchUpdateStrategy(SwPatchManagerMixin,
sw_update_manager.ShowSwUpdateStrategy):
"""Show the details of a patch update strategy for a subcloud."""
pass
class DeletePatchUpdateStrategy(SwPatchManagerMixin,
sw_update_manager.DeleteSwUpdateStrategy):
"""Delete patch update strategy from the database."""
pass
class ApplyPatchUpdateStrategy(SwPatchManagerMixin,
sw_update_manager.ApplySwUpdateStrategy):
"""Apply a patch update strategy."""
pass
class AbortPatchUpdateStrategy(SwPatchManagerMixin,
sw_update_manager.AbortSwUpdateStrategy):
"""Abort a patch update strategy."""
pass

View File

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2017 Wind River Systems, Inc.
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
@ -22,9 +22,16 @@
from dcmanagerclient.commands.v1 import base
from dcmanagerclient import exceptions
# These are the abstract base classes used for sw update managers such as
# - sw-patch-manager
# - fw-update-manager
#
# also handles 'steps' and 'strategies'
def detail_format(sw_update_strategy=None):
columns = (
'strategy type',
'subcloud apply type',
'max parallel subclouds',
'stop on failure',
@ -35,6 +42,7 @@ def detail_format(sw_update_strategy=None):
if sw_update_strategy:
data = (
sw_update_strategy.strategy_type,
sw_update_strategy.subcloud_apply_type,
sw_update_strategy.max_parallel_subclouds,
sw_update_strategy.stop_on_failure,
@ -104,14 +112,18 @@ def detail_strategy_step_format(strategy_step=None):
return columns, data
class CreatePatchStrategy(base.DCManagerShowOne):
"""Create a patch strategy."""
class CreateSwUpdateStrategy(base.DCManagerShowOne):
"""Create a software update strategy."""
def get_sw_update_manager(self):
# This method must be overrridden by the concrete subclass
raise NotImplementedError
def _get_format_function(self):
return detail_format
def get_parser(self, prog_name):
parser = super(CreatePatchStrategy, self).get_parser(prog_name)
parser = super(CreateSwUpdateStrategy, self).get_parser(prog_name)
parser.add_argument(
'--subcloud-apply-type',
@ -131,20 +143,18 @@ class CreatePatchStrategy(base.DCManagerShowOne):
'--stop-on-failure',
required=False,
action='store_true',
help='Do not patch any additional subclouds after a failure.'
help='Do not update any additional subclouds after a failure.'
)
parser.add_argument(
'cloud_name',
nargs='?',
default=None,
help='Name of a single cloud to patch.'
help='Name of a single cloud to update.'
)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.sw_update_manager
kwargs = dict()
if parsed_args.subcloud_apply_type:
kwargs['subcloud-apply-type'] = parsed_args.subcloud_apply_type
@ -155,118 +165,114 @@ class CreatePatchStrategy(base.DCManagerShowOne):
kwargs['stop-on-failure'] = 'true'
if parsed_args.cloud_name is not None:
kwargs['cloud_name'] = parsed_args.cloud_name
return dcmanager_client.sw_update_manager.create_patch_strategy(
**kwargs)
return self.get_sw_update_manager().create_sw_update_strategy(**kwargs)
class ShowPatchStrategy(base.DCManagerShowOne):
"""Show the details of a patch strategy for a subcloud."""
class ShowSwUpdateStrategy(base.DCManagerShowOne):
"""Show the details of an software update strategy for a subcloud."""
def get_sw_update_manager(self):
# This method must be overrridden by the concrete subclass
raise NotImplementedError
def _get_format_function(self):
return detail_format
def get_parser(self, prog_name):
parser = super(ShowPatchStrategy, self).get_parser(prog_name)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.sw_update_manager
return dcmanager_client.sw_update_manager.patch_strategy_detail()
return self.get_sw_update_manager().update_sw_strategy_detail()
class DeletePatchStrategy(base.DCManagerShowOne):
"""Delete patch strategy from the database."""
class DeleteSwUpdateStrategy(base.DCManagerShowOne):
"""Delete a software update strategy from the database."""
def get_sw_update_manager(self):
# This method must be overrridden by the concrete subclass
raise NotImplementedError
def _get_format_function(self):
return detail_format
def get_parser(self, prog_name):
parser = super(DeletePatchStrategy, self).get_parser(prog_name)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.sw_update_manager
try:
return dcmanager_client.sw_update_manager.delete_patch_strategy()
return self.get_sw_update_manager().delete_sw_update_strategy()
except Exception as e:
print(e)
error_msg = "Unable to delete patch strategy"
error_msg = "Unable to delete sw update strategy"
raise exceptions.DCManagerClientException(error_msg)
class ApplyPatchStrategy(base.DCManagerShowOne):
"""Apply a patch strategy."""
class ApplySwUpdateStrategy(base.DCManagerShowOne):
"""Apply a software update strategy."""
def get_sw_update_manager(self):
# This method must be overrridden by the concrete subclass
raise NotImplementedError
def _get_format_function(self):
return detail_format
def get_parser(self, prog_name):
parser = super(ApplyPatchStrategy, self).get_parser(prog_name)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.sw_update_manager
try:
return dcmanager_client.sw_update_manager.apply_patch_strategy()
return self.get_sw_update_manager().apply_sw_update_strategy()
except Exception as e:
print(e)
error_msg = "Unable to apply patch strategy"
error_msg = "Unable to apply sw update strategy"
raise exceptions.DCManagerClientException(error_msg)
class AbortPatchStrategy(base.DCManagerShowOne):
"""Abort a patch strategy."""
class AbortSwUpdateStrategy(base.DCManagerShowOne):
"""Abort a software update strategy."""
def get_sw_update_manager(self):
# This method must be overrridden by the concrete subclass
raise NotImplementedError
def _get_format_function(self):
return detail_format
def get_parser(self, prog_name):
parser = super(AbortPatchStrategy, self).get_parser(prog_name)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.sw_update_manager
try:
return dcmanager_client.sw_update_manager.abort_patch_strategy()
return self.get_sw_update_manager().abort_sw_update_strategy()
except Exception as e:
print(e)
error_msg = "Unable to abort patch strategy"
error_msg = "Unable to abort sw update strategy"
raise exceptions.DCManagerClientException(error_msg)
class ListStrategyStep(base.DCManagerLister):
class ListSwUpdateStrategyStep(base.DCManagerLister):
"""List strategy steps."""
def get_strategy_step_manager(self):
dcmanager_client = self.app.client_manager.strategy_step_manager
return dcmanager_client.strategy_step_manager
def _get_format_function(self):
return strategy_step_format
def get_parser(self, prog_name):
parser = super(ListStrategyStep, self).get_parser(prog_name)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.strategy_step_manager
return dcmanager_client.strategy_step_manager.list_strategy_steps()
return self.get_strategy_step_manager().list_strategy_steps()
class ShowStrategyStep(base.DCManagerShowOne):
class ShowSwUpdateStrategyStep(base.DCManagerShowOne):
"""Show the details of a strategy step."""
def get_strategy_step_manager(self):
dcmanager_client = self.app.client_manager.strategy_step_manager
return dcmanager_client.strategy_step_manager
def _get_format_function(self):
return detail_strategy_step_format
def get_parser(self, prog_name):
parser = super(ShowStrategyStep, self).get_parser(prog_name)
parser = super(ShowSwUpdateStrategyStep, self).get_parser(prog_name)
parser.add_argument(
'cloud_name',
help='Name of cloud to view the details.'
)
return parser
def _get_resources(self, parsed_args):
cloud_name = parsed_args.cloud_name
dcmanager_client = self.app.client_manager.strategy_step_manager
return dcmanager_client.strategy_step_manager.strategy_step_detail(
return self.get_strategy_step_manager().strategy_step_detail(
cloud_name)

View File

@ -0,0 +1,59 @@
# Copyright (c) 2017 Ericsson AB.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from dcmanagerclient.commands.v1 import sw_update_manager
class SwUpgradeManagerMixin(object):
"""This Mixin provides the update manager used for software upgrades."""
def get_sw_update_manager(self):
dcmanager_client = self.app.client_manager.sw_upgrade_manager
return dcmanager_client.sw_upgrade_manager
class CreateSwUpgradeStrategy(SwUpgradeManagerMixin,
sw_update_manager.CreateSwUpdateStrategy):
"""Create a software upgrade strategy."""
pass
class ShowSwUpgradeStrategy(SwUpgradeManagerMixin,
sw_update_manager.ShowSwUpdateStrategy):
"""Show the details of a software upgrade strategy for a subcloud."""
pass
class DeleteSwUpgradeStrategy(SwUpgradeManagerMixin,
sw_update_manager.DeleteSwUpdateStrategy):
"""Delete software upgrade strategy from the database."""
pass
class ApplySwUpgradeStrategy(SwUpgradeManagerMixin,
sw_update_manager.ApplySwUpdateStrategy):
"""Apply a software upgrade strategy."""
pass
class AbortSwUpgradeStrategy(SwUpgradeManagerMixin,
sw_update_manager.AbortSwUpdateStrategy):
"""Abort a software upgrade strategy."""
pass

View File

@ -37,11 +37,14 @@ from osc_lib.command import command
import argparse
from dcmanagerclient.commands.v1 import alarm_manager as am
# from dcmanagerclient.commands.v1 import fw_update_manager as fum
from dcmanagerclient.commands.v1 import subcloud_deploy_manager as sdm
from dcmanagerclient.commands.v1 import subcloud_group_manager as gm
from dcmanagerclient.commands.v1 import subcloud_manager as sm
from dcmanagerclient.commands.v1 import sw_patch_manager as spm
from dcmanagerclient.commands.v1 import sw_update_manager as sum
from dcmanagerclient.commands.v1 import sw_update_options_manager as suom
from dcmanagerclient.commands.v1 import sw_upgrade_manager as supm
LOG = logging.getLogger(__name__)
@ -449,9 +452,11 @@ class DCManagerShell(app.App):
subcloud_group_manager=self.client,
subcloud_deploy_manager=self.client,
alarm_manager=self.client,
sw_update_manager=self.client,
fw_update_manager=self.client,
sw_patch_manager=self.client,
strategy_step_manager=self.client,
sw_update_options_manager=self.client)
sw_update_options_manager=self.client,
sw_upgrade_manager=self.client)
)
self.client_manager = ClientManager()
@ -493,17 +498,31 @@ class DCManagerShell(app.App):
'subcloud-deploy upload': sdm.SubcloudDeployUpload,
'subcloud-deploy show': sdm.SubcloudDeployShow,
'alarm summary': am.ListAlarmSummary,
'patch-strategy create': sum.CreatePatchStrategy,
'patch-strategy delete': sum.DeletePatchStrategy,
'patch-strategy apply': sum.ApplyPatchStrategy,
'patch-strategy abort': sum.AbortPatchStrategy,
'patch-strategy show': sum.ShowPatchStrategy,
'strategy-step list': sum.ListStrategyStep,
'strategy-step show': sum.ShowStrategyStep,
# 'fw-update-strategy create': fum.CreateFwUpdateStrategy,
# 'fw-update-strategy delete': fum.DeleteFwUpdateStrategy,
# 'fw-update-strategy apply': fum.ApplyFwUpdateStrategy,
# 'fw-update-strategy abort': fum.AbortFwUpdateStrategy,
# 'fw-update-strategy show': fum.ShowFwUpdateStrategy,
'patch-strategy create': spm.CreatePatchUpdateStrategy,
'patch-strategy delete': spm.DeletePatchUpdateStrategy,
'patch-strategy apply': spm.ApplyPatchUpdateStrategy,
'patch-strategy abort': spm.AbortPatchUpdateStrategy,
'patch-strategy show': spm.ShowPatchUpdateStrategy,
'strategy-step list': sum.ListSwUpdateStrategyStep,
'strategy-step show': sum.ShowSwUpdateStrategyStep,
'patch-strategy-config update': suom.UpdateSwUpdateOptions,
'patch-strategy-config list': suom.ListSwUpdateOptions,
'patch-strategy-config show': suom.ShowSwUpdateOptions,
'patch-strategy-config delete': suom.DeleteSwUpdateOptions,
'strategy-config update': suom.UpdateSwUpdateOptions,
'strategy-config list': suom.ListSwUpdateOptions,
'strategy-config show': suom.ShowSwUpdateOptions,
'strategy-config delete': suom.DeleteSwUpdateOptions,
'upgrade-strategy create': supm.CreateSwUpgradeStrategy,
'upgrade-strategy delete': supm.DeleteSwUpgradeStrategy,
'upgrade-strategy apply': supm.ApplySwUpgradeStrategy,
'upgrade-strategy abort': supm.AbortSwUpgradeStrategy,
'upgrade-strategy show': supm.ShowSwUpgradeStrategy,
}

View File

@ -0,0 +1,68 @@
# Copyright (c) 2017 Ericsson AB.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import mock
from oslo_utils import timeutils
from dcmanagerclient.api.v1.strategy_step_manager import StrategyStep
from dcmanagerclient.commands.v1 import sw_update_manager as cli_cmd
from dcmanagerclient.tests import base
TEST_CLOUD_ID = 1
TEST_STAGE = 1
TEST_STATE = 'initializing'
TEST_DETAILS = 'some details'
TIME_NOW = timeutils.utcnow().isoformat()
TEST_STARTED_AT = TIME_NOW
TEST_FINISHED_AT = TIME_NOW
TEST_CREATED_AT = TIME_NOW
TEST_UPDATED_AT = TIME_NOW
class TestCLI(base.BaseCommandTest):
def setUp(self):
super(TestCLI, self).setUp()
def test_list_strategy_steps(self):
sample_step = StrategyStep(mock,
TEST_CLOUD_ID,
TEST_STAGE,
TEST_STATE,
TEST_DETAILS,
TEST_STARTED_AT,
TEST_FINISHED_AT,
TEST_CREATED_AT,
TEST_UPDATED_AT)
results = []
results.append(sample_step)
self.app.client_manager.strategy_step_manager.strategy_step_manager.\
list_strategy_steps.return_value = results
actual_call = self.call(cli_cmd.ListSwUpdateStrategyStep)
# ListStrategyStep returns a tuple, want the second field of the tuple
result_steps = actual_call[1]
# Only 1 step
self.assertEqual(1, len(result_steps))
# The step object is a tuple based on the formatter
for step in result_steps:
self.assertEqual(TEST_CLOUD_ID, step[0])