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:
albailey 2020-03-09 10:22:47 -05:00
parent 6d3215fa44
commit 826e167d5e
11 changed files with 682 additions and 40 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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