Subcloud Group support for dcmanager CLI
Added CLI calls for: dcmanager subcloud-group add subcloud-group delete subcloud-group list subcloud-group show subcloud-group update subcloud-group list-subclouds Update subcloud API calls (create, update and detailed list) to include support for subcloud group. Added unit tests for covering the new and changed CLI commands Change-Id: I943a1ce828a4c7a1ba6092ec49b642f19179a598 Depends-On: https://review.opendev.org/#/c/714759 Story: 2007518 Task: 39302 Signed-off-by: albailey <Al.Bailey@windriver.com>
This commit is contained in:
parent
6d3215fa44
commit
826e167d5e
@ -36,8 +36,8 @@ LOG = logging.getLogger(__name__)
|
||||
def log_request(func):
|
||||
def decorator(self, *args, **kwargs):
|
||||
resp = func(self, *args, **kwargs)
|
||||
LOG.debug("HTTP %s %s %d" % (resp.request.method, resp.url,
|
||||
resp.status_code))
|
||||
LOG.debug("HTTP %s %s %d %s" % (resp.request.method, resp.url,
|
||||
resp.status_code, resp.text))
|
||||
return resp
|
||||
|
||||
return decorator
|
||||
|
@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# Copyright (c) 2017 Wind River Systems, Inc.
|
||||
# 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
|
||||
@ -26,6 +26,7 @@ from keystoneauth1 import session as ks_session
|
||||
|
||||
from dcmanagerclient.api import httpclient
|
||||
from dcmanagerclient.api.v1 import alarm_manager as am
|
||||
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_update_options_manager as suom
|
||||
@ -95,6 +96,8 @@ class Client(object):
|
||||
|
||||
# Create all managers
|
||||
self.subcloud_manager = sm.subcloud_manager(self.http_client)
|
||||
self.subcloud_group_manager = \
|
||||
gm.subcloud_group_manager(self.http_client, self.subcloud_manager)
|
||||
self.alarm_manager = am.alarm_manager(self.http_client)
|
||||
self.sw_update_manager = sum.sw_update_manager(self.http_client)
|
||||
self.sw_update_options_manager = \
|
||||
|
@ -0,0 +1,145 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
import json
|
||||
|
||||
from dcmanagerclient.api import base
|
||||
from dcmanagerclient.api.base import get_json
|
||||
|
||||
|
||||
class SubcloudGroup(base.Resource):
|
||||
resource_name = 'subcloud_group'
|
||||
|
||||
def __init__(self,
|
||||
manager,
|
||||
group_id,
|
||||
name,
|
||||
description,
|
||||
update_apply_type,
|
||||
max_parallel_subclouds,
|
||||
created_at,
|
||||
updated_at):
|
||||
self.manager = manager
|
||||
self.group_id = group_id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.update_apply_type = update_apply_type
|
||||
self.max_parallel_subclouds = max_parallel_subclouds
|
||||
self.created_at = created_at
|
||||
self.updated_at = updated_at
|
||||
|
||||
|
||||
class subcloud_group_manager(base.ResourceManager):
|
||||
resource_class = SubcloudGroup
|
||||
|
||||
def __init__(self, http_client, subcloud_manager):
|
||||
super(subcloud_group_manager, self).__init__(http_client)
|
||||
self.subcloud_manager = subcloud_manager
|
||||
|
||||
def _json_to_resource(self, json_object):
|
||||
return self.resource_class(
|
||||
self,
|
||||
group_id=json_object['id'],
|
||||
name=json_object['name'],
|
||||
description=json_object['description'],
|
||||
update_apply_type=json_object['update_apply_type'],
|
||||
max_parallel_subclouds=json_object['max_parallel_subclouds'],
|
||||
created_at=json_object['created-at'],
|
||||
updated_at=json_object['updated-at'])
|
||||
|
||||
def subcloud_group_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._json_to_resource(json_object))
|
||||
return resource
|
||||
|
||||
def subcloud_group_update(self, url, data):
|
||||
data = json.dumps(data)
|
||||
resp = self.http_client.patch(url, data)
|
||||
if resp.status_code != 200:
|
||||
self._raise_api_exception(resp)
|
||||
json_object = get_json(resp)
|
||||
resource = list()
|
||||
resource.append(self._json_to_resource(json_object))
|
||||
return resource
|
||||
|
||||
def subcloud_group_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['subcloud_groups']
|
||||
resource = []
|
||||
for json_object in json_objects:
|
||||
resource.append(self._json_to_resource(json_object))
|
||||
return resource
|
||||
|
||||
def _subcloud_group_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._json_to_resource(json_object))
|
||||
return resource
|
||||
|
||||
def _list_subclouds_for_subcloud_group(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['subclouds']
|
||||
resource = []
|
||||
for json_object in json_objects:
|
||||
resource.append(
|
||||
self.subcloud_manager.json_to_resource(json_object))
|
||||
return resource
|
||||
|
||||
def add_subcloud_group(self, **kwargs):
|
||||
data = kwargs
|
||||
url = '/subcloud-groups/'
|
||||
return self.subcloud_group_create(url, data)
|
||||
|
||||
def list_subcloud_groups(self):
|
||||
url = '/subcloud-groups/'
|
||||
return self.subcloud_group_list(url)
|
||||
|
||||
def subcloud_group_list_subclouds(self, subcloud_group_ref):
|
||||
url = '/subcloud-groups/%s/subclouds' % subcloud_group_ref
|
||||
return self._list_subclouds_for_subcloud_group(url)
|
||||
|
||||
def subcloud_group_detail(self, subcloud_group_ref):
|
||||
url = '/subcloud-groups/%s' % subcloud_group_ref
|
||||
return self._subcloud_group_detail(url)
|
||||
|
||||
def delete_subcloud_group(self, subcloud_group_ref):
|
||||
url = '/subcloud-groups/%s' % subcloud_group_ref
|
||||
return self._delete(url)
|
||||
|
||||
def update_subcloud_group(self, subcloud_group_ref, **kwargs):
|
||||
data = kwargs
|
||||
url = '/subcloud-groups/%s' % subcloud_group_ref
|
||||
return self.subcloud_group_update(url, data)
|
@ -34,7 +34,7 @@ class Subcloud(base.Resource):
|
||||
deploy_status,
|
||||
management_subnet, management_start_ip, management_end_ip,
|
||||
management_gateway_ip, systemcontroller_gateway_ip,
|
||||
created_at, updated_at, sync_status="unknown",
|
||||
created_at, updated_at, group_id, sync_status="unknown",
|
||||
endpoint_sync_status={}):
|
||||
self.manager = manager
|
||||
self.subcloud_id = subcloud_id
|
||||
@ -53,6 +53,7 @@ class Subcloud(base.Resource):
|
||||
self.systemcontroller_gateway_ip = systemcontroller_gateway_ip
|
||||
self.created_at = created_at
|
||||
self.updated_at = updated_at
|
||||
self.group_id = group_id
|
||||
self.sync_status = sync_status
|
||||
self.endpoint_sync_status = endpoint_sync_status
|
||||
|
||||
@ -60,6 +61,27 @@ class Subcloud(base.Resource):
|
||||
class subcloud_manager(base.ResourceManager):
|
||||
resource_class = Subcloud
|
||||
|
||||
def json_to_resource(self, json_object):
|
||||
return self.resource_class(
|
||||
self,
|
||||
subcloud_id=json_object['id'],
|
||||
name=json_object['name'],
|
||||
description=json_object['description'],
|
||||
location=json_object['location'],
|
||||
software_version=json_object['software-version'],
|
||||
management_state=json_object['management-state'],
|
||||
availability_status=json_object['availability-status'],
|
||||
deploy_status=json_object['deploy-status'],
|
||||
management_subnet=json_object['management-subnet'],
|
||||
management_start_ip=json_object['management-start-ip'],
|
||||
management_end_ip=json_object['management-end-ip'],
|
||||
management_gateway_ip=json_object['management-gateway-ip'],
|
||||
systemcontroller_gateway_ip=json_object[
|
||||
'systemcontroller-gateway-ip'],
|
||||
created_at=json_object['created-at'],
|
||||
updated_at=json_object['updated-at'],
|
||||
group_id=json_object['group_id'])
|
||||
|
||||
def subcloud_create(self, url, data):
|
||||
data = json.dumps(data)
|
||||
resp = self.http_client.post(url, data)
|
||||
@ -67,25 +89,7 @@ class subcloud_manager(base.ResourceManager):
|
||||
self._raise_api_exception(resp)
|
||||
json_object = get_json(resp)
|
||||
resource = list()
|
||||
resource.append(
|
||||
self.resource_class(
|
||||
self,
|
||||
subcloud_id=json_object['id'],
|
||||
name=json_object['name'],
|
||||
description=json_object['description'],
|
||||
location=json_object['location'],
|
||||
software_version=json_object['software-version'],
|
||||
management_state=json_object['management-state'],
|
||||
availability_status=json_object['availability-status'],
|
||||
deploy_status=json_object['deploy-status'],
|
||||
management_subnet=json_object['management-subnet'],
|
||||
management_start_ip=json_object['management-start-ip'],
|
||||
management_end_ip=json_object['management-end-ip'],
|
||||
management_gateway_ip=json_object['management-gateway-ip'],
|
||||
systemcontroller_gateway_ip=json_object[
|
||||
'systemcontroller-gateway-ip'],
|
||||
created_at=json_object['created-at'],
|
||||
updated_at=json_object['updated-at']))
|
||||
resource.append(self.json_to_resource(json_object))
|
||||
return resource
|
||||
|
||||
def subcloud_update(self, url, data):
|
||||
@ -113,7 +117,8 @@ class subcloud_manager(base.ResourceManager):
|
||||
systemcontroller_gateway_ip=json_object[
|
||||
'systemcontroller-gateway-ip'],
|
||||
created_at=json_object['created-at'],
|
||||
updated_at=json_object['updated-at']))
|
||||
updated_at=json_object['updated-at'],
|
||||
group_id=json_object['group_id']))
|
||||
return resource
|
||||
|
||||
def subcloud_list(self, url):
|
||||
@ -143,6 +148,7 @@ class subcloud_manager(base.ResourceManager):
|
||||
'systemcontroller-gateway-ip'],
|
||||
created_at=json_object['created-at'],
|
||||
updated_at=json_object['updated-at'],
|
||||
group_id=json_object['group_id'],
|
||||
sync_status=json_object['sync_status'],
|
||||
endpoint_sync_status=json_object['endpoint_sync_status']))
|
||||
return resource
|
||||
@ -172,6 +178,7 @@ class subcloud_manager(base.ResourceManager):
|
||||
'systemcontroller-gateway-ip'],
|
||||
created_at=json_object['created-at'],
|
||||
updated_at=json_object['updated-at'],
|
||||
group_id=json_object['group_id'],
|
||||
endpoint_sync_status=json_object['endpoint_sync_status']))
|
||||
if detail is not None:
|
||||
resource[0].oam_floating_ip = json_object['oam_floating_ip']
|
||||
|
@ -0,0 +1,283 @@
|
||||
# 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 osc_lib.command import command
|
||||
|
||||
from dcmanagerclient.commands.v1 import base
|
||||
from dcmanagerclient.commands.v1.subcloud_manager import detail_format
|
||||
from dcmanagerclient import exceptions
|
||||
|
||||
|
||||
def group_format(subcloud_group=None):
|
||||
columns = (
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
)
|
||||
|
||||
if subcloud_group:
|
||||
data = (
|
||||
subcloud_group.group_id,
|
||||
subcloud_group.name,
|
||||
subcloud_group.description,
|
||||
)
|
||||
|
||||
else:
|
||||
data = (tuple('<none>' for _ in range(len(columns))),)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def detail_group_format(subcloud_group=None):
|
||||
# Include all the fields in group_format
|
||||
# plus some additional fields
|
||||
columns = (
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
'update apply type',
|
||||
'max parallel subclouds',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
)
|
||||
|
||||
if subcloud_group:
|
||||
data = (
|
||||
subcloud_group.group_id,
|
||||
subcloud_group.name,
|
||||
subcloud_group.description,
|
||||
subcloud_group.update_apply_type,
|
||||
subcloud_group.max_parallel_subclouds,
|
||||
subcloud_group.created_at,
|
||||
subcloud_group.updated_at,
|
||||
)
|
||||
else:
|
||||
data = (tuple('<none>' for _ in range(len(columns))),)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
class AddSubcloudGroup(base.DCManagerShowOne):
|
||||
"""Add a new subcloud group."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return detail_group_format
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(AddSubcloudGroup, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
required=True,
|
||||
help='Name for the new subcloud group.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
required=False,
|
||||
default='No description provided',
|
||||
help='Description of new subcloud group.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--update_apply_type',
|
||||
required=False,
|
||||
default='parallel',
|
||||
help='apply type for the new subcloud group.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--max_parallel_subclouds',
|
||||
required=False,
|
||||
default=2,
|
||||
help='max parallel subclouds for the new subcloud group.'
|
||||
)
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
dcmanager_client = self.app.client_manager.subcloud_group_manager
|
||||
kwargs = dict()
|
||||
|
||||
if parsed_args.name is not None:
|
||||
kwargs['name'] = parsed_args.name
|
||||
|
||||
if parsed_args.description is not None:
|
||||
kwargs['description'] = parsed_args.description
|
||||
|
||||
if parsed_args.update_apply_type is not None:
|
||||
kwargs['update_apply_type'] = parsed_args.update_apply_type
|
||||
|
||||
if parsed_args.max_parallel_subclouds is not None:
|
||||
kwargs['max_parallel_subclouds'] = \
|
||||
parsed_args.max_parallel_subclouds
|
||||
return dcmanager_client.subcloud_group_manager.add_subcloud_group(
|
||||
**kwargs)
|
||||
|
||||
|
||||
class ListSubcloudGroup(base.DCManagerLister):
|
||||
"""List subcloud groups."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return group_format
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListSubcloudGroup, self).get_parser(prog_name)
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
dcmanager_client = self.app.client_manager.subcloud_group_manager
|
||||
return dcmanager_client.subcloud_group_manager.list_subcloud_groups()
|
||||
|
||||
|
||||
class ListSubcloudGroupSubclouds(base.DCManagerLister):
|
||||
"""List subclouds referencing a subcloud group."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return detail_format
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListSubcloudGroupSubclouds, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'group',
|
||||
help='Name or ID of subcloud group to list associated subclouds.'
|
||||
)
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
subcloud_group_ref = parsed_args.group
|
||||
dcmanager_client = self.app.client_manager.subcloud_group_manager
|
||||
return dcmanager_client.subcloud_group_manager. \
|
||||
subcloud_group_list_subclouds(subcloud_group_ref)
|
||||
|
||||
|
||||
class ShowSubcloudGroup(base.DCManagerShowOne):
|
||||
"""Show the details of a subcloud group."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return detail_group_format
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowSubcloudGroup, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'group',
|
||||
help='Name or ID of subcloud group to view the details.'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
subcloud_group_ref = parsed_args.group
|
||||
dcmanager_client = self.app.client_manager.subcloud_group_manager
|
||||
return dcmanager_client.subcloud_group_manager.\
|
||||
subcloud_group_detail(subcloud_group_ref)
|
||||
|
||||
|
||||
class DeleteSubcloudGroup(command.Command):
|
||||
"""Delete subcloud group details from the database."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteSubcloudGroup, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'group',
|
||||
help='Name or ID of the subcloud group to delete.'
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
subcloud_group_ref = parsed_args.group
|
||||
dcmanager_client = self.app.client_manager.subcloud_group_manager
|
||||
try:
|
||||
dcmanager_client.subcloud_group_manager.\
|
||||
delete_subcloud_group(subcloud_group_ref)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
msg = "Unable to delete subcloud group %s" % (subcloud_group_ref)
|
||||
raise exceptions.DCManagerClientException(msg)
|
||||
|
||||
|
||||
class UpdateSubcloudGroup(base.DCManagerShowOne):
|
||||
"""Update attributes of a subcloud group."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return detail_group_format
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UpdateSubcloudGroup, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'group',
|
||||
help='Name or ID of the subcloud group to update.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
required=False,
|
||||
help='Name of subcloud group.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
required=False,
|
||||
help='Description of subcloud group.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--update_apply_type',
|
||||
required=False,
|
||||
help='Update apply type of subcloud group.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--max_parallel_subclouds',
|
||||
type=int,
|
||||
required=False,
|
||||
help='max parallel subclouds of subcloud group.'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
subcloud_group_ref = parsed_args.group
|
||||
dcmanager_client = self.app.client_manager.subcloud_group_manager
|
||||
kwargs = dict()
|
||||
if parsed_args.name:
|
||||
kwargs['name'] = parsed_args.name
|
||||
if parsed_args.description:
|
||||
kwargs['description'] = parsed_args.description
|
||||
if parsed_args.update_apply_type:
|
||||
kwargs['update_apply_type'] = parsed_args.update_apply_type
|
||||
if parsed_args.max_parallel_subclouds:
|
||||
kwargs['max_parallel_subclouds'] = \
|
||||
parsed_args.max_parallel_subclouds
|
||||
if len(kwargs) == 0:
|
||||
error_msg = "Nothing to update"
|
||||
raise exceptions.DCManagerClientException(error_msg)
|
||||
|
||||
try:
|
||||
return dcmanager_client. \
|
||||
subcloud_group_manager.update_subcloud_group(
|
||||
subcloud_group_ref, **kwargs)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
msg = "Unable to update subcloud group %s" % (subcloud_group_ref)
|
||||
raise exceptions.DCManagerClientException(msg)
|
@ -71,6 +71,7 @@ def detail_format(subcloud=None):
|
||||
'management_end_ip',
|
||||
'management_gateway_ip',
|
||||
'systemcontroller_gateway_ip',
|
||||
'group_id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
)
|
||||
@ -90,6 +91,7 @@ def detail_format(subcloud=None):
|
||||
subcloud.management_end_ip,
|
||||
subcloud.management_gateway_ip,
|
||||
subcloud.systemcontroller_gateway_ip,
|
||||
subcloud.group_id,
|
||||
subcloud.created_at,
|
||||
subcloud.updated_at,
|
||||
)
|
||||
@ -170,6 +172,12 @@ class AddSubcloud(base.DCManagerShowOne):
|
||||
help='bmc password of the subcloud to be configured, '
|
||||
'if not provided you will be prompted.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--group',
|
||||
required=False,
|
||||
help='Name or ID of subcloud group.'
|
||||
)
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
@ -255,6 +263,9 @@ class AddSubcloud(base.DCManagerShowOne):
|
||||
kwargs["bmc_password"] = password
|
||||
break
|
||||
|
||||
if parsed_args.group is not None:
|
||||
kwargs['group_id'] = parsed_args.group
|
||||
|
||||
return dcmanager_client.subcloud_manager.add_subcloud(**kwargs)
|
||||
|
||||
|
||||
@ -413,6 +424,12 @@ class UpdateSubcloud(base.DCManagerShowOne):
|
||||
help='Location of subcloud.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--group',
|
||||
required=False,
|
||||
help='Name or ID of subcloud group.'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
@ -423,6 +440,8 @@ class UpdateSubcloud(base.DCManagerShowOne):
|
||||
kwargs['description'] = parsed_args.description
|
||||
if parsed_args.location:
|
||||
kwargs['location'] = parsed_args.location
|
||||
if parsed_args.group:
|
||||
kwargs['group_id'] = parsed_args.group
|
||||
if len(kwargs) == 0:
|
||||
error_msg = "Nothing to update"
|
||||
raise exceptions.DCManagerClientException(error_msg)
|
||||
|
@ -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) 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
|
||||
@ -37,6 +37,7 @@ from osc_lib.command import command
|
||||
|
||||
import argparse
|
||||
from dcmanagerclient.commands.v1 import alarm_manager as am
|
||||
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_update_manager as sum
|
||||
from dcmanagerclient.commands.v1 import sw_update_options_manager as suom
|
||||
@ -444,6 +445,7 @@ class DCManagerShell(app.App):
|
||||
'ClientManager',
|
||||
(object,),
|
||||
dict(subcloud_manager=self.client,
|
||||
subcloud_group_manager=self.client,
|
||||
alarm_manager=self.client,
|
||||
sw_update_manager=self.client,
|
||||
strategy_step_manager=self.client,
|
||||
@ -480,6 +482,12 @@ class DCManagerShell(app.App):
|
||||
'subcloud unmanage': sm.UnmanageSubcloud,
|
||||
'subcloud manage': sm.ManageSubcloud,
|
||||
'subcloud update': sm.UpdateSubcloud,
|
||||
'subcloud-group add': gm.AddSubcloudGroup,
|
||||
'subcloud-group delete': gm.DeleteSubcloudGroup,
|
||||
'subcloud-group list': gm.ListSubcloudGroup,
|
||||
'subcloud-group list-subclouds': gm.ListSubcloudGroupSubclouds,
|
||||
'subcloud-group show': gm.ShowSubcloudGroup,
|
||||
'subcloud-group update': gm.UpdateSubcloudGroup,
|
||||
'alarm summary': am.ListAlarmSummary,
|
||||
'patch-strategy create': sum.CreatePatchStrategy,
|
||||
'patch-strategy delete': sum.DeletePatchStrategy,
|
||||
|
@ -33,6 +33,7 @@ class FakeResponse(object):
|
||||
self.status_code = status_code
|
||||
self.content = content
|
||||
self.headers = {}
|
||||
self.text = ''
|
||||
|
||||
def json(self):
|
||||
return json.loads(self.content)
|
||||
|
@ -70,6 +70,7 @@ class FakeResponse(object):
|
||||
self.request = FakeRequest(method)
|
||||
self.url = url
|
||||
self.status_code = status_code
|
||||
self.text = ''
|
||||
|
||||
|
||||
class HTTPClientTest(testtools.TestCase):
|
||||
|
@ -0,0 +1,161 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
import copy
|
||||
import mock
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from dcmanagerclient.api.v1 import subcloud_group_manager as zm
|
||||
from dcmanagerclient.commands.v1 \
|
||||
import subcloud_group_manager as subcloud_group_cmd
|
||||
from dcmanagerclient.tests import base
|
||||
from dcmanagerclient.tests.v1 import test_subcloud_manager as tsm
|
||||
|
||||
|
||||
ID = '2'
|
||||
NAME = 'GroupX'
|
||||
DESCRIPTION = 'Custom subcloud group'
|
||||
APPLY_TYPE = 'parallel'
|
||||
MAX_PARALLEL_SUBCLOUDS = 3
|
||||
TIME_NOW = timeutils.utcnow().isoformat()
|
||||
NEW_DESCRIPTION = 'Slightly different subcloud group'
|
||||
|
||||
SUBCLOUD_GROUP_DICT = {
|
||||
'GROUP_ID': ID,
|
||||
'NAME': NAME,
|
||||
'DESCRIPTION': DESCRIPTION,
|
||||
'APPLY_TYPE': APPLY_TYPE,
|
||||
'MAX_PARALLEL_SUBCLOUDS': MAX_PARALLEL_SUBCLOUDS,
|
||||
'CREATED_AT': TIME_NOW,
|
||||
'UPDATED_AT': TIME_NOW
|
||||
}
|
||||
|
||||
SUBCLOUD_GROUP = zm.SubcloudGroup(
|
||||
mock,
|
||||
group_id=SUBCLOUD_GROUP_DICT['GROUP_ID'],
|
||||
name=SUBCLOUD_GROUP_DICT['NAME'],
|
||||
description=SUBCLOUD_GROUP_DICT['DESCRIPTION'],
|
||||
update_apply_type=SUBCLOUD_GROUP_DICT['APPLY_TYPE'],
|
||||
max_parallel_subclouds=SUBCLOUD_GROUP_DICT['MAX_PARALLEL_SUBCLOUDS'],
|
||||
created_at=SUBCLOUD_GROUP_DICT['CREATED_AT'],
|
||||
updated_at=SUBCLOUD_GROUP_DICT['UPDATED_AT']
|
||||
)
|
||||
|
||||
|
||||
class TestCLISubcloudGroupManagerV1(base.BaseCommandTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCLISubcloudGroupManagerV1, self).setUp()
|
||||
# The client is the subcloud_group_manager
|
||||
self.client = self.app.client_manager.subcloud_group_manager
|
||||
|
||||
def test_list_subcloud_groups(self):
|
||||
self.client.subcloud_group_manager.\
|
||||
list_subcloud_groups.return_value = [SUBCLOUD_GROUP]
|
||||
actual_call = self.call(subcloud_group_cmd.ListSubcloudGroup)
|
||||
self.assertEqual([(ID, NAME, DESCRIPTION)],
|
||||
actual_call[1])
|
||||
|
||||
def test_list_subcloud_groups_empty(self):
|
||||
self.client.subcloud_group_manager.\
|
||||
list_subcloud_groups.return_value = []
|
||||
actual_call = self.call(subcloud_group_cmd.ListSubcloudGroup)
|
||||
self.assertEqual((('<none>', '<none>', '<none>'),),
|
||||
actual_call[1])
|
||||
|
||||
def test_list_subcloud_group_subclouds(self):
|
||||
self.client.subcloud_group_manager.\
|
||||
subcloud_group_list_subclouds.return_value = [tsm.SUBCLOUD]
|
||||
actual_call = self.call(subcloud_group_cmd.ListSubcloudGroupSubclouds,
|
||||
app_args=[ID])
|
||||
self.client.subcloud_group_manager.subcloud_group_list_subclouds.\
|
||||
assert_called_once_with(ID)
|
||||
self.assertEqual([tsm.DEFAULT_SUBCLOUD_FIELD_RESULT_LIST],
|
||||
actual_call[1])
|
||||
|
||||
def test_delete_subcloud_group_by_id(self):
|
||||
self.call(subcloud_group_cmd.DeleteSubcloudGroup, app_args=[ID])
|
||||
self.client.subcloud_group_manager.delete_subcloud_group.\
|
||||
assert_called_once_with(ID)
|
||||
|
||||
def test_delete_subcloud_group_without_id(self):
|
||||
self.assertRaises(SystemExit, self.call,
|
||||
subcloud_group_cmd.DeleteSubcloudGroup, app_args=[])
|
||||
|
||||
def test_show_subcloud_group_with_id(self):
|
||||
self.client.subcloud_group_manager.subcloud_group_detail.\
|
||||
return_value = [SUBCLOUD_GROUP]
|
||||
actual_call = self.call(subcloud_group_cmd.ShowSubcloudGroup,
|
||||
app_args=[ID])
|
||||
self.assertEqual((ID,
|
||||
NAME,
|
||||
DESCRIPTION,
|
||||
APPLY_TYPE,
|
||||
MAX_PARALLEL_SUBCLOUDS,
|
||||
TIME_NOW,
|
||||
TIME_NOW),
|
||||
actual_call[1])
|
||||
|
||||
def test_show_subcloud_group_without_id(self):
|
||||
self.client.subcloud_group_manager.subcloud_group_detail.\
|
||||
return_value = []
|
||||
actual_call = self.call(subcloud_group_cmd.ShowSubcloudGroup,
|
||||
app_args=[ID])
|
||||
self.assertEqual((('<none>', '<none>', '<none>', '<none>',
|
||||
'<none>', '<none>', '<none>'),),
|
||||
actual_call[1])
|
||||
|
||||
def test_add_subcloud_group(self):
|
||||
self.client.subcloud_group_manager.add_subcloud_group.\
|
||||
return_value = [SUBCLOUD_GROUP]
|
||||
|
||||
actual_call = self.call(
|
||||
subcloud_group_cmd.AddSubcloudGroup,
|
||||
app_args=['--name', NAME,
|
||||
'--description', DESCRIPTION]
|
||||
)
|
||||
self.assertEqual((ID,
|
||||
NAME,
|
||||
DESCRIPTION,
|
||||
APPLY_TYPE,
|
||||
MAX_PARALLEL_SUBCLOUDS,
|
||||
TIME_NOW,
|
||||
TIME_NOW),
|
||||
actual_call[1])
|
||||
|
||||
def test_update_subcloud_group(self):
|
||||
UPDATED_SUBCLOUD = copy.copy(SUBCLOUD_GROUP)
|
||||
UPDATED_SUBCLOUD.description = NEW_DESCRIPTION
|
||||
self.client.subcloud_group_manager.update_subcloud_group.\
|
||||
return_value = [UPDATED_SUBCLOUD]
|
||||
actual_call = self.call(
|
||||
subcloud_group_cmd.UpdateSubcloudGroup,
|
||||
app_args=[SUBCLOUD_GROUP.group_id,
|
||||
'--description', NEW_DESCRIPTION])
|
||||
self.assertEqual((ID,
|
||||
NAME,
|
||||
NEW_DESCRIPTION,
|
||||
APPLY_TYPE,
|
||||
MAX_PARALLEL_SUBCLOUDS,
|
||||
TIME_NOW,
|
||||
TIME_NOW),
|
||||
actual_call[1])
|
@ -51,6 +51,7 @@ SYSTEMCONTROLLER_GATEWAY_IP = '192.168.204.101'
|
||||
EXTERNAL_OAM_SUBNET = "10.10.10.0/24"
|
||||
EXTERNAL_OAM_GATEWAY_ADDRESS = "10.10.10.1"
|
||||
EXTERNAL_OAM_FLOATING_ADDRESS = "10.10.10.12"
|
||||
DEFAULT_SUBCLOUD_GROUP_ID = '1'
|
||||
|
||||
SUBCLOUD_DICT = {
|
||||
'SUBCLOUD_ID': ID,
|
||||
@ -68,6 +69,7 @@ SUBCLOUD_DICT = {
|
||||
'SYSTEMCONTROLLER_GATEWAY_IP': SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
'CREATED_AT': TIME_NOW,
|
||||
'UPDATED_AT': TIME_NOW,
|
||||
'GROUP_ID': DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
'OAM_FLOATING_IP': EXTERNAL_OAM_FLOATING_ADDRESS
|
||||
}
|
||||
|
||||
@ -87,7 +89,26 @@ SUBCLOUD = sm.Subcloud(
|
||||
management_gateway_ip=SUBCLOUD_DICT['MANAGEMENT_GATEWAY_IP'],
|
||||
systemcontroller_gateway_ip=SUBCLOUD_DICT['SYSTEMCONTROLLER_GATEWAY_IP'],
|
||||
created_at=SUBCLOUD_DICT['CREATED_AT'],
|
||||
updated_at=SUBCLOUD_DICT['UPDATED_AT'])
|
||||
updated_at=SUBCLOUD_DICT['UPDATED_AT'],
|
||||
group_id=SUBCLOUD_DICT['GROUP_ID'])
|
||||
|
||||
DEFAULT_SUBCLOUD_FIELD_RESULT_LIST = (
|
||||
ID,
|
||||
NAME,
|
||||
DESCRIPTION,
|
||||
LOCATION,
|
||||
SOFTWARE_VERSION,
|
||||
MANAGEMENT_STATE,
|
||||
AVAILABILITY_STATUS,
|
||||
DEPLOY_STATUS,
|
||||
MANAGEMENT_SUBNET,
|
||||
MANAGEMENT_START_IP,
|
||||
MANAGEMENT_END_IP,
|
||||
MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
TIME_NOW,
|
||||
TIME_NOW)
|
||||
|
||||
|
||||
class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
@ -119,19 +140,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
self.client.subcloud_manager.subcloud_detail.\
|
||||
return_value = [SUBCLOUD]
|
||||
actual_call = self.call(subcloud_cmd.ShowSubcloud, app_args=[ID])
|
||||
self.assertEqual((ID, NAME,
|
||||
DESCRIPTION,
|
||||
LOCATION,
|
||||
SOFTWARE_VERSION,
|
||||
MANAGEMENT_STATE,
|
||||
AVAILABILITY_STATUS,
|
||||
DEPLOY_STATUS,
|
||||
MANAGEMENT_SUBNET,
|
||||
MANAGEMENT_START_IP,
|
||||
MANAGEMENT_END_IP,
|
||||
MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
TIME_NOW, TIME_NOW),
|
||||
self.assertEqual(DEFAULT_SUBCLOUD_FIELD_RESULT_LIST,
|
||||
actual_call[1])
|
||||
|
||||
def test_show_subcloud_with_additional_detail(self):
|
||||
@ -155,6 +164,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
MANAGEMENT_END_IP,
|
||||
MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
TIME_NOW, TIME_NOW,
|
||||
EXTERNAL_OAM_FLOATING_ADDRESS),
|
||||
actual_call[1])
|
||||
@ -165,7 +175,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
self.assertEqual((('<none>', '<none>', '<none>', '<none>',
|
||||
'<none>', '<none>', '<none>', '<none>',
|
||||
'<none>', '<none>', '<none>', '<none>',
|
||||
'<none>', '<none>', '<none>'),),
|
||||
'<none>', '<none>', '<none>', '<none>'),),
|
||||
actual_call[1])
|
||||
|
||||
@mock.patch('getpass.getpass', return_value='testpassword')
|
||||
@ -200,6 +210,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
MANAGEMENT_SUBNET, MANAGEMENT_START_IP,
|
||||
MANAGEMENT_END_IP, MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
TIME_NOW, TIME_NOW), actual_call[1])
|
||||
|
||||
def test_unmanage_subcloud(self):
|
||||
@ -214,6 +225,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
MANAGEMENT_SUBNET, MANAGEMENT_START_IP,
|
||||
MANAGEMENT_END_IP, MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
TIME_NOW, TIME_NOW), actual_call[1])
|
||||
|
||||
def test_unmanage_subcloud_without_subcloud_id(self):
|
||||
@ -232,6 +244,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
MANAGEMENT_SUBNET, MANAGEMENT_START_IP,
|
||||
MANAGEMENT_END_IP, MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
TIME_NOW, TIME_NOW), actual_call[1])
|
||||
|
||||
def test_manage_subcloud_without_subcloud_id(self):
|
||||
@ -253,4 +266,5 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
|
||||
MANAGEMENT_SUBNET, MANAGEMENT_START_IP,
|
||||
MANAGEMENT_END_IP, MANAGEMENT_GATEWAY_IP,
|
||||
SYSTEMCONTROLLER_GATEWAY_IP,
|
||||
DEFAULT_SUBCLOUD_GROUP_ID,
|
||||
TIME_NOW, TIME_NOW), actual_call[1])
|
||||
|
Loading…
Reference in New Issue
Block a user