diff options
Diffstat (limited to 'openstackclient/tests/unit')
| -rw-r--r-- | openstackclient/tests/unit/common/test_quota.py | 72 | ||||
| -rw-r--r-- | openstackclient/tests/unit/compute/v2/test_console.py | 28 | ||||
| -rw-r--r-- | openstackclient/tests/unit/compute/v2/test_server.py | 146 | ||||
| -rw-r--r-- | openstackclient/tests/unit/fakes.py | 3 | ||||
| -rw-r--r-- | openstackclient/tests/unit/network/v2/fakes.py | 67 | ||||
| -rw-r--r-- | openstackclient/tests/unit/network/v2/test_network_flavor.py | 407 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v1/fakes.py | 31 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v1/test_qos_specs.py | 21 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v1/test_type.py | 237 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v2/fakes.py | 31 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v2/test_type.py | 276 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v2/test_volume_host.py | 31 |
12 files changed, 1274 insertions, 76 deletions
diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py index 244d74d2..7dd23373 100644 --- a/openstackclient/tests/unit/common/test_quota.py +++ b/openstackclient/tests/unit/common/test_quota.py @@ -13,8 +13,6 @@ import copy import mock -from openstack.network.v2 import quota as _quota - from openstackclient.common import quota from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes from openstackclient.tests.unit import fakes @@ -284,32 +282,27 @@ class TestQuotaSet(TestQuota): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - # TODO(huanxuan): Remove this if condition once the fixed - # SDK Quota class is the minimum required version. - # This is expected to be SDK release 0.9.13 - if not hasattr(_quota.Quota, 'allow_get'): - # Just run this when sdk <= 0.9.10 - result = self.cmd.take_action(parsed_args) - kwargs = { - 'subnet': network_fakes.QUOTA['subnet'], - 'network': network_fakes.QUOTA['network'], - 'floatingip': network_fakes.QUOTA['floatingip'], - 'subnetpool': network_fakes.QUOTA['subnetpool'], - 'security_group_rule': - network_fakes.QUOTA['security_group_rule'], - 'security_group': network_fakes.QUOTA['security_group'], - 'router': network_fakes.QUOTA['router'], - 'rbac_policy': network_fakes.QUOTA['rbac_policy'], - 'port': network_fakes.QUOTA['port'], - 'vip': network_fakes.QUOTA['vip'], - 'healthmonitor': network_fakes.QUOTA['healthmonitor'], - 'l7policy': network_fakes.QUOTA['l7policy'], - } - self.network_mock.update_quota.assert_called_once_with( - identity_fakes.project_id, - **kwargs - ) - self.assertIsNone(result) + result = self.cmd.take_action(parsed_args) + kwargs = { + 'subnet': network_fakes.QUOTA['subnet'], + 'network': network_fakes.QUOTA['network'], + 'floatingip': network_fakes.QUOTA['floatingip'], + 'subnetpool': network_fakes.QUOTA['subnetpool'], + 'security_group_rule': + network_fakes.QUOTA['security_group_rule'], + 'security_group': network_fakes.QUOTA['security_group'], + 'router': network_fakes.QUOTA['router'], + 'rbac_policy': network_fakes.QUOTA['rbac_policy'], + 'port': network_fakes.QUOTA['port'], + 'vip': network_fakes.QUOTA['vip'], + 'healthmonitor': network_fakes.QUOTA['healthmonitor'], + 'l7policy': network_fakes.QUOTA['l7policy'], + } + self.network_mock.update_quota.assert_called_once_with( + identity_fakes.project_id, + **kwargs + ) + self.assertIsNone(result) def test_quota_set_with_class(self): arglist = [ @@ -483,20 +476,15 @@ class TestQuotaShow(TestQuota): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - # TODO(huanxuan): Remove this if condition once the fixed - # SDK QuotaDefault class is the minimum required version. - # This is expected to be SDK release 0.9.13 - if not hasattr(_quota.QuotaDefault, 'project'): - # Just run this when sdk <= 0.9.10 - self.cmd.take_action(parsed_args) - - self.quotas_mock.defaults.assert_called_once_with( - identity_fakes.project_id) - self.volume_quotas_mock.defaults.assert_called_once_with( - identity_fakes.project_id) - self.network.get_quota_default.assert_called_once_with( - identity_fakes.project_id) - self.assertNotCalled(self.network.get_quota) + self.cmd.take_action(parsed_args) + + self.quotas_mock.defaults.assert_called_once_with( + identity_fakes.project_id) + self.volume_quotas_mock.defaults.assert_called_once_with( + identity_fakes.project_id) + self.network.get_quota_default.assert_called_once_with( + identity_fakes.project_id) + self.assertNotCalled(self.network.get_quota) def test_quota_show_with_class(self): arglist = [ diff --git a/openstackclient/tests/unit/compute/v2/test_console.py b/openstackclient/tests/unit/compute/v2/test_console.py index d53d241e..3c708aae 100644 --- a/openstackclient/tests/unit/compute/v2/test_console.py +++ b/openstackclient/tests/unit/compute/v2/test_console.py @@ -35,11 +35,7 @@ class TestConsoleUrlShow(TestConsole): 'protocol': 'fake_protocol', 'type': 'fake_type'}} methods = { - 'get_vnc_console': fake_console_data, - 'get_spice_console': fake_console_data, - 'get_serial_console': fake_console_data, - 'get_rdp_console': fake_console_data, - 'get_mks_console': fake_console_data, + 'get_console_url': fake_console_data } self.fake_server = compute_fakes.FakeServer.create_one_server( methods=methods) @@ -68,7 +64,7 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_vnc_console.assert_called_once_with('novnc') + self.fake_server.get_console_url.assert_called_once_with('novnc') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -83,7 +79,7 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_vnc_console.assert_called_once_with('novnc') + self.fake_server.get_console_url.assert_called_once_with('novnc') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -98,7 +94,7 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_vnc_console.assert_called_once_with('xvpvnc') + self.fake_server.get_console_url.assert_called_once_with('xvpvnc') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -113,14 +109,14 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_spice_console.assert_called_once_with( + self.fake_server.get_console_url.assert_called_once_with( 'spice-html5') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def test_console_url_show_compatible(self): methods = { - 'get_vnc_console': {'console': {'url': 'http://localhost', + 'get_console_url': {'console': {'url': 'http://localhost', 'type': 'fake_type'}}, } old_fake_server = compute_fakes.FakeServer.create_one_server( @@ -130,8 +126,8 @@ class TestConsoleUrlShow(TestConsole): 'url', ) old_data = ( - methods['get_vnc_console']['console']['type'], - methods['get_vnc_console']['console']['url'] + methods['get_console_url']['console']['type'], + methods['get_console_url']['console']['url'] ) arglist = [ 'foo_vm', @@ -144,7 +140,7 @@ class TestConsoleUrlShow(TestConsole): with mock.patch.object(self.servers_mock, 'get', return_value=old_fake_server): columns, data = self.cmd.take_action(parsed_args) - old_fake_server.get_vnc_console.assert_called_once_with('novnc') + old_fake_server.get_console_url.assert_called_once_with('novnc') self.assertEqual(old_columns, columns) self.assertEqual(old_data, data) @@ -159,7 +155,7 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_rdp_console.assert_called_once_with( + self.fake_server.get_console_url.assert_called_once_with( 'rdp-html5') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -175,7 +171,7 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_serial_console.assert_called_once_with( + self.fake_server.get_console_url.assert_called_once_with( 'serial') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -191,6 +187,6 @@ class TestConsoleUrlShow(TestConsole): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.fake_server.get_mks_console.assert_called_once_with() + self.fake_server.get_console_url.assert_called_once_with('webmks') self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index 4cac990e..249902bc 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -467,6 +467,152 @@ class TestServerCreate(TestServer): self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) + def test_server_create_with_auto_network(self): + arglist = [ + '--image', 'image1', + '--flavor', 'flavor1', + '--nic', 'auto', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', 'flavor1'), + ('nic', ['auto']), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[], + nics='auto', + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_none_network(self): + arglist = [ + '--image', 'image1', + '--flavor', 'flavor1', + '--nic', 'none', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', 'flavor1'), + ('nic', ['none']), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[], + nics='none', + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_conflict_network_options(self): + arglist = [ + '--image', 'image1', + '--flavor', 'flavor1', + '--nic', 'none', + '--nic', 'auto', + '--nic', 'port-id=port1', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', 'flavor1'), + ('nic', ['none', 'auto', 'port-id=port1']), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + get_endpoints = mock.Mock() + get_endpoints.return_value = {'network': []} + self.app.client_manager.auth_ref = mock.Mock() + self.app.client_manager.auth_ref.service_catalog = mock.Mock() + self.app.client_manager.auth_ref.service_catalog.get_endpoints = ( + get_endpoints) + + find_port = mock.Mock() + network_client = self.app.client_manager.network + network_client.find_port = find_port + port_resource = mock.Mock() + port_resource.id = 'port1_uuid' + find_port.return_value = port_resource + + self.assertRaises(exceptions.CommandError, + self.cmd.take_action, parsed_args) + self.assertNotCalled(self.servers_mock.create) + + def test_server_create_with_invalid_network_options(self): + arglist = [ + '--image', 'image1', + '--flavor', 'flavor1', + '--nic', 'abcdefgh', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', 'flavor1'), + ('nic', ['abcdefgh']), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises(exceptions.CommandError, + self.cmd.take_action, parsed_args) + self.assertNotCalled(self.servers_mock.create) + @mock.patch.object(common_utils, 'wait_for_status', return_value=True) def test_server_create_with_wait_ok(self, mock_wait_for_status): arglist = [ diff --git a/openstackclient/tests/unit/fakes.py b/openstackclient/tests/unit/fakes.py index 626b466d..f28f9103 100644 --- a/openstackclient/tests/unit/fakes.py +++ b/openstackclient/tests/unit/fakes.py @@ -161,6 +161,9 @@ class FakeModule(object): def __init__(self, name, version): self.name = name self.__version__ = version + # Workaround for openstacksdk case + self.version = mock.Mock() + self.version.__version__ = version class FakeResource(object): diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index 4b266efb..6a73b7e9 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -71,6 +71,10 @@ class TestNetworkV2(utils.TestCommand): token=fakes.AUTH_TOKEN, ) + self.app.client_manager.sdk_connection = mock.Mock() + self.app.client_manager.sdk_connection.network = \ + self.app.client_manager.network + self.app.client_manager.identity = ( identity_fakes_v3.FakeIdentityv3Client( endpoint=fakes.AUTH_URL, @@ -386,6 +390,69 @@ class FakeNetwork(object): return mock.Mock(side_effect=networks) +class FakeNetworkFlavor(object): + """Fake Network Flavor.""" + + @staticmethod + def create_one_network_flavor(attrs=None): + """Create a fake network flavor. + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object faking the network flavor + """ + attrs = attrs or {} + + fake_uuid = uuid.uuid4().hex + network_flavor_attrs = { + 'description': 'network-flavor-description-' + fake_uuid, + 'enabled': True, + 'id': 'network-flavor-id-' + fake_uuid, + 'name': 'network-flavor-name-' + fake_uuid, + 'service_type': 'vpn', + 'tenant_id': 'project-id-' + uuid.uuid4().hex, + } + + # Overwrite default attributes. + network_flavor_attrs.update(attrs) + + network_flavor = fakes.FakeResource( + info=copy.deepcopy(network_flavor_attrs), + loaded=True + ) + + network_flavor.project_id = network_flavor_attrs['tenant_id'] + network_flavor.is_enabled = network_flavor_attrs['enabled'] + + return network_flavor + + @staticmethod + def create_flavor(attrs=None, count=2): + """Create multiple fake network flavors. + + :param Dictionary attrs: + A dictionary with all attributes + :param int count: + The number of network flavors to fake + :return: + A list of FakeResource objects faking the network falvors + """ + network_flavors = [] + for i in range(0, count): + network_flavors.append( + FakeNetworkFlavor.create_one_network_flavor(attrs) + ) + return network_flavors + + @staticmethod + def get_flavor(network_flavors=None, count=2): + """Get a list of flavors.""" + if network_flavors is None: + network_flavors = (FakeNetworkFlavor.create_flavor(count)) + return mock.Mock(side_effect=network_flavors) + + class FakeNetworkSegment(object): """Fake one or more network segments.""" diff --git a/openstackclient/tests/unit/network/v2/test_network_flavor.py b/openstackclient/tests/unit/network/v2/test_network_flavor.py new file mode 100644 index 00000000..11e27841 --- /dev/null +++ b/openstackclient/tests/unit/network/v2/test_network_flavor.py @@ -0,0 +1,407 @@ +# Copyright (c) 2016, Intel Corporation. +# 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. +# + +import mock + +from osc_lib import exceptions + +from openstackclient.network.v2 import network_flavor +from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes_v3 +from openstackclient.tests.unit.network.v2 import fakes as network_fakes +from openstackclient.tests.unit import utils as tests_utils + + +class TestNetworkFlavor(network_fakes.TestNetworkV2): + + def setUp(self): + super(TestNetworkFlavor, self).setUp() + + # Get a shortcut to the network client + self.network = self.app.client_manager.network + # Get a shortcut to the ProjectManager Mock + self.projects_mock = self.app.client_manager.identity.projects + # Get a shortcut to the DomainManager Mock + self.domains_mock = self.app.client_manager.identity.domains + + +class TestCreateNetworkFlavor(TestNetworkFlavor): + + project = identity_fakes_v3.FakeProject.create_one_project() + domain = identity_fakes_v3.FakeDomain.create_one_domain() + # The new network flavor created. + new_network_flavor = ( + network_fakes.FakeNetworkFlavor.create_one_network_flavor()) + columns = ( + 'description', + 'enabled', + 'id', + 'name', + 'project_id', + 'service_type' + ) + data = ( + new_network_flavor.description, + new_network_flavor.enabled, + new_network_flavor.id, + new_network_flavor.name, + new_network_flavor.project_id, + new_network_flavor.service_type, + ) + + def setUp(self): + super(TestCreateNetworkFlavor, self).setUp() + self.network.create_flavor = mock.Mock( + return_value=self.new_network_flavor) + + # Get the command object to test + self.cmd = network_flavor.CreateNetworkFlavor(self.app, self.namespace) + + self.projects_mock.get.return_value = self.project + self.domains_mock.get.return_value = self.domain + + def test_create_no_options(self): + arglist = [] + verifylist = [] + + # Missing required args should bail here + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_create_default_options(self): + arglist = [ + '--service-type', self.new_network_flavor.service_type, + self.new_network_flavor.name, + ] + verifylist = [ + ('service_type', self.new_network_flavor.service_type), + ('name', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = (self.cmd.take_action(parsed_args)) + + self.network.create_flavor.assert_called_once_with(**{ + 'service_type': self.new_network_flavor.service_type, + 'name': self.new_network_flavor.name, + }) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_create_all_options(self): + arglist = [ + '--description', self.new_network_flavor.description, + '--enable', + '--project', self.new_network_flavor.project_id, + '--project-domain', self.domain.name, + '--service-type', self.new_network_flavor.service_type, + self.new_network_flavor.name, + ] + verifylist = [ + ('description', self.new_network_flavor.description), + ('enable', True), + ('project', self.new_network_flavor.project_id), + ('project_domain', self.domain.name), + ('service_type', self.new_network_flavor.service_type), + ('name', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = (self.cmd.take_action(parsed_args)) + + self.network.create_flavor.assert_called_once_with(**{ + 'description': self.new_network_flavor.description, + 'enabled': True, + 'tenant_id': self.project.id, + 'service_type': self.new_network_flavor.service_type, + 'name': self.new_network_flavor.name, + }) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_create_disable(self): + arglist = [ + '--disable', + '--service-type', self.new_network_flavor.service_type, + self.new_network_flavor.name, + ] + verifylist = [ + ('disable', True), + ('service_type', self.new_network_flavor.service_type), + ('name', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.create_flavor.assert_called_once_with(**{ + 'enabled': False, + 'service_type': self.new_network_flavor.service_type, + 'name': self.new_network_flavor.name, + }) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + +class TestDeleteNetworkFlavor(TestNetworkFlavor): + + # The network flavor to delete. + _network_flavors = ( + network_fakes.FakeNetworkFlavor.create_flavor(count=2)) + + def setUp(self): + super(TestDeleteNetworkFlavor, self).setUp() + self.network.delete_flavor = mock.Mock(return_value=None) + self.network.find_flavor = ( + network_fakes.FakeNetworkFlavor.get_flavor( + network_flavors=self._network_flavors) + ) + + # Get the command object to test + self.cmd = network_flavor.DeleteNetworkFlavor(self.app, self.namespace) + + def test_network_flavor_delete(self): + arglist = [ + self._network_flavors[0].name, + ] + verifylist = [ + ('flavor', [self._network_flavors[0].name]), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.network.find_flavor.assert_called_once_with( + self._network_flavors[0].name, ignore_missing=False) + self.network.delete_flavor.assert_called_once_with( + self._network_flavors[0]) + self.assertIsNone(result) + + def test_multi_network_flavors_delete(self): + arglist = [] + verifylist = [] + + for a in self._network_flavors: + arglist.append(a.name) + verifylist = [ + ('flavor', arglist), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + calls = [] + for a in self._network_flavors: + calls.append(mock.call(a)) + self.network.delete_flavor.assert_has_calls(calls) + self.assertIsNone(result) + + def test_multi_network_flavors_delete_with_exception(self): + arglist = [ + self._network_flavors[0].name, + 'unexist_network_flavor', + ] + verifylist = [ + ('flavor', + [self._network_flavors[0].name, 'unexist_network_flavor']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + find_mock_result = [self._network_flavors[0], exceptions.CommandError] + self.network.find_flavor = ( + mock.Mock(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 flavors failed to delete.', str(e)) + + self.network.find_flavor.assert_any_call( + self._network_flavors[0].name, ignore_missing=False) + self.network.find_flavor.assert_any_call( + 'unexist_network_flavor', ignore_missing=False) + self.network.delete_flavor.assert_called_once_with( + self._network_flavors[0] + ) + + +class TestListNetworkFlavor(TestNetworkFlavor): + + # The network flavors to list up. + _network_flavors = ( + network_fakes.FakeNetworkFlavor.create_flavor(count=2)) + columns = ( + 'ID', + 'Name', + 'Enabled', + 'Service Type', + 'Description', + ) + data = [] + for flavor in _network_flavors: + data.append(( + flavor.id, + flavor.name, + flavor.enabled, + flavor.service_type, + flavor.description, + )) + + def setUp(self): + super(TestListNetworkFlavor, self).setUp() + self.network.flavors = mock.Mock( + return_value=self._network_flavors) + + # Get the command object to test + self.cmd = network_flavor.ListNetworkFlavor(self.app, self.namespace) + + def test_network_flavor_list(self): + arglist = [] + verifylist = [] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.flavors.assert_called_once_with(**{}) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + +class TestShowNetworkFlavor(TestNetworkFlavor): + + # The network flavor to show. + new_network_flavor = ( + network_fakes.FakeNetworkFlavor.create_one_network_flavor()) + columns = ( + 'description', + 'enabled', + 'id', + 'name', + 'project_id', + 'service_type' + ) + data = ( + new_network_flavor.description, + new_network_flavor.enabled, + new_network_flavor.id, + new_network_flavor.name, + new_network_flavor.project_id, + new_network_flavor.service_type, + ) + + def setUp(self): + super(TestShowNetworkFlavor, self).setUp() + self.network.find_flavor = mock.Mock( + return_value=self.new_network_flavor) + + # Get the command object to test + self.cmd = network_flavor.ShowNetworkFlavor(self.app, self.namespace) + + def test_show_no_options(self): + arglist = [] + verifylist = [] + + # Missing required args should bail here + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_show_all_options(self): + arglist = [ + self.new_network_flavor.name, + ] + verifylist = [ + ('flavor', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.network.find_flavor.assert_called_once_with( + self.new_network_flavor.name, ignore_missing=False) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + +class TestSetNetworkFlavor(TestNetworkFlavor): + + # The network flavor to set. + new_network_flavor = ( + network_fakes.FakeNetworkFlavor.create_one_network_flavor()) + + def setUp(self): + super(TestSetNetworkFlavor, self).setUp() + self.network.update_flavor = mock.Mock(return_value=None) + self.network.find_flavor = mock.Mock( + return_value=self.new_network_flavor) + + # Get the command object to test + self.cmd = network_flavor.SetNetworkFlavor(self.app, self.namespace) + + def test_set_nothing(self): + arglist = [self.new_network_flavor.name, ] + verifylist = [ + ('flavor', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + attrs = {} + self.network.update_flavor.assert_called_with( + self.new_network_flavor, **attrs) + self.assertIsNone(result) + + def test_set_name_and_enable(self): + arglist = [ + '--name', 'new_network_flavor', + '--enable', + self.new_network_flavor.name, + ] + verifylist = [ + ('name', 'new_network_flavor'), + ('enable', True), + ('flavor', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + attrs = { + 'name': "new_network_flavor", + 'enabled': True, + } + self.network.update_flavor.assert_called_with( + self.new_network_flavor, **attrs) + self.assertIsNone(result) + + def test_set_disable(self): + arglist = [ + '--disable', + self.new_network_flavor.name, + ] + verifylist = [ + ('disable', True), + ('flavor', self.new_network_flavor.name), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + attrs = { + 'enabled': False, + } + self.network.update_flavor.assert_called_with( + self.new_network_flavor, **attrs) + self.assertIsNone(result) diff --git a/openstackclient/tests/unit/volume/v1/fakes.py b/openstackclient/tests/unit/volume/v1/fakes.py index 78a8227e..fff5181d 100644 --- a/openstackclient/tests/unit/volume/v1/fakes.py +++ b/openstackclient/tests/unit/volume/v1/fakes.py @@ -364,6 +364,9 @@ class FakeVolumev1Client(object): self.qos_specs.resource_class = fakes.FakeResource(None, {}) self.volume_types = mock.Mock() self.volume_types.resource_class = fakes.FakeResource(None, {}) + self.volume_encryption_types = mock.Mock() + self.volume_encryption_types.resource_class = ( + fakes.FakeResource(None, {})) self.transfers = mock.Mock() self.transfers.resource_class = fakes.FakeResource(None, {}) self.volume_snapshots = mock.Mock() @@ -470,6 +473,34 @@ class FakeType(object): return mock.Mock(side_effect=types) + @staticmethod + def create_one_encryption_type(attrs=None): + """Create a fake encryption type. + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object with volume_type_id etc. + """ + attrs = attrs or {} + + # Set default attributes. + encryption_info = { + "volume_type_id": 'type-id-' + uuid.uuid4().hex, + 'provider': 'LuksEncryptor', + 'cipher': None, + 'key_size': None, + 'control_location': 'front-end', + } + + # Overwrite default attributes. + encryption_info.update(attrs) + + encryption_type = fakes.FakeResource( + info=copy.deepcopy(encryption_info), + loaded=True) + return encryption_type + class FakeSnapshot(object): """Fake one or more snapshot.""" diff --git a/openstackclient/tests/unit/volume/v1/test_qos_specs.py b/openstackclient/tests/unit/volume/v1/test_qos_specs.py index 464038e7..e3dc1e78 100644 --- a/openstackclient/tests/unit/volume/v1/test_qos_specs.py +++ b/openstackclient/tests/unit/volume/v1/test_qos_specs.py @@ -70,23 +70,22 @@ class TestQosAssociate(TestQos): class TestQosCreate(TestQos): - new_qos_spec = volume_fakes.FakeQos.create_one_qos() columns = ( 'consumer', 'id', 'name', - 'specs' - ) - datalist = ( - new_qos_spec.consumer, - new_qos_spec.id, - new_qos_spec.name, - new_qos_spec.specs + 'properties' ) def setUp(self): super(TestQosCreate, self).setUp() - + self.new_qos_spec = volume_fakes.FakeQos.create_one_qos() + self.datalist = ( + self.new_qos_spec.consumer, + self.new_qos_spec.id, + self.new_qos_spec.name, + utils.format_dict(self.new_qos_spec.specs) + ) self.qos_mock.create.return_value = self.new_qos_spec # Get the command object to test self.cmd = qos_specs.CreateQos(self.app, None) @@ -336,7 +335,7 @@ class TestQosList(TestQos): 'Name', 'Consumer', 'Associations', - 'Specs', + 'Properties', ) self.assertEqual(collist, columns) datalist = (( @@ -413,7 +412,7 @@ class TestQosShow(TestQos): 'consumer', 'id', 'name', - 'specs' + 'properties' ) self.assertEqual(collist, columns) datalist = ( diff --git a/openstackclient/tests/unit/volume/v1/test_type.py b/openstackclient/tests/unit/volume/v1/test_type.py index 81ad8301..dcdd3d56 100644 --- a/openstackclient/tests/unit/volume/v1/test_type.py +++ b/openstackclient/tests/unit/volume/v1/test_type.py @@ -31,6 +31,10 @@ class TestType(volume_fakes.TestVolumev1): self.types_mock = self.app.client_manager.volume.volume_types self.types_mock.reset_mock() + self.encryption_types_mock = ( + self.app.client_manager.volume.volume_encryption_types) + self.encryption_types_mock.reset_mock() + class TestTypeCreate(TestType): @@ -75,6 +79,67 @@ class TestTypeCreate(TestType): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_type_create_with_encryption(self): + encryption_info = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': '128', + 'control_location': 'front-end', + } + encryption_type = volume_fakes.FakeType.create_one_encryption_type( + attrs=encryption_info + ) + self.new_volume_type = volume_fakes.FakeType.create_one_type( + attrs={'encryption': encryption_info}) + self.types_mock.create.return_value = self.new_volume_type + self.encryption_types_mock.create.return_value = encryption_type + encryption_columns = ( + 'description', + 'encryption', + 'id', + 'is_public', + 'name', + ) + encryption_data = ( + self.new_volume_type.description, + utils.format_dict(encryption_info), + self.new_volume_type.id, + True, + self.new_volume_type.name, + ) + arglist = [ + '--encryption-provider', 'LuksEncryptor', + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-key-size', '128', + '--encryption-control-location', 'front-end', + self.new_volume_type.name, + ] + verifylist = [ + ('encryption_provider', 'LuksEncryptor'), + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_key_size', 128), + ('encryption_control_location', 'front-end'), + ('name', self.new_volume_type.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.types_mock.create.assert_called_with( + self.new_volume_type.name, + ) + body = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end', + } + self.encryption_types_mock.create.assert_called_with( + self.new_volume_type, + body, + ) + self.assertEqual(encryption_columns, columns) + self.assertEqual(encryption_data, data) + class TestTypeDelete(TestType): @@ -156,17 +221,17 @@ class TestTypeList(TestType): volume_types = volume_fakes.FakeType.create_types() - columns = ( + columns = [ "ID", "Name", "Is Public", - ) - columns_long = ( + ] + columns_long = [ "ID", "Name", "Is Public", "Properties" - ) + ] data = [] for t in volume_types: @@ -188,6 +253,8 @@ class TestTypeList(TestType): super(TestTypeList, self).setUp() self.types_mock.list.return_value = self.volume_types + self.encryption_types_mock.create.return_value = None + self.encryption_types_mock.update.return_value = None # get the command to test self.cmd = volume_type.ListVolumeType(self.app, None) @@ -195,6 +262,7 @@ class TestTypeList(TestType): arglist = [] verifylist = [ ("long", False), + ("encryption_type", False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -217,6 +285,47 @@ class TestTypeList(TestType): self.assertEqual(self.columns_long, columns) self.assertEqual(self.data_long, list(data)) + def test_type_list_with_encryption(self): + encryption_type = volume_fakes.FakeType.create_one_encryption_type( + attrs={'volume_type_id': self.volume_types[0].id}) + encryption_info = { + 'provider': 'LuksEncryptor', + 'cipher': None, + 'key_size': None, + 'control_location': 'front-end', + } + encryption_columns = self.columns + [ + "Encryption", + ] + encryption_data = [] + encryption_data.append(( + self.volume_types[0].id, + self.volume_types[0].name, + self.volume_types[0].is_public, + utils.format_dict(encryption_info), + )) + encryption_data.append(( + self.volume_types[1].id, + self.volume_types[1].name, + self.volume_types[1].is_public, + '-', + )) + + self.encryption_types_mock.list.return_value = [encryption_type] + arglist = [ + "--encryption-type", + ] + verifylist = [ + ("encryption_type", True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.encryption_types_mock.list.assert_called_once_with() + self.types_mock.list.assert_called_once_with() + self.assertEqual(encryption_columns, columns) + self.assertEqual(encryption_data, list(data)) + class TestTypeSet(TestType): @@ -260,6 +369,60 @@ class TestTypeSet(TestType): {'myprop': 'myvalue'}) self.assertIsNone(result) + def test_type_set_new_encryption(self): + arglist = [ + '--encryption-provider', 'LuksEncryptor', + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-key-size', '128', + '--encryption-control-location', 'front-end', + self.volume_type.id, + ] + verifylist = [ + ('encryption_provider', 'LuksEncryptor'), + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_key_size', 128), + ('encryption_control_location', 'front-end'), + ('volume_type', self.volume_type.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + body = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end', + } + self.encryption_types_mock.create.assert_called_with( + self.volume_type, + body, + ) + self.assertIsNone(result) + + def test_type_set_new_encryption_without_provider(self): + arglist = [ + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-key-size', '128', + '--encryption-control-location', 'front-end', + self.volume_type.id, + ] + verifylist = [ + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_key_size', 128), + ('encryption_control_location', 'front-end'), + ('volume_type', self.volume_type.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("Command Failed: One or more of" + " the operations failed", + str(e)) + self.encryption_types_mock.create.assert_not_called() + self.encryption_types_mock.update.assert_not_called() + class TestTypeShow(TestType): @@ -293,7 +456,8 @@ class TestTypeShow(TestType): self.volume_type.id ] verifylist = [ - ("volume_type", self.volume_type.id) + ("volume_type", self.volume_type.id), + ("encryption_type", False), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -303,6 +467,50 @@ class TestTypeShow(TestType): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_type_show_with_encryption(self): + encryption_type = volume_fakes.FakeType.create_one_encryption_type() + encryption_info = { + 'provider': 'LuksEncryptor', + 'cipher': None, + 'key_size': None, + 'control_location': 'front-end', + } + self.volume_type = volume_fakes.FakeType.create_one_type( + attrs={'encryption': encryption_info}) + self.types_mock.get.return_value = self.volume_type + self.encryption_types_mock.get.return_value = encryption_type + encryption_columns = ( + 'description', + 'encryption', + 'id', + 'is_public', + 'name', + 'properties', + ) + encryption_data = ( + self.volume_type.description, + utils.format_dict(encryption_info), + self.volume_type.id, + True, + self.volume_type.name, + utils.format_dict(self.volume_type.extra_specs) + ) + arglist = [ + '--encryption-type', + self.volume_type.id + ] + verifylist = [ + ('encryption_type', True), + ("volume_type", self.volume_type.id) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.types_mock.get.assert_called_with(self.volume_type.id) + self.encryption_types_mock.get.assert_called_with(self.volume_type.id) + self.assertEqual(encryption_columns, columns) + self.assertEqual(encryption_data, data) + class TestTypeUnset(TestType): @@ -317,13 +525,14 @@ class TestTypeUnset(TestType): # Get the command object to test self.cmd = volume_type.UnsetVolumeType(self.app, None) - def test_type_unset(self): + def test_type_unset_property(self): arglist = [ '--property', 'property', '--property', 'multi_property', self.volume_type.id, ] verifylist = [ + ('encryption_type', False), ('property', ['property', 'multi_property']), ('volume_type', self.volume_type.id), ] @@ -333,6 +542,7 @@ class TestTypeUnset(TestType): result = self.cmd.take_action(parsed_args) self.volume_type.unset_keys.assert_called_once_with( ['property', 'multi_property']) + self.encryption_types_mock.delete.assert_not_called() self.assertIsNone(result) def test_type_unset_failed_with_missing_volume_type_argument(self): @@ -362,3 +572,18 @@ class TestTypeUnset(TestType): result = self.cmd.take_action(parsed_args) self.assertIsNone(result) + + def test_type_unset_encryption_type(self): + arglist = [ + '--encryption-type', + self.volume_type.id, + ] + verifylist = [ + ('encryption_type', True), + ('volume_type', self.volume_type.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.encryption_types_mock.delete.assert_called_with(self.volume_type) + self.assertIsNone(result) diff --git a/openstackclient/tests/unit/volume/v2/fakes.py b/openstackclient/tests/unit/volume/v2/fakes.py index a6676403..d54faec7 100644 --- a/openstackclient/tests/unit/volume/v2/fakes.py +++ b/openstackclient/tests/unit/volume/v2/fakes.py @@ -208,6 +208,9 @@ class FakeVolumeClient(object): self.volume_types.resource_class = fakes.FakeResource(None, {}) self.volume_type_access = mock.Mock() self.volume_type_access.resource_class = fakes.FakeResource(None, {}) + self.volume_encryption_types = mock.Mock() + self.volume_encryption_types.resource_class = ( + fakes.FakeResource(None, {})) self.restores = mock.Mock() self.restores.resource_class = fakes.FakeResource(None, {}) self.qos_specs = mock.Mock() @@ -923,3 +926,31 @@ class FakeType(object): types = FakeType.create_types(count) return mock.Mock(side_effect=types) + + @staticmethod + def create_one_encryption_type(attrs=None): + """Create a fake encryption type. + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object with volume_type_id etc. + """ + attrs = attrs or {} + + # Set default attributes. + encryption_info = { + "volume_type_id": 'type-id-' + uuid.uuid4().hex, + 'provider': 'LuksEncryptor', + 'cipher': None, + 'key_size': None, + 'control_location': 'front-end', + } + + # Overwrite default attributes. + encryption_info.update(attrs) + + encryption_type = fakes.FakeResource( + info=copy.deepcopy(encryption_info), + loaded=True) + return encryption_type diff --git a/openstackclient/tests/unit/volume/v2/test_type.py b/openstackclient/tests/unit/volume/v2/test_type.py index cec01bd8..4023d55b 100644 --- a/openstackclient/tests/unit/volume/v2/test_type.py +++ b/openstackclient/tests/unit/volume/v2/test_type.py @@ -36,6 +36,10 @@ class TestType(volume_fakes.TestVolume): self.app.client_manager.volume.volume_type_access) self.types_access_mock.reset_mock() + self.encryption_types_mock = ( + self.app.client_manager.volume.volume_encryption_types) + self.encryption_types_mock.reset_mock() + self.projects_mock = self.app.client_manager.identity.projects self.projects_mock.reset_mock() @@ -131,6 +135,68 @@ class TestTypeCreate(TestType): self.cmd.take_action, parsed_args) + def test_type_create_with_encryption(self): + encryption_info = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': '128', + 'control_location': 'front-end', + } + encryption_type = volume_fakes.FakeType.create_one_encryption_type( + attrs=encryption_info + ) + self.new_volume_type = volume_fakes.FakeType.create_one_type( + attrs={'encryption': encryption_info}) + self.types_mock.create.return_value = self.new_volume_type + self.encryption_types_mock.create.return_value = encryption_type + encryption_columns = ( + 'description', + 'encryption', + 'id', + 'is_public', + 'name', + ) + encryption_data = ( + self.new_volume_type.description, + utils.format_dict(encryption_info), + self.new_volume_type.id, + True, + self.new_volume_type.name, + ) + arglist = [ + '--encryption-provider', 'LuksEncryptor', + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-key-size', '128', + '--encryption-control-location', 'front-end', + self.new_volume_type.name, + ] + verifylist = [ + ('encryption_provider', 'LuksEncryptor'), + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_key_size', 128), + ('encryption_control_location', 'front-end'), + ('name', self.new_volume_type.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.types_mock.create.assert_called_with( + self.new_volume_type.name, + description=None, + ) + body = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end', + } + self.encryption_types_mock.create.assert_called_with( + self.new_volume_type, + body, + ) + self.assertEqual(encryption_columns, columns) + self.assertEqual(encryption_data, data) + class TestTypeDelete(TestType): @@ -305,6 +371,7 @@ class TestTypeList(TestType): "--default", ] verifylist = [ + ("encryption_type", False), ("long", False), ("private", False), ("public", False), @@ -317,6 +384,47 @@ class TestTypeList(TestType): self.assertEqual(self.columns, columns) self.assertEqual(self.data_with_default_type, list(data)) + def test_type_list_with_encryption(self): + encryption_type = volume_fakes.FakeType.create_one_encryption_type( + attrs={'volume_type_id': self.volume_types[0].id}) + encryption_info = { + 'provider': 'LuksEncryptor', + 'cipher': None, + 'key_size': None, + 'control_location': 'front-end', + } + encryption_columns = self.columns + [ + "Encryption", + ] + encryption_data = [] + encryption_data.append(( + self.volume_types[0].id, + self.volume_types[0].name, + self.volume_types[0].is_public, + utils.format_dict(encryption_info), + )) + encryption_data.append(( + self.volume_types[1].id, + self.volume_types[1].name, + self.volume_types[1].is_public, + '-', + )) + + self.encryption_types_mock.list.return_value = [encryption_type] + arglist = [ + "--encryption-type", + ] + verifylist = [ + ("encryption_type", True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.encryption_types_mock.list.assert_called_once_with() + self.types_mock.list.assert_called_once_with(is_public=None) + self.assertEqual(encryption_columns, columns) + self.assertEqual(encryption_data, list(data)) + class TestTypeSet(TestType): @@ -331,6 +439,8 @@ class TestTypeSet(TestType): # Return a project self.projects_mock.get.return_value = self.project + self.encryption_types_mock.create.return_value = None + self.encryption_types_mock.update.return_value = None # Get the command object to test self.cmd = volume_type.SetVolumeType(self.app, None) @@ -454,6 +564,107 @@ class TestTypeSet(TestType): self.project.id, ) + def test_type_set_new_encryption(self): + self.encryption_types_mock.update.side_effect = ( + exceptions.NotFound('NotFound')) + arglist = [ + '--encryption-provider', 'LuksEncryptor', + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-key-size', '128', + '--encryption-control-location', 'front-end', + self.volume_type.id, + ] + verifylist = [ + ('encryption_provider', 'LuksEncryptor'), + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_key_size', 128), + ('encryption_control_location', 'front-end'), + ('volume_type', self.volume_type.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + body = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end', + } + self.encryption_types_mock.update.assert_called_with( + self.volume_type, + body, + ) + self.encryption_types_mock.create.assert_called_with( + self.volume_type, + body, + ) + self.assertIsNone(result) + + @mock.patch.object(utils, 'find_resource') + def test_type_set_existing_encryption(self, mock_find): + mock_find.side_effect = [self.volume_type, + "existing_encryption_type"] + arglist = [ + '--encryption-provider', 'LuksEncryptor', + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-control-location', 'front-end', + self.volume_type.id, + ] + verifylist = [ + ('encryption_provider', 'LuksEncryptor'), + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_control_location', 'front-end'), + ('volume_type', self.volume_type.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + body = { + 'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'control_location': 'front-end', + } + self.encryption_types_mock.update.assert_called_with( + self.volume_type, + body, + ) + self.encryption_types_mock.create.assert_not_called() + self.assertIsNone(result) + + def test_type_set_new_encryption_without_provider(self): + self.encryption_types_mock.update.side_effect = ( + exceptions.NotFound('NotFound')) + arglist = [ + '--encryption-cipher', 'aes-xts-plain64', + '--encryption-key-size', '128', + '--encryption-control-location', 'front-end', + self.volume_type.id, + ] + verifylist = [ + ('encryption_cipher', 'aes-xts-plain64'), + ('encryption_key_size', 128), + ('encryption_control_location', 'front-end'), + ('volume_type', self.volume_type.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("Command Failed: One or more of" + " the operations failed", + str(e)) + body = { + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end', + } + self.encryption_types_mock.update.assert_called_with( + self.volume_type, + body, + ) + self.encryption_types_mock.create.assert_not_called() + class TestTypeShow(TestType): @@ -489,6 +700,7 @@ class TestTypeShow(TestType): self.volume_type.id ] verifylist = [ + ("encryption_type", False), ("volume_type", self.volume_type.id) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -564,6 +776,52 @@ class TestTypeShow(TestType): ) self.assertEqual(private_type_data, data) + def test_type_show_with_encryption(self): + encryption_type = volume_fakes.FakeType.create_one_encryption_type() + encryption_info = { + 'provider': 'LuksEncryptor', + 'cipher': None, + 'key_size': None, + 'control_location': 'front-end', + } + self.volume_type = volume_fakes.FakeType.create_one_type( + attrs={'encryption': encryption_info}) + self.types_mock.get.return_value = self.volume_type + self.encryption_types_mock.get.return_value = encryption_type + encryption_columns = ( + 'access_project_ids', + 'description', + 'encryption', + 'id', + 'is_public', + 'name', + 'properties', + ) + encryption_data = ( + None, + self.volume_type.description, + utils.format_dict(encryption_info), + self.volume_type.id, + True, + self.volume_type.name, + utils.format_dict(self.volume_type.extra_specs) + ) + arglist = [ + '--encryption-type', + self.volume_type.id + ] + verifylist = [ + ('encryption_type', True), + ("volume_type", self.volume_type.id) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.types_mock.get.assert_called_with(self.volume_type.id) + self.encryption_types_mock.get.assert_called_with(self.volume_type.id) + self.assertEqual(encryption_columns, columns) + self.assertEqual(encryption_data, data) + class TestTypeUnset(TestType): @@ -625,6 +883,7 @@ class TestTypeUnset(TestType): self.volume_type.id, ] verifylist = [ + ('encryption_type', False), ('project', ''), ('volume_type', self.volume_type.id), ] @@ -633,7 +892,7 @@ class TestTypeUnset(TestType): result = self.cmd.take_action(parsed_args) self.assertIsNone(result) - + self.encryption_types_mock.delete.assert_not_called() self.assertFalse(self.types_access_mock.remove_project_access.called) def test_type_unset_failed_with_missing_volume_type_argument(self): @@ -649,3 +908,18 @@ class TestTypeUnset(TestType): self.cmd, arglist, verifylist) + + def test_type_unset_encryption_type(self): + arglist = [ + '--encryption-type', + self.volume_type.id, + ] + verifylist = [ + ('encryption_type', True), + ('volume_type', self.volume_type.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.encryption_types_mock.delete.assert_called_with(self.volume_type) + self.assertIsNone(result) diff --git a/openstackclient/tests/unit/volume/v2/test_volume_host.py b/openstackclient/tests/unit/volume/v2/test_volume_host.py index aad7bb0b..b024329a 100644 --- a/openstackclient/tests/unit/volume/v2/test_volume_host.py +++ b/openstackclient/tests/unit/volume/v2/test_volume_host.py @@ -35,6 +35,7 @@ class TestVolumeHostSet(TestVolumeHost): self.host_mock.freeze_host.return_value = None self.host_mock.thaw_host.return_value = None + # Get the command object to mock self.cmd = volume_host.SetVolumeHost(self.app, None) def test_volume_host_set_nothing(self): @@ -84,3 +85,33 @@ class TestVolumeHostSet(TestVolumeHost): self.host_mock.freeze_host.assert_called_with(self.service.host) self.host_mock.thaw_host.assert_not_called() self.assertIsNone(result) + + +class TestVolumeHostFailover(TestVolumeHost): + + service = host_fakes.FakeService.create_one_service() + + def setUp(self): + super(TestVolumeHostFailover, self).setUp() + + self.host_mock.failover_host.return_value = None + + # Get the command object to mock + self.cmd = volume_host.FailoverVolumeHost(self.app, None) + + def test_volume_host_failover(self): + arglist = [ + '--volume-backend', 'backend_test', + self.service.host, + ] + verifylist = [ + ('volume_backend', 'backend_test'), + ('host', self.service.host), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.host_mock.failover_host.assert_called_with( + self.service.host, 'backend_test') + self.assertIsNone(result) |
