diff --git a/novaclient/base.py b/novaclient/base.py index 74c7e2fe2..a07bd2497 100644 --- a/novaclient/base.py +++ b/novaclient/base.py @@ -274,6 +274,9 @@ class BootingManagerWithFind(ManagerWithFind): """Like a `ManagerWithFind`, but has the ability to boot servers.""" def _parse_block_device_mapping(self, block_device_mapping): + """Parses legacy block device mapping.""" + # FIXME(andreykurilin): make it work with block device mapping v2 + bdm = [] for device_name, mapping in six.iteritems(block_device_mapping): @@ -285,15 +288,9 @@ class BootingManagerWithFind(ManagerWithFind): mapping_parts = mapping.split(':') source_id = mapping_parts[0] - bdm_dict['uuid'] = source_id - bdm_dict['boot_index'] = 0 - if len(mapping_parts) == 1: - bdm_dict['volume_id'] = source_id - bdm_dict['source_type'] = 'volume' - elif len(mapping_parts) > 1: + if len(mapping_parts) > 1: source_type = mapping_parts[1] - bdm_dict['source_type'] = source_type if source_type.startswith('snap'): bdm_dict['snapshot_id'] = source_id else: diff --git a/novaclient/tests/functional/base.py b/novaclient/tests/functional/base.py index f39dbf0e5..8b0e17266 100644 --- a/novaclient/tests/functional/base.py +++ b/novaclient/tests/functional/base.py @@ -193,6 +193,28 @@ class ClientTestBase(testtools.TestCase): self.fail("Volume %s did not reach status %s after %d s" % (volume.id, status, timeout)) + def wait_for_resource_delete(self, resource, manager, + timeout=60, poll_interval=1): + """Wait until getting the resource raises NotFound exception. + + :param resource: Resource object. + :param manager: Manager object with get method. + :param timeout: timeout in seconds + :param poll_interval: poll interval in seconds + """ + start_time = time.time() + while time.time() - start_time < timeout: + try: + manager.get(resource) + except Exception as e: + if getattr(e, "http_status", None) == 404: + break + else: + raise + time.sleep(poll_interval) + else: + self.fail("The resource '%s' still exists." % resource.id) + def name_generate(self, prefix='Entity'): """Generate randomized name for some entity. @@ -200,3 +222,24 @@ class ClientTestBase(testtools.TestCase): """ name = "%s-%s" % (prefix, six.text_type(uuid.uuid4())) return name + + def _get_value_from_the_table(self, table, key): + """Parses table to get desired value. + + EXAMPLE of the table: + # +-------------+----------------------------------+ + # | Property | Value | + # +-------------+----------------------------------+ + # | description | | + # | enabled | True | + # | id | 582df899eabc47018c96713c2f7196ba | + # | name | admin | + # +-------------+----------------------------------+ + """ + lines = table.split("\n") + for line in lines: + if "|" in line: + l_property, l_value = line.split("|")[1:3] + if l_property.strip() == key: + return l_value.strip() + raise ValueError("Property '%s' is missing from the table." % key) diff --git a/novaclient/tests/functional/test_quotas.py b/novaclient/tests/functional/test_quotas.py index 3b75ed5f6..cd6392fd5 100644 --- a/novaclient/tests/functional/test_quotas.py +++ b/novaclient/tests/functional/test_quotas.py @@ -25,19 +25,10 @@ class TestQuotasNovaClient(base.ClientTestBase): 'server_groups', 'server_group_members'] def test_quotas_update(self): - # `nova quota-update` requires tenant-id. EXAMPLE of keystone output: - # +-------------+----------------------------------+ - # | Property | Value | - # +-------------+----------------------------------+ - # | description | | - # | enabled | True | - # | id | 582df899eabc47018c96713c2f7196ba | - # | name | admin | - # +-------------+----------------------------------+ + # `nova quota-update` requires tenant-id. tenant_info = self.cli_clients.keystone( - "tenant-get", params=self.cli_clients.tenant_name).split("\n") - tenant_id = [l.rsplit("|", 2)[-2].strip() - for l in tenant_info if "id" in l][0] + "tenant-get", params=self.cli_clients.tenant_name) + tenant_id = self._get_value_from_the_table(tenant_info, "id") self.addCleanup(self.client.quotas.delete, tenant_id) diff --git a/novaclient/tests/functional/test_servers.py b/novaclient/tests/functional/test_servers.py index 9de2cb2c5..75be3f472 100644 --- a/novaclient/tests/functional/test_servers.py +++ b/novaclient/tests/functional/test_servers.py @@ -16,6 +16,30 @@ from novaclient.tests.functional import base from novaclient.v2 import shell +class TestServersBootNovaClient(base.ClientTestBase): + """Servers boot functional tests. + """ + + def test_boot_server_with_legacy_bdm(self): + volume_size = 1 + volume_name = str(uuid.uuid4()) + volume = self.client.volumes.create(size=volume_size, + display_name=volume_name, + imageRef=self.image.id) + self.wait_for_volume_status(volume, "available") + + server_info = self.nova("boot", params=( + "%(name)s --flavor %(flavor)s --poll " + "--block-device-mapping vda=%(volume_id)s:::1" % { + "name": str(uuid.uuid4()), "flavor": + self.flavor.id, + "volume_id": volume.id})) + server_id = self._get_value_from_the_table(server_info, "id") + + self.client.servers.delete(server_id) + self.wait_for_resource_delete(server_id, self.client.servers) + + class TestServersListNovaClient(base.ClientTestBase): """Servers list functional tests. """ diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py index 9b5e0396e..ed68c383e 100644 --- a/novaclient/tests/unit/v2/test_shell.py +++ b/novaclient/tests/unit/v2/test_shell.py @@ -274,10 +274,7 @@ class ShellTest(utils.TestCase): { 'volume_id': 'blah', 'delete_on_termination': '0', - 'device_name': 'vda', - 'uuid': 'blah', - 'boot_index': 0, - 'source_type': '' + 'device_name': 'vda' } ], 'imageRef': '',