diff options
Diffstat (limited to 'openstackclient')
26 files changed, 1623 insertions, 222 deletions
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py index ebbf7ddf..8f099cc9 100644 --- a/openstackclient/common/quota.py +++ b/openstackclient/common/quota.py @@ -154,36 +154,34 @@ class SetQuota(command.Command): if value is not None: compute_kwargs[k] = value - if parsed_args.project: - project = utils.find_resource( - identity_client.projects, - parsed_args.project, - ) - if parsed_args.quota_class: if compute_kwargs: compute_client.quota_classes.update( - project.id, + parsed_args.project, **compute_kwargs) if volume_kwargs: volume_client.quota_classes.update( - project.id, + parsed_args.project, **volume_kwargs) if network_kwargs: sys.stderr.write("Network quotas are ignored since quota class" "is not supported.") else: + project = utils.find_resource( + identity_client.projects, + parsed_args.project, + ).id if compute_kwargs: compute_client.quotas.update( - project.id, + project, **compute_kwargs) if volume_kwargs: volume_client.quotas.update( - project.id, + project, **volume_kwargs) if network_kwargs: network_client.update_quota( - project.id, + project, **network_kwargs) @@ -230,15 +228,15 @@ class ShowQuota(command.ShowOne): return project def get_compute_volume_quota(self, client, parsed_args): - project = self._get_project(parsed_args) - try: if parsed_args.quota_class: - quota = client.quota_classes.get(project) - elif parsed_args.default: - quota = client.quotas.defaults(project) + quota = client.quota_classes.get(parsed_args.project) else: - quota = client.quotas.get(project) + project = self._get_project(parsed_args) + if parsed_args.default: + quota = client.quotas.defaults(project) + else: + quota = client.quotas.get(project) except Exception as e: if type(e).__name__ == 'EndpointNotFound': return {} diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py index 31b173e1..dbf1b601 100644 --- a/openstackclient/network/v2/network.py +++ b/openstackclient/network/v2/network.py @@ -304,21 +304,66 @@ class ListNetwork(common.NetworkAndComputeLister): """List networks""" def update_parser_common(self, parser): - parser.add_argument( + router_ext_group = parser.add_mutually_exclusive_group() + router_ext_group.add_argument( '--external', action='store_true', - default=False, help=_("List external networks") ) + router_ext_group.add_argument( + '--internal', + action='store_true', + help=_("List internal networks") + ) parser.add_argument( '--long', action='store_true', - default=False, help=_("List additional fields in output") ) + parser.add_argument( + '--name', + metavar='<name>', + help=_("List networks according to their name") + ) + admin_state_group = parser.add_mutually_exclusive_group() + admin_state_group.add_argument( + '--enable', + action='store_true', + help=_("List enabled networks") + ) + admin_state_group.add_argument( + '--disable', + action='store_true', + help=_("List disabled networks") + ) + parser.add_argument( + '--project', + metavar='<project>', + help=_("List networks according to their project (name or ID)") + ) + identity_common.add_project_domain_option_to_parser(parser) + shared_group = parser.add_mutually_exclusive_group() + shared_group.add_argument( + '--share', + action='store_true', + help=_("List networks shared between projects") + ) + shared_group.add_argument( + '--no-share', + action='store_true', + help=_("List networks not shared between projects") + ) + parser.add_argument( + '--status', + metavar='<status>', + choices=['ACTIVE', 'BUILD', 'DOWN', 'ERROR'], + help=_("List networks according to their status " + "('ACTIVE', 'BUILD', 'DOWN', 'ERROR')") + ) return parser def take_action_network(self, client, parsed_args): + identity_client = self.app.client_manager.identity if parsed_args.long: columns = ( 'id', @@ -356,10 +401,36 @@ class ListNetwork(common.NetworkAndComputeLister): 'Subnets', ) + args = {} + if parsed_args.external: - args = {'router:external': True} - else: - args = {} + args['router:external'] = True + elif parsed_args.internal: + args['router:external'] = False + + if parsed_args.name is not None: + args['name'] = parsed_args.name + + if parsed_args.enable: + args['admin_state_up'] = True + elif parsed_args.disable: + args['admin_state_up'] = False + + if parsed_args.project: + project = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ) + args['tenant_id'] = project.id + + if parsed_args.share: + args['shared'] = True + elif parsed_args.no_share: + args['shared'] = False + + if parsed_args.status: + args['status'] = parsed_args.status data = client.networks(**args) diff --git a/openstackclient/network/v2/network_segment.py b/openstackclient/network/v2/network_segment.py index bedf15f7..34cac0e0 100644 --- a/openstackclient/network/v2/network_segment.py +++ b/openstackclient/network/v2/network_segment.py @@ -13,14 +13,129 @@ """Network segment action implementations""" -# TODO(rtheis): Add description and name properties when support is available. +import logging from osc_lib.command import command +from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ +LOG = logging.getLogger(__name__) + + +class CreateNetworkSegment(command.ShowOne): + """Create new network segment + + (Caution: This is a beta command and subject to change. + Use global option --os-beta-command to enable + this command) + """ + + def get_parser(self, prog_name): + parser = super(CreateNetworkSegment, self).get_parser(prog_name) + parser.add_argument( + 'name', + metavar='<name>', + help=_('New network segment name') + ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('Network segment description'), + ) + parser.add_argument( + '--physical-network', + metavar='<physical-network>', + help=_('Physical network name of this network segment'), + ) + parser.add_argument( + '--segment', + metavar='<segment>', + type=int, + help=_('Segment identifier for this network segment which is ' + 'based on the network type, VLAN ID for vlan network ' + 'type and tunnel ID for geneve, gre and vxlan network ' + 'types'), + ) + parser.add_argument( + '--network', + metavar='<network>', + required=True, + help=_('Network this network segment belongs to (name or ID)'), + ) + parser.add_argument( + '--network-type', + metavar='<network-type>', + choices=['flat', 'geneve', 'gre', 'local', 'vlan', 'vxlan'], + required=True, + help=_('Network type of this network segment ' + '(flat, geneve, gre, local, vlan or vxlan)'), + ) + return parser + + def take_action(self, parsed_args): + self.validate_os_beta_command_enabled() + client = self.app.client_manager.network + attrs = {} + attrs['name'] = parsed_args.name + attrs['network_id'] = client.find_network(parsed_args.network, + ignore_missing=False).id + attrs['network_type'] = parsed_args.network_type + if parsed_args.description is not None: + attrs['description'] = parsed_args.description + if parsed_args.physical_network is not None: + attrs['physical_network'] = parsed_args.physical_network + if parsed_args.segment is not None: + attrs['segmentation_id'] = parsed_args.segment + obj = client.create_segment(**attrs) + columns = tuple(sorted(obj.keys())) + data = utils.get_item_properties(obj, columns) + return (columns, data) + + +class DeleteNetworkSegment(command.Command): + """Delete network segment(s) + + (Caution: This is a beta command and subject to change. + Use global option --os-beta-command to enable + this command) + """ + + def get_parser(self, prog_name): + parser = super(DeleteNetworkSegment, self).get_parser(prog_name) + parser.add_argument( + 'network_segment', + metavar='<network-segment>', + nargs='+', + help=_('Network segment(s) to delete (name or ID)'), + ) + return parser + + def take_action(self, parsed_args): + self.validate_os_beta_command_enabled() + client = self.app.client_manager.network + + result = 0 + for network_segment in parsed_args.network_segment: + try: + obj = client.find_segment(network_segment, + ignore_missing=False) + client.delete_segment(obj) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete network segment with " + "ID '%(network_segment)s': %(e)s") + % {'network_segment': network_segment, 'e': e}) + + if result > 0: + total = len(parsed_args.network_segment) + msg = (_("%(result)s of %(total)s network segments failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + + class ListNetworkSegment(command.Lister): """List network segments @@ -61,12 +176,14 @@ class ListNetworkSegment(command.Lister): headers = ( 'ID', + 'Name', 'Network', 'Network Type', 'Segment', ) columns = ( 'id', + 'name', 'network_id', 'network_type', 'segmentation_id', @@ -86,6 +203,46 @@ class ListNetworkSegment(command.Lister): ) for s in data)) +class SetNetworkSegment(command.Command): + """Set network segment properties + + (Caution: This is a beta command and subject to change. + Use global option --os-beta-command to enable + this command) + """ + + def get_parser(self, prog_name): + parser = super(SetNetworkSegment, self).get_parser(prog_name) + parser.add_argument( + 'network_segment', + metavar='<network-segment>', + help=_('Network segment to modify (name or ID)'), + ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('Set network segment description'), + ) + parser.add_argument( + '--name', + metavar='<name>', + help=_('Set network segment name'), + ) + return parser + + def take_action(self, parsed_args): + self.validate_os_beta_command_enabled() + client = self.app.client_manager.network + obj = client.find_segment(parsed_args.network_segment, + ignore_missing=False) + attrs = {} + if parsed_args.description is not None: + attrs['description'] = parsed_args.description + if parsed_args.name is not None: + attrs['name'] = parsed_args.name + client.update_segment(obj, **attrs) + + class ShowNetworkSegment(command.ShowOne): """Display network segment details @@ -99,7 +256,7 @@ class ShowNetworkSegment(command.ShowOne): parser.add_argument( 'network_segment', metavar='<network-segment>', - help=_('Network segment to display (ID only)'), + help=_('Network segment to display (name or ID)'), ) return parser diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py index d30197cc..03134b8c 100644 --- a/openstackclient/network/v2/router.py +++ b/openstackclient/network/v2/router.py @@ -119,7 +119,7 @@ class AddPortToRouter(command.Command): def take_action(self, parsed_args): client = self.app.client_manager.network port = client.find_port(parsed_args.port, ignore_missing=False) - client.router_add_interface(client.find_router( + client.add_interface_to_router(client.find_router( parsed_args.router, ignore_missing=False), port_id=port.id) @@ -144,7 +144,7 @@ class AddSubnetToRouter(command.Command): client = self.app.client_manager.network subnet = client.find_subnet(parsed_args.subnet, ignore_missing=False) - client.router_add_interface( + client.add_interface_to_router( client.find_router(parsed_args.router, ignore_missing=False), subnet_id=subnet.id) @@ -324,7 +324,7 @@ class RemovePortFromRouter(command.Command): def take_action(self, parsed_args): client = self.app.client_manager.network port = client.find_port(parsed_args.port, ignore_missing=False) - client.router_remove_interface(client.find_router( + client.remove_interface_from_router(client.find_router( parsed_args.router, ignore_missing=False), port_id=port.id) @@ -349,7 +349,7 @@ class RemoveSubnetFromRouter(command.Command): client = self.app.client_manager.network subnet = client.find_subnet(parsed_args.subnet, ignore_missing=False) - client.router_remove_interface( + client.remove_interface_from_router( client.find_router(parsed_args.router, ignore_missing=False), subnet_id=subnet.id) diff --git a/openstackclient/tests/functional/base.py b/openstackclient/tests/functional/base.py index f7f0361e..298b2454 100644 --- a/openstackclient/tests/functional/base.py +++ b/openstackclient/tests/functional/base.py @@ -58,6 +58,11 @@ class TestCase(testtools.TestCase): return cls.openstack('configuration show ' + opts) @classmethod + def get_openstack_extention_names(cls): + opts = cls.get_opts(['Name']) + return cls.openstack('extension list ' + opts) + + @classmethod def get_opts(cls, fields, format='value'): return ' -f {0} {1}'.format(format, ' '.join(['-c ' + it for it in fields])) diff --git a/openstackclient/tests/functional/common/test_quota.py b/openstackclient/tests/functional/common/test_quota.py index 9687cdb0..c1de9aa9 100644 --- a/openstackclient/tests/functional/common/test_quota.py +++ b/openstackclient/tests/functional/common/test_quota.py @@ -26,8 +26,8 @@ class QuotaTests(base.TestCase): cls.get_openstack_configuration_value('auth.project_name') def test_quota_set(self): - self.openstack('quota set --instances 11 --volumes 11 --networks 11 ' - + self.PROJECT_NAME) + self.openstack('quota set --instances 11 --volumes 11 --networks 11 ' + + self.PROJECT_NAME) opts = self.get_opts(self.EXPECTED_FIELDS) raw_output = self.openstack('quota show ' + self.PROJECT_NAME + opts) self.assertEqual("11\n11\n11\n", raw_output) @@ -51,3 +51,12 @@ class QuotaTests(base.TestCase): raw_output = self.openstack('quota show --class') for expected_field in self.EXPECTED_CLASS_FIELDS: self.assertIn(expected_field, raw_output) + + def test_quota_class_set(self): + class_name = 'default' + class_expected_fields = ['instances', 'volumes'] + self.openstack('quota set --instances 11 --volumes 11 --class ' + + class_name) + opts = self.get_opts(class_expected_fields) + raw_output = self.openstack('quota show --class ' + class_name + opts) + self.assertEqual("11\n11\n", raw_output) diff --git a/openstackclient/tests/functional/network/v2/test_network_segment.py b/openstackclient/tests/functional/network/v2/test_network_segment.py index f871e88e..de5aef96 100644 --- a/openstackclient/tests/functional/network/v2/test_network_segment.py +++ b/openstackclient/tests/functional/network/v2/test_network_segment.py @@ -10,20 +10,18 @@ # License for the specific language governing permissions and limitations # under the License. -import testtools import uuid from openstackclient.tests.functional import base -# NOTE(rtheis): Routed networks is still a WIP and not enabled by default. -@testtools.skip("bp/routed-networks") class NetworkSegmentTests(base.TestCase): """Functional tests for network segment. """ NETWORK_NAME = uuid.uuid4().hex PHYSICAL_NETWORK_NAME = uuid.uuid4().hex NETWORK_SEGMENT_ID = None NETWORK_ID = None + NETWORK_SEGMENT_EXTENSION = None @classmethod def setUpClass(cls): @@ -32,29 +30,75 @@ class NetworkSegmentTests(base.TestCase): raw_output = cls.openstack('network create ' + cls.NETWORK_NAME + opts) cls.NETWORK_ID = raw_output.strip('\n') - # Get the segment for the network. - opts = cls.get_opts(['ID', 'Network']) - raw_output = cls.openstack('--os-beta-command ' - 'network segment list ' - ' --network ' + cls.NETWORK_NAME + - ' ' + opts) - raw_output_row = raw_output.split('\n')[0] - cls.NETWORK_SEGMENT_ID = raw_output_row.split(' ')[0] + # NOTE(rtheis): The segment extension is not yet enabled by default. + # Skip the tests if not enabled. + extensions = cls.get_openstack_extention_names() + if 'Segment' in extensions: + cls.NETWORK_SEGMENT_EXTENSION = 'Segment' + + if cls.NETWORK_SEGMENT_EXTENSION: + # Get the segment for the network. + opts = cls.get_opts(['ID', 'Network']) + raw_output = cls.openstack('--os-beta-command ' + 'network segment list ' + ' --network ' + cls.NETWORK_NAME + + ' ' + opts) + raw_output_row = raw_output.split('\n')[0] + cls.NETWORK_SEGMENT_ID = raw_output_row.split(' ')[0] @classmethod def tearDownClass(cls): raw_output = cls.openstack('network delete ' + cls.NETWORK_NAME) cls.assertOutput('', raw_output) + def test_network_segment_create_delete(self): + if self.NETWORK_SEGMENT_EXTENSION: + opts = self.get_opts(['id']) + raw_output = self.openstack( + '--os-beta-command' + + ' network segment create --network ' + self.NETWORK_ID + + ' --network-type geneve ' + + ' --segment 2055 test_segment ' + opts + ) + network_segment_id = raw_output.strip('\n') + raw_output = self.openstack('--os-beta-command ' + + 'network segment delete ' + + network_segment_id) + self.assertOutput('', raw_output) + else: + self.skipTest('Segment extension disabled') + def test_network_segment_list(self): - opts = self.get_opts(['ID']) - raw_output = self.openstack('--os-beta-command ' - 'network segment list' + opts) - self.assertIn(self.NETWORK_SEGMENT_ID, raw_output) + if self.NETWORK_SEGMENT_EXTENSION: + opts = self.get_opts(['ID']) + raw_output = self.openstack('--os-beta-command ' + 'network segment list' + opts) + self.assertIn(self.NETWORK_SEGMENT_ID, raw_output) + else: + self.skipTest('Segment extension disabled') + + def test_network_segment_set(self): + if self.NETWORK_SEGMENT_EXTENSION: + new_description = 'new_description' + raw_output = self.openstack('--os-beta-command ' + 'network segment set ' + + '--description ' + new_description + + ' ' + self.NETWORK_SEGMENT_ID) + self.assertOutput('', raw_output) + opts = self.get_opts(['description']) + raw_output = self.openstack('--os-beta-command ' + 'network segment show ' + + self.NETWORK_SEGMENT_ID + opts) + self.assertEqual(new_description + "\n", raw_output) + else: + self.skipTest('Segment extension disabled') def test_network_segment_show(self): - opts = self.get_opts(['network_id']) - raw_output = self.openstack('--os-beta-command ' - 'network segment show ' + - self.NETWORK_SEGMENT_ID + opts) - self.assertEqual(self.NETWORK_ID + "\n", raw_output) + if self.NETWORK_SEGMENT_EXTENSION: + opts = self.get_opts(['network_id']) + raw_output = self.openstack('--os-beta-command ' + 'network segment show ' + + self.NETWORK_SEGMENT_ID + opts) + self.assertEqual(self.NETWORK_ID + "\n", raw_output) + else: + self.skipTest('Segment extension disabled') diff --git a/openstackclient/tests/functional/volume/v1/test_transfer_request.py b/openstackclient/tests/functional/volume/v1/test_transfer_request.py index d8406b02..e03cd717 100644 --- a/openstackclient/tests/functional/volume/v1/test_transfer_request.py +++ b/openstackclient/tests/functional/volume/v1/test_transfer_request.py @@ -47,7 +47,45 @@ class TransferRequestTests(common.BaseVolumeTests): cls.assertOutput('', raw_output_transfer) cls.assertOutput('', raw_output_volume) + def test_volume_transfer_request_accept(self): + volume_name = uuid.uuid4().hex + name = uuid.uuid4().hex + + # create a volume + opts = self.get_opts(['display_name']) + raw_output = self.openstack( + 'volume create --size 1 ' + volume_name + opts) + self.assertEqual(volume_name + '\n', raw_output) + + # create volume transfer request for the volume + # and get the auth_key of the new transfer request + opts = self.get_opts(['auth_key']) + auth_key = self.openstack( + 'volume transfer request create ' + + volume_name + + ' --name ' + name + opts) + self.assertNotEqual('', auth_key) + + # accept the volume transfer request + opts = self.get_opts(self.FIELDS) + raw_output = self.openstack( + 'volume transfer request accept ' + name + + ' ' + auth_key + opts) + self.assertEqual(name + '\n', raw_output) + + # the volume transfer will be removed by default after accepted + # so just need to delete the volume here + raw_output = self.openstack( + 'volume delete ' + volume_name) + self.assertEqual('', raw_output) + def test_volume_transfer_request_list(self): opts = self.get_opts(self.HEADERS) raw_output = self.openstack('volume transfer request list' + opts) self.assertIn(self.NAME, raw_output) + + def test_volume_transfer_request_show(self): + opts = self.get_opts(self.FIELDS) + raw_output = self.openstack( + 'volume transfer request show ' + self.NAME + opts) + self.assertEqual(self.NAME + '\n', raw_output) diff --git a/openstackclient/tests/functional/volume/v2/test_transfer_request.py b/openstackclient/tests/functional/volume/v2/test_transfer_request.py index 4f02238b..1791f8ac 100644 --- a/openstackclient/tests/functional/volume/v2/test_transfer_request.py +++ b/openstackclient/tests/functional/volume/v2/test_transfer_request.py @@ -47,7 +47,45 @@ class TransferRequestTests(common.BaseVolumeTests): cls.assertOutput('', raw_output_transfer) cls.assertOutput('', raw_output_volume) + def test_volume_transfer_request_accept(self): + volume_name = uuid.uuid4().hex + name = uuid.uuid4().hex + + # create a volume + opts = self.get_opts(self.FIELDS) + raw_output = self.openstack( + 'volume create --size 1 ' + volume_name + opts) + self.assertEqual(volume_name + '\n', raw_output) + + # create volume transfer request for the volume + # and get the auth_key of the new transfer request + opts = self.get_opts(['auth_key']) + auth_key = self.openstack( + 'volume transfer request create ' + + volume_name + + ' --name ' + name + opts) + self.assertNotEqual('', auth_key) + + # accept the volume transfer request + opts = self.get_opts(self.FIELDS) + raw_output = self.openstack( + 'volume transfer request accept ' + name + + ' ' + auth_key + opts) + self.assertEqual(name + '\n', raw_output) + + # the volume transfer will be removed by default after accepted + # so just need to delete the volume here + raw_output = self.openstack( + 'volume delete ' + volume_name) + self.assertEqual('', raw_output) + def test_volume_transfer_request_list(self): opts = self.get_opts(self.HEADERS) raw_output = self.openstack('volume transfer request list' + opts) self.assertIn(self.NAME, raw_output) + + def test_volume_transfer_request_show(self): + opts = self.get_opts(self.FIELDS) + raw_output = self.openstack( + 'volume transfer request show ' + self.NAME + opts) + self.assertEqual(self.NAME + '\n', raw_output) diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py index 294d772d..7dd23373 100644 --- a/openstackclient/tests/unit/common/test_quota.py +++ b/openstackclient/tests/unit/common/test_quota.py @@ -82,6 +82,18 @@ class TestQuotaSet(TestQuota): loaded=True, ) + self.quotas_class_mock.update.return_value = FakeQuotaResource( + None, + copy.deepcopy(compute_fakes.QUOTA), + loaded=True, + ) + + self.volume_quotas_class_mock.update.return_value = FakeQuotaResource( + None, + copy.deepcopy(compute_fakes.QUOTA), + loaded=True, + ) + self.network_mock = self.app.client_manager.network self.network_mock.update_quota = mock.Mock() @@ -294,27 +306,72 @@ class TestQuotaSet(TestQuota): def test_quota_set_with_class(self): arglist = [ + '--injected-files', str(compute_fakes.injected_file_num), + '--injected-file-size', str(compute_fakes.injected_file_size_num), + '--injected-path-size', str(compute_fakes.injected_path_size_num), + '--key-pairs', str(compute_fakes.key_pair_num), + '--cores', str(compute_fakes.core_num), + '--ram', str(compute_fakes.ram_num), '--instances', str(compute_fakes.instance_num), + '--properties', str(compute_fakes.property_num), + '--server-groups', str(compute_fakes.servgroup_num), + '--server-group-members', str(compute_fakes.servgroup_members_num), + '--gigabytes', str(compute_fakes.floating_ip_num), + '--snapshots', str(compute_fakes.fix_ip_num), '--volumes', str(volume_fakes.QUOTA['volumes']), '--network', str(network_fakes.QUOTA['network']), - '--class', - identity_fakes.project_name, + '--class', identity_fakes.project_name, ] verifylist = [ + ('injected_files', compute_fakes.injected_file_num), + ('injected_file_content_bytes', + compute_fakes.injected_file_size_num), + ('injected_file_path_bytes', compute_fakes.injected_path_size_num), + ('key_pairs', compute_fakes.key_pair_num), + ('cores', compute_fakes.core_num), + ('ram', compute_fakes.ram_num), ('instances', compute_fakes.instance_num), + ('metadata_items', compute_fakes.property_num), + ('server_groups', compute_fakes.servgroup_num), + ('server_group_members', compute_fakes.servgroup_members_num), + ('gigabytes', compute_fakes.floating_ip_num), + ('snapshots', compute_fakes.fix_ip_num), ('volumes', volume_fakes.QUOTA['volumes']), ('network', network_fakes.QUOTA['network']), + ('project', identity_fakes.project_name), ('quota_class', True), ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) - self.quotas_class_mock.update.assert_called_once_with( - identity_fakes.project_id, - **{'instances': compute_fakes.instance_num} + + kwargs_compute = { + 'injected_files': compute_fakes.injected_file_num, + 'injected_file_content_bytes': + compute_fakes.injected_file_size_num, + 'injected_file_path_bytes': compute_fakes.injected_path_size_num, + 'key_pairs': compute_fakes.key_pair_num, + 'cores': compute_fakes.core_num, + 'ram': compute_fakes.ram_num, + 'instances': compute_fakes.instance_num, + 'metadata_items': compute_fakes.property_num, + 'server_groups': compute_fakes.servgroup_num, + 'server_group_members': compute_fakes.servgroup_members_num, + } + kwargs_volume = { + 'gigabytes': compute_fakes.floating_ip_num, + 'snapshots': compute_fakes.fix_ip_num, + 'volumes': volume_fakes.QUOTA['volumes'], + } + + self.quotas_class_mock.update.assert_called_with( + identity_fakes.project_name, + **kwargs_compute ) - self.volume_quotas_class_mock.update.assert_called_once_with( - identity_fakes.project_id, - **{'volumes': volume_fakes.QUOTA['volumes']} + self.volume_quotas_class_mock.update.assert_called_with( + identity_fakes.project_name, + **kwargs_volume ) self.assertNotCalled(self.network_mock.update_quota) self.assertIsNone(result) @@ -444,9 +501,9 @@ class TestQuotaShow(TestQuota): self.cmd.take_action(parsed_args) self.quotas_class_mock.get.assert_called_once_with( - identity_fakes.project_id) + identity_fakes.project_name) self.volume_quotas_class_mock.get.assert_called_once_with( - identity_fakes.project_id) + identity_fakes.project_name) self.assertNotCalled(self.network.get_quota) self.assertNotCalled(self.network.get_quota_default) diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index 89b128ee..91aebf9f 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -364,11 +364,14 @@ class FakeNetworkSegment(object): attrs = attrs or {} # Set default attributes. + fake_uuid = uuid.uuid4().hex network_segment_attrs = { - 'id': 'network-segment-id-' + uuid.uuid4().hex, - 'network_id': 'network-id-' + uuid.uuid4().hex, + 'description': 'network-segment-description-' + fake_uuid, + 'id': 'network-segment-id-' + fake_uuid, + 'name': 'network-segment-name-' + fake_uuid, + 'network_id': 'network-id-' + fake_uuid, 'network_type': 'vlan', - 'physical_network': 'physical-network-name-' + uuid.uuid4().hex, + 'physical_network': 'physical-network-name-' + fake_uuid, 'segmentation_id': 1024, } diff --git a/openstackclient/tests/unit/network/v2/test_network.py b/openstackclient/tests/unit/network/v2/test_network.py index 1094131e..50a60c2d 100644 --- a/openstackclient/tests/unit/network/v2/test_network.py +++ b/openstackclient/tests/unit/network/v2/test_network.py @@ -13,6 +13,7 @@ import mock from mock import call +import random from osc_lib import exceptions from osc_lib import utils @@ -498,6 +499,23 @@ class TestListNetwork(TestNetwork): self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) + def test_list_internal(self): + arglist = [ + '--internal', + ] + verifylist = [ + ('internal', True), + ('long', False), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'router:external': False} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + def test_network_list_long(self): arglist = [ '--long', @@ -517,6 +535,150 @@ class TestListNetwork(TestNetwork): self.assertEqual(self.columns_long, columns) self.assertEqual(self.data_long, list(data)) + def test_list_name(self): + test_name = "fakename" + arglist = [ + '--name', test_name, + ] + verifylist = [ + ('external', False), + ('long', False), + ('name', test_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'name': test_name} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_network_list_enable(self): + arglist = [ + '--enable', + ] + verifylist = [ + ('long', False), + ('external', False), + ('enable', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'admin_state_up': True} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_network_list_disable(self): + arglist = [ + '--disable', + ] + verifylist = [ + ('long', False), + ('external', False), + ('disable', True) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'admin_state_up': False} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_network_list_project(self): + project = identity_fakes_v3.FakeProject.create_one_project() + self.projects_mock.get.return_value = project + arglist = [ + '--project', project.id, + ] + verifylist = [ + ('project', project.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.network.networks.assert_called_once_with( + **{'tenant_id': project.id} + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_networ_list_project_domain(self): + project = identity_fakes_v3.FakeProject.create_one_project() + self.projects_mock.get.return_value = project + arglist = [ + '--project', project.id, + '--project-domain', project.domain_id, + ] + verifylist = [ + ('project', project.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + filters = {'tenant_id': project.id} + + self.network.networks.assert_called_once_with(**filters) + + def test_network_list_share(self): + arglist = [ + '--share', + ] + verifylist = [ + ('long', False), + ('share', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'shared': True} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_network_list_no_share(self): + arglist = [ + '--no-share', + ] + verifylist = [ + ('long', False), + ('no_share', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'shared': False} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_network_list_status(self): + choices = ['ACTIVE', 'BUILD', 'DOWN', 'ERROR'] + test_status = random.choice(choices) + arglist = [ + '--status', test_status, + ] + verifylist = [ + ('long', False), + ('status', test_status), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.networks.assert_called_once_with( + **{'status': test_status} + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + class TestSetNetwork(TestNetwork): diff --git a/openstackclient/tests/unit/network/v2/test_network_segment.py b/openstackclient/tests/unit/network/v2/test_network_segment.py index b9fce078..3e755e07 100644 --- a/openstackclient/tests/unit/network/v2/test_network_segment.py +++ b/openstackclient/tests/unit/network/v2/test_network_segment.py @@ -12,6 +12,7 @@ # import mock +from mock import call from osc_lib import exceptions @@ -32,6 +33,243 @@ class TestNetworkSegment(network_fakes.TestNetworkV2): self.network = self.app.client_manager.network +class TestCreateNetworkSegment(TestNetworkSegment): + + # The network segment to create along with associated network. + _network_segment = \ + network_fakes.FakeNetworkSegment.create_one_network_segment() + _network = network_fakes.FakeNetwork.create_one_network({ + 'id': _network_segment.network_id, + }) + + columns = ( + 'description', + 'id', + 'name', + 'network_id', + 'network_type', + 'physical_network', + 'segmentation_id', + ) + + data = ( + _network_segment.description, + _network_segment.id, + _network_segment.name, + _network_segment.network_id, + _network_segment.network_type, + _network_segment.physical_network, + _network_segment.segmentation_id, + ) + + def setUp(self): + super(TestCreateNetworkSegment, self).setUp() + + self.network.create_segment = mock.Mock( + return_value=self._network_segment + ) + self.network.find_network = mock.Mock(return_value=self._network) + + # Get the command object to test + self.cmd = network_segment.CreateNetworkSegment( + self.app, + self.namespace + ) + + def test_create_no_options(self): + # Missing required args should bail here + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, [], []) + + def test_create_no_beta_commands(self): + arglist = [ + '--network', self._network_segment.network_id, + '--network-type', self._network_segment.network_type, + self._network_segment.name, + ] + verifylist = [ + ('network', self._network_segment.network_id), + ('network_type', self._network_segment.network_type), + ('name', self._network_segment.name), + ] + self.app.options.os_beta_command = False + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + + def test_create_invalid_network_type(self): + arglist = [ + '--network', self._network_segment.network_id, + '--network-type', 'foo', + self._network_segment.name, + ] + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, []) + + def test_create_minimum_options(self): + arglist = [ + '--network', self._network_segment.network_id, + '--network-type', self._network_segment.network_type, + self._network_segment.name, + ] + verifylist = [ + ('network', self._network_segment.network_id), + ('network_type', self._network_segment.network_type), + ('name', self._network_segment.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.find_network.assert_called_once_with( + self._network_segment.network_id, + ignore_missing=False + ) + self.network.create_segment.assert_called_once_with(**{ + 'network_id': self._network_segment.network_id, + 'network_type': self._network_segment.network_type, + 'name': self._network_segment.name, + }) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_create_all_options(self): + arglist = [ + '--description', self._network_segment.description, + '--network', self._network_segment.network_id, + '--network-type', self._network_segment.network_type, + '--physical-network', self._network_segment.physical_network, + '--segment', str(self._network_segment.segmentation_id), + self._network_segment.name, + ] + verifylist = [ + ('description', self._network_segment.description), + ('network', self._network_segment.network_id), + ('network_type', self._network_segment.network_type), + ('physical_network', self._network_segment.physical_network), + ('segment', self._network_segment.segmentation_id), + ('name', self._network_segment.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.find_network.assert_called_once_with( + self._network_segment.network_id, + ignore_missing=False + ) + self.network.create_segment.assert_called_once_with(**{ + 'description': self._network_segment.description, + 'network_id': self._network_segment.network_id, + 'network_type': self._network_segment.network_type, + 'physical_network': self._network_segment.physical_network, + 'segmentation_id': self._network_segment.segmentation_id, + 'name': self._network_segment.name, + }) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + +class TestDeleteNetworkSegment(TestNetworkSegment): + + # The network segments to delete. + _network_segments = \ + network_fakes.FakeNetworkSegment.create_network_segments() + + def setUp(self): + super(TestDeleteNetworkSegment, self).setUp() + + self.network.delete_segment = mock.Mock(return_value=None) + self.network.find_segment = mock.MagicMock( + side_effect=self._network_segments + ) + + # Get the command object to test + self.cmd = network_segment.DeleteNetworkSegment( + self.app, + self.namespace + ) + + def test_delete_no_beta_commands(self): + arglist = [ + self._network_segments[0].id, + ] + verifylist = [ + ('network_segment', [self._network_segments[0].id]), + ] + self.app.options.os_beta_command = False + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + + def test_delete(self): + arglist = [ + self._network_segments[0].id, + ] + verifylist = [ + ('network_segment', [self._network_segments[0].id]), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.network.delete_segment.assert_called_once_with( + self._network_segments[0] + ) + self.assertIsNone(result) + + def test_delete_multiple(self): + arglist = [] + for _network_segment in self._network_segments: + arglist.append(_network_segment.id) + verifylist = [ + ('network_segment', arglist), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + calls = [] + for _network_segment in self._network_segments: + calls.append(call(_network_segment)) + self.network.delete_segment.assert_has_calls(calls) + self.assertIsNone(result) + + def test_delete_multiple_with_exception(self): + arglist = [ + self._network_segments[0].id, + 'doesnotexist' + ] + verifylist = [ + ('network_segment', [self._network_segments[0].id, + 'doesnotexist']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + find_mock_result = [self._network_segments[0], + exceptions.CommandError] + self.network.find_segment = ( + mock.MagicMock(side_effect=find_mock_result) + ) + + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except exceptions.CommandError as e: + self.assertEqual('1 of 2 network segments failed to delete.', + str(e)) + + self.network.find_segment.assert_any_call( + self._network_segments[0].id, ignore_missing=False) + self.network.find_segment.assert_any_call( + 'doesnotexist', ignore_missing=False) + self.network.delete_segment.assert_called_once_with( + self._network_segments[0] + ) + + class TestListNetworkSegment(TestNetworkSegment): _network = network_fakes.FakeNetwork.create_one_network() _network_segments = \ @@ -39,6 +277,7 @@ class TestListNetworkSegment(TestNetworkSegment): columns = ( 'ID', + 'Name', 'Network', 'Network Type', 'Segment', @@ -51,6 +290,7 @@ class TestListNetworkSegment(TestNetworkSegment): for _network_segment in _network_segments: data.append(( _network_segment.id, + _network_segment.name, _network_segment.network_id, _network_segment.network_type, _network_segment.segmentation_id, @@ -60,6 +300,7 @@ class TestListNetworkSegment(TestNetworkSegment): for _network_segment in _network_segments: data_long.append(( _network_segment.id, + _network_segment.name, _network_segment.network_id, _network_segment.network_type, _network_segment.segmentation_id, @@ -131,6 +372,78 @@ class TestListNetworkSegment(TestNetworkSegment): self.assertEqual(self.data, list(data)) +class TestSetNetworkSegment(TestNetworkSegment): + + # The network segment to show. + _network_segment = \ + network_fakes.FakeNetworkSegment.create_one_network_segment() + + def setUp(self): + super(TestSetNetworkSegment, self).setUp() + + self.network.find_segment = mock.Mock( + return_value=self._network_segment + ) + self.network.update_segment = mock.Mock( + return_value=self._network_segment + ) + + # Get the command object to test + self.cmd = network_segment.SetNetworkSegment(self.app, self.namespace) + + def test_set_no_beta_commands(self): + arglist = [ + self._network_segment.id, + ] + verifylist = [ + ('network_segment', self._network_segment.id), + ] + self.app.options.os_beta_command = False + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + + def test_set_no_options(self): + arglist = [ + self._network_segment.id, + ] + verifylist = [ + ('network_segment', self._network_segment.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + self.network.update_segment.assert_called_once_with( + self._network_segment, **{} + ) + self.assertIsNone(result) + + def test_set_all_options(self): + arglist = [ + '--description', 'new description', + '--name', 'new name', + self._network_segment.id, + ] + verifylist = [ + ('description', 'new description'), + ('name', 'new name'), + ('network_segment', self._network_segment.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + attrs = { + 'description': 'new description', + 'name': 'new name', + } + self.network.update_segment.assert_called_once_with( + self._network_segment, **attrs + ) + self.assertIsNone(result) + + class TestShowNetworkSegment(TestNetworkSegment): # The network segment to show. @@ -138,7 +451,9 @@ class TestShowNetworkSegment(TestNetworkSegment): network_fakes.FakeNetworkSegment.create_one_network_segment() columns = ( + 'description', 'id', + 'name', 'network_id', 'network_type', 'physical_network', @@ -146,7 +461,9 @@ class TestShowNetworkSegment(TestNetworkSegment): ) data = ( + _network_segment.description, _network_segment.id, + _network_segment.name, _network_segment.network_id, _network_segment.network_type, _network_segment.physical_network, diff --git a/openstackclient/tests/unit/network/v2/test_router.py b/openstackclient/tests/unit/network/v2/test_router.py index 6898a046..5ed969b4 100644 --- a/openstackclient/tests/unit/network/v2/test_router.py +++ b/openstackclient/tests/unit/network/v2/test_router.py @@ -40,7 +40,7 @@ class TestAddPortToRouter(TestRouter): def setUp(self): super(TestAddPortToRouter, self).setUp() - self.network.router_add_interface = mock.Mock() + self.network.add_interface_to_router = mock.Mock() self.cmd = router.AddPortToRouter(self.app, self.namespace) self.network.find_router = mock.Mock(return_value=self._router) self.network.find_port = mock.Mock(return_value=self._port) @@ -65,9 +65,8 @@ class TestAddPortToRouter(TestRouter): result = self.cmd.take_action(parsed_args) - self.network.router_add_interface.assert_called_with(self._router, **{ - 'port_id': self._router.port, - }) + self.network.add_interface_to_router.assert_called_with( + self._router, **{'port_id': self._router.port, }) self.assertIsNone(result) @@ -80,7 +79,7 @@ class TestAddSubnetToRouter(TestRouter): def setUp(self): super(TestAddSubnetToRouter, self).setUp() - self.network.router_add_interface = mock.Mock() + self.network.add_interface_to_router = mock.Mock() self.cmd = router.AddSubnetToRouter(self.app, self.namespace) self.network.find_router = mock.Mock(return_value=self._router) self.network.find_subnet = mock.Mock(return_value=self._subnet) @@ -104,7 +103,7 @@ class TestAddSubnetToRouter(TestRouter): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.network.router_add_interface.assert_called_with( + self.network.add_interface_to_router.assert_called_with( self._router, **{'subnet_id': self._router.subnet}) self.assertIsNone(result) @@ -411,7 +410,7 @@ class TestRemovePortFromRouter(TestRouter): def setUp(self): super(TestRemovePortFromRouter, self).setUp() - self.network.router_remove_interface = mock.Mock() + self.network.remove_interface_from_router = mock.Mock() self.cmd = router.RemovePortFromRouter(self.app, self.namespace) self.network.find_router = mock.Mock(return_value=self._router) self.network.find_port = mock.Mock(return_value=self._port) @@ -436,7 +435,7 @@ class TestRemovePortFromRouter(TestRouter): result = self.cmd.take_action(parsed_args) - self.network.router_remove_interface.assert_called_with( + self.network.remove_interface_from_router.assert_called_with( self._router, **{'port_id': self._router.port}) self.assertIsNone(result) @@ -450,7 +449,7 @@ class TestRemoveSubnetFromRouter(TestRouter): def setUp(self): super(TestRemoveSubnetFromRouter, self).setUp() - self.network.router_remove_interface = mock.Mock() + self.network.remove_interface_from_router = mock.Mock() self.cmd = router.RemoveSubnetFromRouter(self.app, self.namespace) self.network.find_router = mock.Mock(return_value=self._router) self.network.find_subnet = mock.Mock(return_value=self._subnet) @@ -474,7 +473,7 @@ class TestRemoveSubnetFromRouter(TestRouter): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.network.router_remove_interface.assert_called_with( + self.network.remove_interface_from_router.assert_called_with( self._router, **{'subnet_id': self._router.subnet}) self.assertIsNone(result) diff --git a/openstackclient/tests/unit/test_shell.py b/openstackclient/tests/unit/test_shell.py index 87cd7f51..3d91da9b 100644 --- a/openstackclient/tests/unit/test_shell.py +++ b/openstackclient/tests/unit/test_shell.py @@ -413,9 +413,6 @@ class TestShellCli(TestShell): class TestShellArgV(TestShell): """Test the deferred help flag""" - def setUp(self): - super(TestShellArgV, self).setUp() - def test_shell_argv(self): """Test argv decoding diff --git a/openstackclient/tests/unit/volume/v1/fakes.py b/openstackclient/tests/unit/volume/v1/fakes.py index 2a4f62c5..ef52e4b0 100644 --- a/openstackclient/tests/unit/volume/v1/fakes.py +++ b/openstackclient/tests/unit/volume/v1/fakes.py @@ -146,8 +146,6 @@ class FakeTransfer(object): """ # Set default attribute transfer_info = { - 'auth_key': 'key-' + uuid.uuid4().hex, - 'created_at': 'time-' + uuid.uuid4().hex, 'volume_id': 'volume-id-' + uuid.uuid4().hex, 'name': 'fake_transfer_name', 'id': 'id-' + uuid.uuid4().hex, @@ -363,24 +361,24 @@ class FakeVolume(object): # Set default attribute volume_info = { 'id': 'volume-id' + uuid.uuid4().hex, - 'name': 'volume-name' + uuid.uuid4().hex, - 'description': 'description' + uuid.uuid4().hex, - 'status': random.choice(['available', 'in_use']), - 'size': random.randint(1, 20), + 'display_name': 'volume-name' + uuid.uuid4().hex, + 'display_description': 'description' + uuid.uuid4().hex, + 'status': 'available', + 'size': 10, 'volume_type': random.choice(['fake_lvmdriver-1', 'fake_lvmdriver-2']), - 'bootable': - random.randint(0, 1), + 'bootable': 'true', 'metadata': { 'key' + uuid.uuid4().hex: 'val' + uuid.uuid4().hex, 'key' + uuid.uuid4().hex: 'val' + uuid.uuid4().hex, 'key' + uuid.uuid4().hex: 'val' + uuid.uuid4().hex}, - 'snapshot_id': random.randint(1, 5), + 'snapshot_id': 'snapshot-id-' + uuid.uuid4().hex, 'availability_zone': 'zone' + uuid.uuid4().hex, 'attachments': [{ 'device': '/dev/' + uuid.uuid4().hex, 'server_id': uuid.uuid4().hex, }, ], + 'created_at': 'time-' + uuid.uuid4().hex, } # Overwrite default attributes if there are some attributes set diff --git a/openstackclient/tests/unit/volume/v1/test_transfer_request.py b/openstackclient/tests/unit/volume/v1/test_transfer_request.py index e89c5056..b3788d6e 100644 --- a/openstackclient/tests/unit/volume/v1/test_transfer_request.py +++ b/openstackclient/tests/unit/volume/v1/test_transfer_request.py @@ -36,6 +36,53 @@ class TestTransfer(transfer_fakes.TestVolumev1): self.volumes_mock.reset_mock() +class TestTransferAccept(TestTransfer): + + columns = ( + 'id', + 'name', + 'volume_id', + ) + + def setUp(self): + super(TestTransferAccept, self).setUp() + + self.volume_transfer = ( + transfer_fakes.FakeTransfer.create_one_transfer()) + self.data = ( + self.volume_transfer.id, + self.volume_transfer.name, + self.volume_transfer.volume_id, + ) + + self.transfer_mock.get.return_value = self.volume_transfer + self.transfer_mock.accept.return_value = self.volume_transfer + + # Get the command object to test + self.cmd = volume_transfer_request.AcceptTransferRequest( + self.app, None) + + def test_transfer_accept(self): + arglist = [ + self.volume_transfer.id, + 'auth_key', + ] + verifylist = [ + ('transfer_request', self.volume_transfer.id), + ('auth_key', 'auth_key'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.transfer_mock.get.assert_called_once_with( + self.volume_transfer.id) + self.transfer_mock.accept.assert_called_once_with( + self.volume_transfer.id, 'auth_key') + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + class TestTransferCreate(TestTransfer): volume = transfer_fakes.FakeVolume.create_one_volume() @@ -52,7 +99,10 @@ class TestTransferCreate(TestTransfer): super(TestTransferCreate, self).setUp() self.volume_transfer = transfer_fakes.FakeTransfer.create_one_transfer( - attrs={'volume_id': self.volume.id}) + attrs={'volume_id': self.volume.id, + 'auth_key': 'key', + 'created_at': 'time'} + ) self.data = ( self.volume_transfer.auth_key, self.volume_transfer.created_at, @@ -266,3 +316,49 @@ class TestTransferList(TestTransfer): detailed=True, search_opts={'all_tenants': 1} ) + + +class TestTransferShow(TestTransfer): + + columns = ( + 'created_at', + 'id', + 'name', + 'volume_id', + ) + + def setUp(self): + super(TestTransferShow, self).setUp() + + self.volume_transfer = ( + transfer_fakes.FakeTransfer.create_one_transfer( + attrs={'created_at': 'time'}) + ) + self.data = ( + self.volume_transfer.created_at, + self.volume_transfer.id, + self.volume_transfer.name, + self.volume_transfer.volume_id, + ) + + self.transfer_mock.get.return_value = self.volume_transfer + + # Get the command object to test + self.cmd = volume_transfer_request.ShowTransferRequest( + self.app, None) + + def test_transfer_show(self): + arglist = [ + self.volume_transfer.id, + ] + verifylist = [ + ('transfer_request', self.volume_transfer.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.transfer_mock.get.assert_called_once_with( + self.volume_transfer.id) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) diff --git a/openstackclient/tests/unit/volume/v1/test_volume.py b/openstackclient/tests/unit/volume/v1/test_volume.py index e95f42d0..895f1f87 100644 --- a/openstackclient/tests/unit/volume/v1/test_volume.py +++ b/openstackclient/tests/unit/volume/v1/test_volume.py @@ -67,48 +67,50 @@ class TestVolumeCreate(TestVolume): user = identity_fakes.FakeUser.create_one_user() columns = ( - 'attach_status', + 'attachments', 'availability_zone', + 'bootable', + 'created_at', 'display_description', 'display_name', 'id', 'properties', 'size', + 'snapshot_id', 'status', 'type', ) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) def setUp(self): super(TestVolumeCreate, self).setUp() - - self.volumes_mock.create.return_value = fakes.FakeResource( - None, - copy.deepcopy(volume_fakes.VOLUME), - loaded=True, + self.new_volume = volume_fakes.FakeVolume.create_one_volume() + self.datalist = ( + self.new_volume.attachments, + self.new_volume.availability_zone, + self.new_volume.bootable, + self.new_volume.created_at, + self.new_volume.display_description, + self.new_volume.display_name, + self.new_volume.id, + utils.format_dict(self.new_volume.metadata), + self.new_volume.size, + self.new_volume.snapshot_id, + self.new_volume.status, + self.new_volume.volume_type, ) + self.volumes_mock.create.return_value = self.new_volume # Get the command object to test self.cmd = volume.CreateVolume(self.app, None) def test_volume_create_min_options(self): arglist = [ - '--size', str(volume_fakes.volume_size), - volume_fakes.volume_name, + '--size', str(self.new_volume.size), + self.new_volume.display_name, ] verifylist = [ - ('size', volume_fakes.volume_size), - ('name', volume_fakes.volume_name), + ('size', self.new_volume.size), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -123,10 +125,10 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, + self.new_volume.display_name, None, None, None, @@ -140,18 +142,18 @@ class TestVolumeCreate(TestVolume): def test_volume_create_options(self): arglist = [ - '--size', str(volume_fakes.volume_size), - '--description', volume_fakes.volume_description, - '--type', volume_fakes.volume_type, - '--availability-zone', volume_fakes.volume_zone, - volume_fakes.volume_name, + '--size', str(self.new_volume.size), + '--description', self.new_volume.display_description, + '--type', self.new_volume.volume_type, + '--availability-zone', self.new_volume.availability_zone, + self.new_volume.display_name, ] verifylist = [ - ('size', volume_fakes.volume_size), - ('description', volume_fakes.volume_description), - ('type', volume_fakes.volume_type), - ('availability_zone', volume_fakes.volume_zone), - ('name', volume_fakes.volume_name), + ('size', self.new_volume.size), + ('description', self.new_volume.display_description), + ('type', self.new_volume.volume_type), + ('availability_zone', self.new_volume.availability_zone), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -166,15 +168,15 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, - volume_fakes.volume_description, - volume_fakes.volume_type, + self.new_volume.display_name, + self.new_volume.display_description, + self.new_volume.volume_type, None, None, - volume_fakes.volume_zone, + self.new_volume.availability_zone, None, None, ) @@ -189,16 +191,16 @@ class TestVolumeCreate(TestVolume): self.users_mock.get.return_value = self.user arglist = [ - '--size', str(volume_fakes.volume_size), + '--size', str(self.new_volume.size), '--project', self.project.id, '--user', self.user.id, - volume_fakes.volume_name, + self.new_volume.display_name, ] verifylist = [ - ('size', volume_fakes.volume_size), + ('size', self.new_volume.size), ('project', self.project.id), ('user', self.user.id), - ('name', volume_fakes.volume_name), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -213,10 +215,10 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, + self.new_volume.display_name, None, None, self.user.id, @@ -236,16 +238,16 @@ class TestVolumeCreate(TestVolume): self.users_mock.get.return_value = self.user arglist = [ - '--size', str(volume_fakes.volume_size), + '--size', str(self.new_volume.size), '--project', self.project.name, '--user', self.user.name, - volume_fakes.volume_name, + self.new_volume.display_name, ] verifylist = [ - ('size', volume_fakes.volume_size), + ('size', self.new_volume.size), ('project', self.project.name), ('user', self.user.name), - ('name', volume_fakes.volume_name), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -260,10 +262,10 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, + self.new_volume.display_name, None, None, self.user.id, @@ -280,13 +282,13 @@ class TestVolumeCreate(TestVolume): arglist = [ '--property', 'Alpha=a', '--property', 'Beta=b', - '--size', str(volume_fakes.volume_size), - volume_fakes.volume_name, + '--size', str(self.new_volume.size), + self.new_volume.display_name, ] verifylist = [ ('property', {'Alpha': 'a', 'Beta': 'b'}), - ('size', volume_fakes.volume_size), - ('name', volume_fakes.volume_name), + ('size', self.new_volume.size), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -301,10 +303,10 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, + self.new_volume.display_name, None, None, None, @@ -326,13 +328,13 @@ class TestVolumeCreate(TestVolume): arglist = [ '--image', volume_fakes.image_id, - '--size', str(volume_fakes.volume_size), - volume_fakes.volume_name, + '--size', str(self.new_volume.size), + self.new_volume.display_name, ] verifylist = [ ('image', volume_fakes.image_id), - ('size', volume_fakes.volume_size), - ('name', volume_fakes.volume_name), + ('size', self.new_volume.size), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -347,10 +349,10 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, + self.new_volume.display_name, None, None, None, @@ -372,13 +374,13 @@ class TestVolumeCreate(TestVolume): arglist = [ '--image', volume_fakes.image_name, - '--size', str(volume_fakes.volume_size), - volume_fakes.volume_name, + '--size', str(self.new_volume.size), + self.new_volume.display_name, ] verifylist = [ ('image', volume_fakes.image_name), - ('size', volume_fakes.volume_size), - ('name', volume_fakes.volume_name), + ('size', self.new_volume.size), + ('name', self.new_volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -393,10 +395,10 @@ class TestVolumeCreate(TestVolume): # project_id=, availability_zone=, # metadata=, imageRef=) self.volumes_mock.create.assert_called_with( - volume_fakes.volume_size, + self.new_volume.size, None, None, - volume_fakes.volume_name, + self.new_volume.display_name, None, None, None, @@ -503,6 +505,7 @@ class TestVolumeDelete(TestVolume): class TestVolumeList(TestVolume): + _volume = volume_fakes.FakeVolume.create_one_volume() columns = ( 'ID', 'Display Name', @@ -510,26 +513,23 @@ class TestVolumeList(TestVolume): 'Size', 'Attached to', ) + server = _volume.attachments[0]['server_id'] + device = _volume.attachments[0]['device'] + msg = 'Attached to %s on %s ' % (server, device) datalist = ( ( - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_status, - volume_fakes.volume_size, - '', + _volume.id, + _volume.display_name, + _volume.status, + _volume.size, + msg, ), ) def setUp(self): super(TestVolumeList, self).setUp() - self.volumes_mock.list.return_value = [ - fakes.FakeResource( - None, - copy.deepcopy(volume_fakes.VOLUME), - loaded=True, - ), - ] + self.volumes_mock.list.return_value = [self._volume] # Get the command object to test self.cmd = volume.ListVolume(self.app, None) @@ -552,12 +552,12 @@ class TestVolumeList(TestVolume): def test_volume_list_name(self): arglist = [ - '--name', volume_fakes.volume_name, + '--name', self._volume.display_name, ] verifylist = [ ('long', False), ('all_projects', False), - ('name', volume_fakes.volume_name), + ('name', self._volume.display_name), ('status', None), ('limit', None), ] @@ -569,13 +569,13 @@ class TestVolumeList(TestVolume): def test_volume_list_status(self): arglist = [ - '--status', volume_fakes.volume_status, + '--status', self._volume.status, ] verifylist = [ ('long', False), ('all_projects', False), ('name', None), - ('status', volume_fakes.volume_status), + ('status', self._volume.status), ('limit', None), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -630,14 +630,14 @@ class TestVolumeList(TestVolume): self.assertEqual(collist, columns) datalist = (( - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_status, - volume_fakes.volume_size, - volume_fakes.volume_type, - '', - '', - "Alpha='a', Beta='b', Gamma='g'", + self._volume.id, + self._volume.display_name, + self._volume.status, + self._volume.size, + self._volume.volume_type, + self._volume.bootable, + self.msg, + utils.format_dict(self._volume.metadata), ), ) self.assertEqual(datalist, tuple(data)) @@ -679,33 +679,27 @@ class TestVolumeList(TestVolume): class TestVolumeSet(TestVolume): + _volume = volume_fakes.FakeVolume.create_one_volume() + def setUp(self): super(TestVolumeSet, self).setUp() - self.volumes_mock.get.return_value = fakes.FakeResource( - None, - copy.deepcopy(volume_fakes.VOLUME), - loaded=True, - ) + self.volumes_mock.get.return_value = self._volume - self.volumes_mock.update.return_value = fakes.FakeResource( - None, - copy.deepcopy(volume_fakes.VOLUME), - loaded=True, - ) + self.volumes_mock.update.return_value = self._volume # Get the command object to test self.cmd = volume.SetVolume(self.app, None) def test_volume_set_no_options(self): arglist = [ - volume_fakes.volume_name, + self._volume.display_name, ] verifylist = [ ('name', None), ('description', None), ('size', None), ('property', None), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -715,14 +709,14 @@ class TestVolumeSet(TestVolume): def test_volume_set_name(self): arglist = [ '--name', 'qwerty', - volume_fakes.volume_name, + self._volume.display_name, ] verifylist = [ ('name', 'qwerty'), ('description', None), ('size', None), ('property', None), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -733,7 +727,7 @@ class TestVolumeSet(TestVolume): 'display_name': 'qwerty', } self.volumes_mock.update.assert_called_with( - volume_fakes.volume_id, + self._volume.id, **kwargs ) self.assertIsNone(result) @@ -741,14 +735,14 @@ class TestVolumeSet(TestVolume): def test_volume_set_description(self): arglist = [ '--description', 'new desc', - volume_fakes.volume_name, + self._volume.display_name, ] verifylist = [ ('name', None), ('description', 'new desc'), ('size', None), ('property', None), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -759,7 +753,7 @@ class TestVolumeSet(TestVolume): 'display_description': 'new desc', } self.volumes_mock.update.assert_called_with( - volume_fakes.volume_id, + self._volume.id, **kwargs ) self.assertIsNone(result) @@ -767,14 +761,14 @@ class TestVolumeSet(TestVolume): def test_volume_set_size(self): arglist = [ '--size', '130', - volume_fakes.volume_name, + self._volume.display_name, ] verifylist = [ ('name', None), ('description', None), ('size', 130), ('property', None), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -783,23 +777,24 @@ class TestVolumeSet(TestVolume): # Set expected values size = 130 self.volumes_mock.extend.assert_called_with( - volume_fakes.volume_id, + self._volume.id, size ) self.assertIsNone(result) @mock.patch.object(volume.LOG, 'error') def test_volume_set_size_smaller(self, mock_log_error): + self._volume.status = 'available' arglist = [ - '--size', '100', - volume_fakes.volume_name, + '--size', '1', + self._volume.display_name, ] verifylist = [ ('name', None), ('description', None), - ('size', 100), + ('size', 1), ('property', None), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -807,22 +802,22 @@ class TestVolumeSet(TestVolume): mock_log_error.assert_called_with("New size must be greater " "than %s GB", - volume_fakes.volume_size) + self._volume.size) self.assertIsNone(result) @mock.patch.object(volume.LOG, 'error') def test_volume_set_size_not_available(self, mock_log_error): - self.volumes_mock.get.return_value.status = 'error' + self._volume.status = 'error' arglist = [ '--size', '130', - volume_fakes.volume_name, + self._volume.display_name, ] verifylist = [ ('name', None), ('description', None), ('size', 130), ('property', None), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -836,14 +831,14 @@ class TestVolumeSet(TestVolume): def test_volume_set_property(self): arglist = [ '--property', 'myprop=myvalue', - volume_fakes.volume_name, + self._volume.display_name, ] verifylist = [ ('name', None), ('description', None), ('size', None), ('property', {'myprop': 'myvalue'}), - ('volume', volume_fakes.volume_name), + ('volume', self._volume.display_name), ('bootable', False), ('non_bootable', False) ] @@ -856,26 +851,26 @@ class TestVolumeSet(TestVolume): 'myprop': 'myvalue' } self.volumes_mock.set_metadata.assert_called_with( - volume_fakes.volume_id, + self._volume.id, metadata ) self.assertIsNone(result) def test_volume_set_bootable(self): arglist = [ - ['--bootable', volume_fakes.volume_id], - ['--non-bootable', volume_fakes.volume_id] + ['--bootable', self._volume.id], + ['--non-bootable', self._volume.id] ] verifylist = [ [ ('bootable', True), ('non_bootable', False), - ('volume', volume_fakes.volume_id) + ('volume', self._volume.id) ], [ ('bootable', False), ('non_bootable', True), - ('volume', volume_fakes.volume_id) + ('volume', self._volume.id) ] ] for index in range(len(arglist)): @@ -884,4 +879,103 @@ class TestVolumeSet(TestVolume): self.cmd.take_action(parsed_args) self.volumes_mock.set_bootable.assert_called_with( - volume_fakes.volume_id, verifylist[index][0][1]) + self._volume.id, verifylist[index][0][1]) + + +class TestVolumeShow(TestVolume): + + columns = ( + 'attachments', + 'availability_zone', + 'bootable', + 'created_at', + 'display_description', + 'display_name', + 'id', + 'properties', + 'size', + 'snapshot_id', + 'status', + 'type', + ) + + def setUp(self): + super(TestVolumeShow, self).setUp() + self._volume = volume_fakes.FakeVolume.create_one_volume() + self.datalist = ( + self._volume.attachments, + self._volume.availability_zone, + self._volume.bootable, + self._volume.created_at, + self._volume.display_description, + self._volume.display_name, + self._volume.id, + utils.format_dict(self._volume.metadata), + self._volume.size, + self._volume.snapshot_id, + self._volume.status, + self._volume.volume_type, + ) + self.volumes_mock.get.return_value = self._volume + # Get the command object to test + self.cmd = volume.ShowVolume(self.app, None) + + def test_volume_show(self): + arglist = [ + self._volume.id + ] + verifylist = [ + ("volume", self._volume.id) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.volumes_mock.get.assert_called_with(self._volume.id) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) + + +class TestVolumeUnset(TestVolume): + + _volume = volume_fakes.FakeVolume.create_one_volume() + + def setUp(self): + super(TestVolumeUnset, self).setUp() + + self.volumes_mock.get.return_value = self._volume + + self.volumes_mock.delete_metadata.return_value = None + # Get the command object to test + self.cmd = volume.UnsetVolume(self.app, None) + + def test_volume_unset_no_options(self): + arglist = [ + self._volume.display_name, + ] + verifylist = [ + ('property', None), + ('volume', self._volume.display_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.assertIsNone(result) + + def test_volume_unset_property(self): + arglist = [ + '--property', 'myprop', + self._volume.display_name, + ] + verifylist = [ + ('property', ['myprop']), + ('volume', self._volume.display_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.volumes_mock.delete_metadata.assert_called_with( + self._volume.id, ['myprop'] + ) + self.assertIsNone(result) diff --git a/openstackclient/tests/unit/volume/v2/fakes.py b/openstackclient/tests/unit/volume/v2/fakes.py index 8d7ac831..2aeea60a 100644 --- a/openstackclient/tests/unit/volume/v2/fakes.py +++ b/openstackclient/tests/unit/volume/v2/fakes.py @@ -52,8 +52,6 @@ class FakeTransfer(object): """ # Set default attribute transfer_info = { - 'auth_key': 'key-' + uuid.uuid4().hex, - 'created_at': 'time-' + uuid.uuid4().hex, 'volume_id': 'volume-id-' + uuid.uuid4().hex, 'name': 'fake_transfer_name', 'id': 'id-' + uuid.uuid4().hex, diff --git a/openstackclient/tests/unit/volume/v2/test_backup.py b/openstackclient/tests/unit/volume/v2/test_backup.py index 45633870..306c9eb3 100644 --- a/openstackclient/tests/unit/volume/v2/test_backup.py +++ b/openstackclient/tests/unit/volume/v2/test_backup.py @@ -336,6 +336,75 @@ class TestBackupRestore(TestBackup): self.assertIsNone(result) +class TestBackupSet(TestBackup): + + backup = volume_fakes.FakeBackup.create_one_backup() + + def setUp(self): + super(TestBackupSet, self).setUp() + + self.backups_mock.get.return_value = self.backup + + # Get the command object to test + self.cmd = backup.SetVolumeBackup(self.app, None) + + def test_backup_set_name(self): + arglist = [ + '--name', 'new_name', + self.backup.id, + ] + verifylist = [ + ('name', 'new_name'), + ('backup', self.backup.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns nothing + result = self.cmd.take_action(parsed_args) + self.backups_mock.update.assert_called_once_with( + self.backup.id, **{'name': 'new_name'}) + self.assertIsNone(result) + + def test_backup_set_state(self): + arglist = [ + '--state', 'error', + self.backup.id + ] + verifylist = [ + ('state', 'error'), + ('backup', self.backup.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.backups_mock.reset_state.assert_called_once_with( + self.backup.id, 'error') + self.assertIsNone(result) + + def test_backup_set_state_failed(self): + self.backups_mock.reset_state.side_effect = exceptions.CommandError() + arglist = [ + '--state', 'error', + self.backup.id + ] + verifylist = [ + ('state', 'error'), + ('backup', self.backup.id) + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except exceptions.CommandError as e: + self.assertEqual('One or more of the set operations failed', + str(e)) + self.backups_mock.reset_state.assert_called_with( + self.backup.id, 'error') + + class TestBackupShow(TestBackup): backup = volume_fakes.FakeBackup.create_one_backup() diff --git a/openstackclient/tests/unit/volume/v2/test_transfer_request.py b/openstackclient/tests/unit/volume/v2/test_transfer_request.py index b4f89089..8cd6534b 100644 --- a/openstackclient/tests/unit/volume/v2/test_transfer_request.py +++ b/openstackclient/tests/unit/volume/v2/test_transfer_request.py @@ -36,6 +36,53 @@ class TestTransfer(transfer_fakes.TestVolume): self.volumes_mock.reset_mock() +class TestTransferAccept(TestTransfer): + + columns = ( + 'id', + 'name', + 'volume_id', + ) + + def setUp(self): + super(TestTransferAccept, self).setUp() + + self.volume_transfer = ( + transfer_fakes.FakeTransfer.create_one_transfer()) + self.data = ( + self.volume_transfer.id, + self.volume_transfer.name, + self.volume_transfer.volume_id, + ) + + self.transfer_mock.get.return_value = self.volume_transfer + self.transfer_mock.accept.return_value = self.volume_transfer + + # Get the command object to test + self.cmd = volume_transfer_request.AcceptTransferRequest( + self.app, None) + + def test_transfer_accept(self): + arglist = [ + self.volume_transfer.id, + 'auth_key', + ] + verifylist = [ + ('transfer_request', self.volume_transfer.id), + ('auth_key', 'auth_key'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.transfer_mock.get.assert_called_once_with( + self.volume_transfer.id) + self.transfer_mock.accept.assert_called_once_with( + self.volume_transfer.id, 'auth_key') + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + class TestTransferCreate(TestTransfer): volume = transfer_fakes.FakeVolume.create_one_volume() @@ -52,7 +99,10 @@ class TestTransferCreate(TestTransfer): super(TestTransferCreate, self).setUp() self.volume_transfer = transfer_fakes.FakeTransfer.create_one_transfer( - attrs={'volume_id': self.volume.id}) + attrs={'volume_id': self.volume.id, + 'auth_key': 'key', + 'created_at': 'time'} + ) self.data = ( self.volume_transfer.auth_key, self.volume_transfer.created_at, @@ -266,3 +316,49 @@ class TestTransferList(TestTransfer): detailed=True, search_opts={'all_tenants': 1} ) + + +class TestTransferShow(TestTransfer): + + columns = ( + 'created_at', + 'id', + 'name', + 'volume_id', + ) + + def setUp(self): + super(TestTransferShow, self).setUp() + + self.volume_transfer = ( + transfer_fakes.FakeTransfer.create_one_transfer( + attrs={'created_at': 'time'}) + ) + self.data = ( + self.volume_transfer.created_at, + self.volume_transfer.id, + self.volume_transfer.name, + self.volume_transfer.volume_id, + ) + + self.transfer_mock.get.return_value = self.volume_transfer + + # Get the command object to test + self.cmd = volume_transfer_request.ShowTransferRequest( + self.app, None) + + def test_transfer_show(self): + arglist = [ + self.volume_transfer.id, + ] + verifylist = [ + ('transfer_request', self.volume_transfer.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.transfer_mock.get.assert_called_once_with( + self.volume_transfer.id) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py index 69bf3803..89fa2014 100644 --- a/openstackclient/volume/v1/volume.py +++ b/openstackclient/volume/v1/volume.py @@ -452,10 +452,8 @@ class UnsetVolume(command.Command): '--property', metavar='<key>', action='append', - default=[], help=_('Remove a property from volume ' '(repeat option to remove multiple properties)'), - required=True, ) return parser diff --git a/openstackclient/volume/v1/volume_transfer_request.py b/openstackclient/volume/v1/volume_transfer_request.py index a985f8e5..4d6f2161 100644 --- a/openstackclient/volume/v1/volume_transfer_request.py +++ b/openstackclient/volume/v1/volume_transfer_request.py @@ -27,6 +27,34 @@ from openstackclient.i18n import _ LOG = logging.getLogger(__name__) +class AcceptTransferRequest(command.ShowOne): + """Accept volume transfer request.""" + + def get_parser(self, prog_name): + parser = super(AcceptTransferRequest, self).get_parser(prog_name) + parser.add_argument( + 'transfer_request', + metavar="<transfer-request>", + help=_('Volume transfer request to accept (name or ID)'), + ) + parser.add_argument( + 'auth_key', + metavar="<auth-key>", + help=_('Authentication key of transfer request'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + transfer_request_id = utils.find_resource( + volume_client.transfers, parsed_args.transfer_request).id + transfer_accept = volume_client.transfers.accept( + transfer_request_id, parsed_args.auth_key) + transfer_accept._info.pop("links", None) + + return zip(*sorted(six.iteritems(transfer_accept._info))) + + class CreateTransferRequest(command.ShowOne): """Create volume transfer request.""" @@ -120,3 +148,24 @@ class ListTransferRequest(command.Lister): return (column_headers, ( utils.get_item_properties(s, columns) for s in volume_transfer_result)) + + +class ShowTransferRequest(command.ShowOne): + """Show volume transfer request details.""" + + def get_parser(self, prog_name): + parser = super(ShowTransferRequest, self).get_parser(prog_name) + parser.add_argument( + 'transfer_request', + metavar="<transfer-request>", + help=_('Volume transfer request to display (name or ID)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + volume_transfer_request = utils.find_resource( + volume_client.transfers, parsed_args.transfer_request) + volume_transfer_request._info.pop("links", None) + + return zip(*sorted(six.iteritems(volume_transfer_request._info))) diff --git a/openstackclient/volume/v2/backup.py b/openstackclient/volume/v2/backup.py index 07c1c94f..4a133d36 100644 --- a/openstackclient/volume/v2/backup.py +++ b/openstackclient/volume/v2/backup.py @@ -281,6 +281,65 @@ class RestoreBackup(RestoreVolumeBackup): return super(RestoreBackup, self).take_action(parsed_args) +class SetVolumeBackup(command.Command): + """Set volume backup properties""" + + def get_parser(self, prog_name): + parser = super(SetVolumeBackup, self).get_parser(prog_name) + parser.add_argument( + "backup", + metavar="<backup>", + help=_("Backup to modify (name or ID)") + ) + parser.add_argument( + '--name', + metavar='<name>', + help=_('New backup name') + ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('New backup description') + ) + parser.add_argument( + '--state', + metavar='<state>', + choices=['available', 'error'], + help=_('New backup state ("available" or "error") (admin only)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + backup = utils.find_resource(volume_client.backups, + parsed_args.backup) + result = 0 + if parsed_args.state: + try: + volume_client.backups.reset_state( + backup.id, parsed_args.state) + except Exception as e: + LOG.error(_("Failed to set backup state: %s"), e) + result += 1 + + kwargs = {} + if parsed_args.name: + kwargs['name'] = parsed_args.name + if parsed_args.description: + kwargs['description'] = parsed_args.description + if kwargs: + try: + volume_client.backups.update(backup.id, **kwargs) + except Exception as e: + LOG.error(_("Failed to update backup name " + "or description: %s"), e) + result += 1 + + if result > 0: + raise exceptions.CommandError(_("One or more of the " + "set operations failed")) + + class ShowVolumeBackup(command.ShowOne): """Display volume backup details""" diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py index 5089aed1..0805b2be 100644 --- a/openstackclient/volume/v2/volume.py +++ b/openstackclient/volume/v2/volume.py @@ -490,7 +490,7 @@ class ShowVolume(command.ShowOne): parser = super(ShowVolume, self).get_parser(prog_name) parser.add_argument( 'volume', - metavar="<volume-id>", + metavar="<volume>", help=_("Volume to display (name or ID)") ) return parser diff --git a/openstackclient/volume/v2/volume_transfer_request.py b/openstackclient/volume/v2/volume_transfer_request.py index 8e79807c..9008fe3c 100644 --- a/openstackclient/volume/v2/volume_transfer_request.py +++ b/openstackclient/volume/v2/volume_transfer_request.py @@ -27,6 +27,34 @@ from openstackclient.i18n import _ LOG = logging.getLogger(__name__) +class AcceptTransferRequest(command.ShowOne): + """Accept volume transfer request.""" + + def get_parser(self, prog_name): + parser = super(AcceptTransferRequest, self).get_parser(prog_name) + parser.add_argument( + 'transfer_request', + metavar="<transfer-request>", + help=_('Volume transfer request to accept (name or ID)'), + ) + parser.add_argument( + 'auth_key', + metavar="<auth-key>", + help=_('Authentication key of transfer request'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + transfer_request_id = utils.find_resource( + volume_client.transfers, parsed_args.transfer_request).id + transfer_accept = volume_client.transfers.accept( + transfer_request_id, parsed_args.auth_key) + transfer_accept._info.pop("links", None) + + return zip(*sorted(six.iteritems(transfer_accept._info))) + + class CreateTransferRequest(command.ShowOne): """Create volume transfer request.""" @@ -120,3 +148,24 @@ class ListTransferRequest(command.Lister): return (column_headers, ( utils.get_item_properties(s, columns) for s in volume_transfer_result)) + + +class ShowTransferRequest(command.ShowOne): + """Show volume transfer request details.""" + + def get_parser(self, prog_name): + parser = super(ShowTransferRequest, self).get_parser(prog_name) + parser.add_argument( + 'transfer_request', + metavar="<transfer-request>", + help=_('Volume transfer request to display (name or ID)'), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + volume_transfer_request = utils.find_resource( + volume_client.transfers, parsed_args.transfer_request) + volume_transfer_request._info.pop("links", None) + + return zip(*sorted(six.iteritems(volume_transfer_request._info))) |
