Fix boot-from-volume test in project.instances.tests

The test for the instance table with boot-from-volume had
several issues previously.

a) api.cinder.volume_list is mocked but return_value was not
   specified and called arguments were not checked.
b) The mocked api.nova.server_list returned Server instance
   from novaclient, but it should return Server instance from
   the horizon API wrapper (api.nova.Server). As a result,
   for example, "image_name" property in api.nova.Server
   was skipped.
c) Test data for cinder volumes had wrong attachment information.
   attachment ID must match a volume ID, but it did not.

This commit fixes the above issues and adds a test logic to
check volume_image_metadata handling in instances/views.py.

This is a preparation to implement a unit test in
https://review.opendev.org/#/c/668595/.

NOTE:
The issues (a) and (b) above need to be fixed globally
in the openstack_dashboard testing, but it will be covered
by follow-up commit(s). This commit focues to prepare for
https://review.opendev.org/#/c/668595/.

Change-Id: I7ebb68220f75fef36b43b89e32e5aff18fc0fe25
This commit is contained in:
Akihiro Motoki 2019-07-12 15:56:42 +09:00
parent 67ca5ad9f7
commit 82a20c670a
2 changed files with 29 additions and 7 deletions

View File

@ -393,12 +393,28 @@ class InstanceTableTests(InstanceTestBase, InstanceTableTestMixin):
api.cinder: ('volume_list',), api.cinder: ('volume_list',),
}) })
def test_index_with_instance_booted_from_volume(self): def test_index_with_instance_booted_from_volume(self):
volume_server = self.servers.first()
volume_server.image = ""
volume_server.image_name = "(not found)"
servers = self.servers.list() servers = self.servers.list()
volume_server = servers[0]
# Override the server is booted from a volume.
volume_server.image = ""
# NOTE(amotoki): openstack_dashboard.api.nova.server_list should return
# a list of api.nova.Server instances, but the current test code
# returns a list of novaclient.v2.servers.Server instances.
# This leads to a situation that image_name property of api.nova.Server
# is not handled in our test case properly.
# TODO(amotoki): Refactor test_data/nova_data.py to use api.nova.Server
# (horizon API wrapper class).
volume_server = api.nova.Server(volume_server, self.request)
servers[0] = volume_server servers[0] = volume_server
volumes = self.cinder_volumes.list()
# 3rd volume in the list is attached to server with ID 1.
volume = volumes[2]
base_image = self.images.get(name='private_image')
volume.volume_image_metadata = {
"image_id": base_image.id,
}
self._mock_extension_supported({'AdminActions': True, self._mock_extension_supported({'AdminActions': True,
'Shelve': True}) 'Shelve': True})
self.mock_is_feature_available.return_value = True self.mock_is_feature_available.return_value = True
@ -410,13 +426,14 @@ class InstanceTableTests(InstanceTestBase, InstanceTableTestMixin):
self.mock_tenant_absolute_limits.return_value = self.limits['absolute'] self.mock_tenant_absolute_limits.return_value = self.limits['absolute']
self.mock_floating_ip_supported.return_value = True self.mock_floating_ip_supported.return_value = True
self.mock_floating_ip_simple_associate_supported.return_value = True self.mock_floating_ip_simple_associate_supported.return_value = True
self.mock_volume_list.return_value = volumes
res = self.client.get(INDEX_URL) res = self.client.get(INDEX_URL)
self.assertTemplateUsed(res, INDEX_TEMPLATE) self.assertTemplateUsed(res, INDEX_TEMPLATE)
instances = res.context['instances_table'].data instances = res.context['instances_table'].data
self.assertEqual(len(instances), len(servers)) self.assertEqual(len(instances), len(servers))
self.assertContains(res, "(not found)") self.assertContains(res, base_image.name)
self._check_extension_supported({'AdminActions': 16, self._check_extension_supported({'AdminActions': 16,
'Shelve': 4}) 'Shelve': 4})
@ -442,6 +459,7 @@ class InstanceTableTests(InstanceTestBase, InstanceTableTestMixin):
self.assert_mock_multiple_calls_with_same_arguments( self.assert_mock_multiple_calls_with_same_arguments(
self.mock_floating_ip_simple_associate_supported, 4, self.mock_floating_ip_simple_associate_supported, 4,
mock.call(helpers.IsHttpRequest())) mock.call(helpers.IsHttpRequest()))
self.mock_volume_list.assert_called_once_with(helpers.IsHttpRequest())
def test_index_with_console_link(self): def test_index_with_console_link(self):
res = self._get_index() res = self._get_index()

View File

@ -118,7 +118,8 @@ def data(TEST):
'created_at': '2013-04-01 10:30:00', 'created_at': '2013-04-01 10:30:00',
'volume_type': None, 'volume_type': None,
'bootable': 'true', 'bootable': 'true',
'attachments': [{"id": "1", "server_id": '1', 'attachments': [{"id": "21023e92-8008-1234-8059-7f2293ff3889",
"server_id": '1',
"device": "/dev/hda"}]}) "device": "/dev/hda"}]})
volume_with_type = volumes.Volume( volume_with_type = volumes.Volume(
volumes.VolumeManager(None), volumes.VolumeManager(None),
@ -131,7 +132,8 @@ def data(TEST):
'created_at': '2013-04-01 10:30:00', 'created_at': '2013-04-01 10:30:00',
'volume_type': 'vol_type_2', 'volume_type': 'vol_type_2',
'bootable': 'false', 'bootable': 'false',
'attachments': [{"id": "2", "server_id": '2', 'attachments': [{"id": "7dcb47fd-07d9-42c2-9647-be5eab799ebe",
"server_id": '2',
"device": "/dev/hdb"}]}) "device": "/dev/hdb"}]})
non_bootable_volume = volumes.Volume( non_bootable_volume = volumes.Volume(
volumes.VolumeManager(None), volumes.VolumeManager(None),
@ -143,7 +145,9 @@ def data(TEST):
'created_at': '2013-04-01 10:30:00', 'created_at': '2013-04-01 10:30:00',
'volume_type': None, 'volume_type': None,
'bootable': 'false', 'bootable': 'false',
'attachments': [{"id": "1", "server_id": '1', 'bootable': False,
'attachments': [{"id": "21023e92-8008-1234-8059-7f2293ff3890",
"server_id": '1',
"device": "/dev/hda"}]}) "device": "/dev/hda"}]})
volume.bootable = 'true' volume.bootable = 'true'