diff --git a/nova/compute/api.py b/nova/compute/api.py index aa7ea23dbea6..1cf915196efa 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2147,9 +2147,8 @@ class API(base.Base): 'user_id': str(context.user_id), 'image_type': image_type, } - image_ref = instance.image_ref - sent_meta = compute_utils.get_image_metadata( - context, self.image_api, image_ref, instance) + sent_meta = utils.get_image_from_system_metadata( + instance.system_metadata) # Delete properties that are non-inheritable image_props = sent_meta.get("properties", {}) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 71442861c683..03e23fae11a2 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -3120,9 +3120,7 @@ class ComputeManager(manager.Manager): instance=instance) rescue_image_ref = instance.image_ref - image_meta = compute_utils.get_image_metadata(context, self.image_api, - rescue_image_ref, - instance) + image_meta = self.image_api.get(context, rescue_image_ref) # NOTE(belliott) bug #1227350 - xenapi needs the actual image id image_meta['id'] = rescue_image_ref return image_meta @@ -4677,9 +4675,8 @@ class ComputeManager(manager.Manager): 'ports'), {'ports': len(network_info)}) raise exception.InterfaceAttachFailed( instance_uuid=instance.uuid) - image_ref = instance.get('image_ref') - image_meta = compute_utils.get_image_metadata( - context, self.image_api, image_ref, instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) try: self.driver.attach_interface(instance, image_meta, network_info[0]) @@ -6204,9 +6201,8 @@ class ComputeManager(manager.Manager): def quiesce_instance(self, context, instance): """Quiesce an instance on this host.""" context = context.elevated() - image_ref = instance.image_ref - image_meta = compute_utils.get_image_metadata( - context, self.image_api, image_ref, instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) self.driver.quiesce(context, instance, image_meta) def _wait_for_snapshots_completion(self, context, mapping): @@ -6240,7 +6236,6 @@ class ComputeManager(manager.Manager): LOG.exception(_LE("Exception while waiting completion of " "volume snapshots: %s"), error, instance=instance) - image_ref = instance.image_ref - image_meta = compute_utils.get_image_metadata( - context, self.image_api, image_ref, instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) self.driver.unquiesce(context, instance, image_meta) diff --git a/nova/compute/utils.py b/nova/compute/utils.py index 0c3989ff9a5b..124147cf99f2 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -196,34 +196,6 @@ def _get_unused_letter(used_letters): return letters[0] -def get_image_metadata(context, image_api, image_id_or_uri, instance): - image_system_meta = {} - # In case of boot from volume, image_id_or_uri may be None or '' - if image_id_or_uri is not None and image_id_or_uri != '': - # If the base image is still available, get its metadata - try: - image = image_api.get(context, image_id_or_uri) - except (exception.ImageNotAuthorized, - exception.ImageNotFound, - exception.Invalid) as e: - LOG.warning(_LW("Can't access image %(image_id)s: %(error)s"), - {"image_id": image_id_or_uri, "error": e}, - instance=instance) - else: - flavor = instance.get_flavor() - image_system_meta = utils.get_system_metadata_from_image(image, - flavor) - - # Get the system metadata from the instance - system_meta = utils.instance_sys_meta(instance) - - # Merge the metadata from the instance with the image's, if any - system_meta.update(image_system_meta) - - # Convert the system metadata to image metadata - return utils.get_image_from_system_metadata(system_meta) - - def get_value_from_system_metadata(instance, key, type, default): """Get a value of a specified type from image metadata. diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index d06d621a4a54..730dc144cc48 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -46,6 +46,7 @@ from nova.objects import base as nova_object from nova import quota from nova.scheduler import client as scheduler_client from nova.scheduler import utils as scheduler_utils +from nova import utils LOG = logging.getLogger(__name__) @@ -535,9 +536,8 @@ class ComputeTaskManager(base.Base): def _cold_migrate(self, context, instance, flavor, filter_properties, reservations, clean_shutdown): - image_ref = instance.image_ref - image = compute_utils.get_image_metadata( - context, self.image_api, image_ref, instance) + image = utils.get_image_from_system_metadata( + instance.system_metadata) request_spec = scheduler_utils.build_request_spec( context, image, [instance], instance_type=flavor) diff --git a/nova/conductor/tasks/live_migrate.py b/nova/conductor/tasks/live_migrate.py index 38b37f867262..79027783b2b2 100644 --- a/nova/conductor/tasks/live_migrate.py +++ b/nova/conductor/tasks/live_migrate.py @@ -15,7 +15,6 @@ from oslo_log import log as logging from nova.compute import power_state from nova.compute import rpcapi as compute_rpcapi -from nova.compute import utils as compute_utils from nova import exception from nova.i18n import _ from nova import image @@ -23,6 +22,7 @@ from nova import objects from nova.scheduler import client as scheduler_client from nova.scheduler import utils as scheduler_utils from nova import servicegroup +from nova import utils LOG = logging.getLogger(__name__) @@ -147,12 +147,8 @@ class LiveMigrationTask(object): def _find_destination(self): # TODO(johngarbutt) this retry loop should be shared attempted_hosts = [self.source] - image = None - if self.instance.image_ref: - image = compute_utils.get_image_metadata(self.context, - self.image_api, - self.instance.image_ref, - self.instance) + image = utils.get_image_from_system_metadata( + self.instance.system_metadata) request_spec = scheduler_utils.build_request_spec(self.context, image, [self.instance]) diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index f9b15cf8957f..3954128fd64e 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -60,6 +60,7 @@ from nova.console import type as ctype from nova import context from nova import db from nova import exception +from nova.image import api as image_api from nova.image import glance from nova.network import api as network_api from nova.network import model as network_model @@ -2186,11 +2187,10 @@ class ComputeTestCase(BaseTestCase): self.assertEqual('some_random_state', inst_obj.vm_state) - @mock.patch.object(nova.compute.utils, "get_image_metadata") + @mock.patch.object(image_api.API, "get") @mock.patch.object(nova.virt.fake.FakeDriver, "rescue") def test_rescue_with_image_specified(self, mock_rescue, - mock_get_image_metadata): - + mock_image_get): image_ref = "image-ref" rescue_image_meta = {} params = {"task_state": task_states.RESCUING} @@ -2200,24 +2200,21 @@ class ComputeTestCase(BaseTestCase): mock_context = mock.Mock() mock_context.elevated.return_value = ctxt - mock_get_image_metadata.return_value = rescue_image_meta + mock_image_get.return_value = rescue_image_meta self.compute.rescue_instance(mock_context, instance=instance, rescue_password="password", rescue_image_ref=image_ref, clean_shutdown=True) - mock_get_image_metadata.assert_called_with(ctxt, - self.compute.image_api, - image_ref, instance) + mock_image_get.assert_called_with(ctxt, image_ref) mock_rescue.assert_called_with(ctxt, instance, [], rescue_image_meta, 'password') self.compute.terminate_instance(ctxt, instance, [], []) - @mock.patch.object(nova.compute.utils, "get_image_metadata") + @mock.patch.object(image_api.API, "get") @mock.patch.object(nova.virt.fake.FakeDriver, "rescue") def test_rescue_with_base_image_when_image_not_specified(self, - mock_rescue, mock_get_image_metadata): - + mock_rescue, mock_image_get): image_ref = "image-ref" system_meta = {"image_base_image_ref": image_ref} rescue_image_meta = {} @@ -2229,16 +2226,15 @@ class ComputeTestCase(BaseTestCase): mock_context = mock.Mock() mock_context.elevated.return_value = ctxt - mock_get_image_metadata.return_value = rescue_image_meta + mock_image_get.return_value = rescue_image_meta self.compute.rescue_instance(mock_context, instance=instance, rescue_password="password", rescue_image_ref=None, clean_shutdown=True) - mock_get_image_metadata.assert_called_with(ctxt, - self.compute.image_api, - image_ref, instance) + mock_image_get.assert_called_with(ctxt, image_ref) + mock_rescue.assert_called_with(ctxt, instance, [], rescue_image_meta, 'password') self.compute.terminate_instance(self.context, instance, [], []) diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py index 90fd16be4dad..1d89dacfeef6 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -51,6 +51,7 @@ from nova.tests.unit import matchers from nova.tests.unit.objects import test_flavor from nova.tests.unit.objects import test_migration from nova.tests.unit.objects import test_service +from nova import utils from nova.volume import cinder @@ -1764,7 +1765,7 @@ class _ComputeAPIUnitTestMixIn(object): extra_props = dict(cow='moo', cat='meow') - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(self.compute_api.image_api, 'create') self.mox.StubOutWithMock(instance, 'save') @@ -1780,9 +1781,8 @@ class _ComputeAPIUnitTestMixIn(object): self.compute_api.is_volume_backed_instance(self.context, instance).AndReturn(False) - compute_utils.get_image_metadata( - self.context, self.compute_api.image_api, - FAKE_IMAGE_REF, instance).AndReturn(fake_image_meta) + utils.get_image_from_system_metadata( + instance.system_metadata).AndReturn(fake_image_meta) fake_image = dict(id='fake-image-id') mock_method = self.compute_api.image_api.create( diff --git a/nova/tests/unit/compute/test_compute_utils.py b/nova/tests/unit/compute/test_compute_utils.py index 143af51b9423..cf4c074faf4b 100644 --- a/nova/tests/unit/compute/test_compute_utils.py +++ b/nova/tests/unit/compute/test_compute_utils.py @@ -25,7 +25,6 @@ from oslo_config import cfg from oslo_serialization import jsonutils from oslo_utils import importutils import six -import testtools from nova.compute import flavors from nova.compute import power_state @@ -38,7 +37,6 @@ from nova.image import glance from nova.network import api as network_api from nova import objects from nova.objects import block_device as block_device_obj -from nova.objects import instance as instance_obj from nova import rpc from nova import test from nova.tests.unit import fake_block_device @@ -47,9 +45,7 @@ from nova.tests.unit import fake_network from nova.tests.unit import fake_notifier from nova.tests.unit import fake_server_actions import nova.tests.unit.image.fake -from nova.tests.unit import matchers from nova.tests.unit.objects import test_flavor -from nova import utils from nova.virt import driver CONF = cfg.CONF @@ -637,147 +633,6 @@ class UsageInfoTestCase(test.TestCase): self.assertEqual(len(fake_notifier.NOTIFICATIONS), 0) -class ComputeGetImageMetadataTestCase(test.NoDBTestCase): - def setUp(self): - super(ComputeGetImageMetadataTestCase, self).setUp() - self.context = context.RequestContext('fake', 'fake') - - self.image = { - "min_ram": 10, - "min_disk": 1, - "disk_format": "raw", - "container_format": "bare", - "properties": {}, - } - - self.mock_image_api = mock.Mock() - self.mock_image_api.get.return_value = self.image - - self.ctx = context.RequestContext('fake', 'fake') - - sys_meta = { - 'image_min_ram': 10, - 'image_min_disk': 1, - 'image_disk_format': 'raw', - 'image_container_format': 'bare', - } - - flavor = objects.Flavor( - id=0, - name='m1.fake', - memory_mb=10, - vcpus=1, - root_gb=1, - ephemeral_gb=1, - flavorid='0', - swap=1, - rxtx_factor=0.0, - vcpu_weight=None) - - instance = fake_instance.fake_db_instance( - memory_mb=0, root_gb=0, - system_metadata=sys_meta) - self.instance_obj = objects.Instance._from_db_object( - self.ctx, objects.Instance(), instance, - expected_attrs=instance_obj.INSTANCE_DEFAULT_FIELDS) - with mock.patch.object(self.instance_obj, 'save'): - self.instance_obj.set_flavor(flavor) - - @mock.patch('nova.objects.Flavor.get_by_flavor_id') - def test_get_image_meta(self, mock_get): - mock_get.return_value = objects.Flavor(extra_specs={}) - image_meta = compute_utils.get_image_metadata( - self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) - - self.image['properties'] = 'DONTCARE' - self.assertThat(self.image, matchers.DictMatches(image_meta)) - - @mock.patch('nova.objects.Flavor.get_by_flavor_id') - def test_get_image_meta_with_image_id_none(self, mock_flavor_get): - mock_flavor_get.return_value = objects.Flavor(extra_specs={}) - self.image['properties'] = {'fake_property': 'fake_value'} - - inst = self.instance_obj - - with mock.patch.object(flavors, - "extract_flavor") as mock_extract_flavor: - with mock.patch.object(utils, "get_system_metadata_from_image" - ) as mock_get_sys_metadata: - image_meta = compute_utils.get_image_metadata( - self.ctx, self.mock_image_api, None, inst) - - self.assertEqual(0, self.mock_image_api.get.call_count) - self.assertEqual(0, mock_extract_flavor.call_count) - self.assertEqual(0, mock_get_sys_metadata.call_count) - self.assertNotIn('fake_property', image_meta['properties']) - - # Checking mock_image_api_get is called with 0 image_id - # as 0 is a valid image ID - image_meta = compute_utils.get_image_metadata(self.ctx, - self.mock_image_api, - 0, self.instance_obj) - self.assertEqual(1, self.mock_image_api.get.call_count) - self.assertIn('fake_property', image_meta['properties']) - - def _test_get_image_meta_exception(self, error): - self.mock_image_api.get.side_effect = error - - image_meta = compute_utils.get_image_metadata( - self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) - - self.image['properties'] = 'DONTCARE' - # NOTE(danms): The trip through system_metadata will stringify things - for key in self.image: - self.image[key] = str(self.image[key]) - self.assertThat(self.image, matchers.DictMatches(image_meta)) - - def test_get_image_meta_no_image(self): - error = exception.ImageNotFound(image_id='fake-image') - self._test_get_image_meta_exception(error) - - def test_get_image_meta_not_authorized(self): - error = exception.ImageNotAuthorized(image_id='fake-image') - self._test_get_image_meta_exception(error) - - def test_get_image_meta_bad_request(self): - error = exception.Invalid() - self._test_get_image_meta_exception(error) - - def test_get_image_meta_unexpected_exception(self): - error = test.TestingException() - with testtools.ExpectedException(test.TestingException): - self._test_get_image_meta_exception(error) - - def test_get_image_meta_no_image_system_meta(self): - for k in self.instance_obj.system_metadata.keys(): - if k.startswith('image_'): - del self.instance_obj.system_metadata[k] - - with mock.patch('nova.objects.Flavor.get_by_flavor_id') as get: - get.return_value = objects.Flavor(extra_specs={}) - image_meta = compute_utils.get_image_metadata( - self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) - - self.image['properties'] = 'DONTCARE' - self.assertThat(self.image, matchers.DictMatches(image_meta)) - - def test_get_image_meta_no_image_no_image_system_meta(self): - e = exception.ImageNotFound(image_id='fake-image') - self.mock_image_api.get.side_effect = e - - for k in self.instance_obj.system_metadata.keys(): - if k.startswith('image_'): - del self.instance_obj.system_metadata[k] - - with mock.patch('nova.objects.Flavor.get_by_flavor_id') as get: - get.return_value = objects.Flavor(extra_specs={}) - image_meta = compute_utils.get_image_metadata( - self.ctx, self.mock_image_api, 'fake-image', self.instance_obj) - - expected = {'properties': 'DONTCARE'} - self.assertThat(expected, matchers.DictMatches(image_meta)) - - class ComputeUtilsGetValFromSysMetadata(test.NoDBTestCase): def test_get_value_from_system_metadata(self): diff --git a/nova/tests/unit/conductor/tasks/test_live_migrate.py b/nova/tests/unit/conductor/tasks/test_live_migrate.py index 1c2865ec283f..decca75b2e7b 100644 --- a/nova/tests/unit/conductor/tasks/test_live_migrate.py +++ b/nova/tests/unit/conductor/tasks/test_live_migrate.py @@ -13,13 +13,13 @@ from mox3 import mox from nova.compute import power_state -from nova.compute import utils as compute_utils from nova.conductor.tasks import live_migrate from nova import exception from nova import objects from nova.scheduler import utils as scheduler_utils from nova import test from nova.tests.unit import fake_instance +from nova import utils class LiveMigrationTaskTestCase(test.NoDBTestCase): @@ -37,6 +37,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): image_ref=self.instance_image) self.instance = objects.Instance._from_db_object( self.context, objects.Instance(), db_instance) + self.instance.system_metadata = {'image_hw_disk_bus': 'scsi'} self.destination = "destination" self.block_migration = "bm" self.disk_over_commit = "doc" @@ -228,7 +229,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): self.task._check_requested_destination) def test_find_destination_works(self): - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, @@ -237,9 +238,8 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') - compute_utils.get_image_metadata(self.context, - self.task.image_api, self.instance_image, - self.instance).AndReturn("image") + utils.get_image_from_system_metadata( + self.instance.system_metadata).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( @@ -264,8 +264,10 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') - scheduler_utils.build_request_spec(self.context, None, - mox.IgnoreArg()).AndReturn({}) + scheduler_utils.build_request_spec( + self.context, + {'properties': {'hw_disk_bus': 'scsi'}}, + mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( self.context, {}, {'ignore_hosts': [self.instance_host]}) self.task.scheduler_client.select_destinations(self.context, @@ -278,7 +280,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): self.assertEqual("host1", self.task._find_destination()) def _test_find_destination_retry_hypervisor_raises(self, error): - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, @@ -287,9 +289,8 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') - compute_utils.get_image_metadata(self.context, - self.task.image_api, self.instance_image, - self.instance).AndReturn("image") + utils.get_image_from_system_metadata( + self.instance.system_metadata).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( @@ -321,7 +322,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): def test_find_destination_retry_with_invalid_livem_checks(self): self.flags(migrate_max_retries=1) - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, @@ -330,9 +331,8 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): '_check_compatible_with_source_hypervisor') self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host') - compute_utils.get_image_metadata(self.context, - self.task.image_api, self.instance_image, - self.instance).AndReturn("image") + utils.get_image_from_system_metadata( + self.instance.system_metadata).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( @@ -357,7 +357,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): def test_find_destination_retry_exceeds_max(self): self.flags(migrate_max_retries=0) - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, @@ -365,9 +365,8 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): self.mox.StubOutWithMock(self.task, '_check_compatible_with_source_hypervisor') - compute_utils.get_image_metadata(self.context, - self.task.image_api, self.instance_image, - self.instance).AndReturn("image") + utils.get_image_from_system_metadata( + self.instance.system_metadata).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( @@ -382,14 +381,13 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): self.assertRaises(exception.NoValidHost, self.task._find_destination) def test_find_destination_when_runs_out_of_hosts(self): - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.task.scheduler_client, 'select_destinations') - compute_utils.get_image_metadata(self.context, - self.task.image_api, self.instance_image, - self.instance).AndReturn("image") + utils.get_image_from_system_metadata( + self.instance.system_metadata).AndReturn("image") scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({}) scheduler_utils.setup_instance_group( diff --git a/nova/tests/unit/conductor/test_conductor.py b/nova/tests/unit/conductor/test_conductor.py index 0df9c89562b0..74cd3abe5373 100644 --- a/nova/tests/unit/conductor/test_conductor.py +++ b/nova/tests/unit/conductor/test_conductor.py @@ -942,7 +942,7 @@ class _BaseTaskTestCase(object): 'block_migration', 'disk_over_commit') def _test_cold_migrate(self, clean_shutdown=True): - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock( @@ -952,13 +952,13 @@ class _BaseTaskTestCase(object): inst = fake_instance.fake_db_instance(image_ref='image_ref') inst_obj = objects.Instance._from_db_object( self.context, objects.Instance(), inst, []) + inst_obj.system_metadata = {'image_hw_disk_bus': 'scsi'} flavor = flavors.get_default_flavor() flavor.extra_specs = {'extra_specs': 'fake'} request_spec = {'instance_type': obj_base.obj_to_primitive(flavor), 'instance_properties': {}} - compute_utils.get_image_metadata( - self.context, self.conductor_manager.image_api, - 'image_ref', mox.IsA(objects.Instance)).AndReturn('image') + utils.get_image_from_system_metadata( + inst_obj.system_metadata).AndReturn('image') scheduler_utils.build_request_spec( self.context, 'image', @@ -1619,18 +1619,20 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): def test_cold_migrate_no_valid_host_back_in_active_state(self): flavor = flavors.get_flavor_by_name('m1.tiny') - inst = fake_instance.fake_db_instance(image_ref='fake-image_ref', - instance_type_id=flavor['id']) - inst_obj = objects.Instance._from_db_object( - self.context, objects.Instance(), inst, - expected_attrs=[]) + inst_obj = objects.Instance( + image_ref='fake-image_ref', + instance_type_id=flavor['id'], + vm_state=vm_states.ACTIVE, + system_metadata={}, + uuid='fake', + user_id='fake') request_spec = dict(instance_type=dict(extra_specs=dict()), instance_properties=dict()) filter_props = dict(context=None) resvs = 'fake-resvs' image = 'fake-image' - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.conductor.scheduler_client, @@ -1639,9 +1641,8 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): '_set_vm_state_and_notify') self.mox.StubOutWithMock(quota.QUOTAS, 'rollback') - compute_utils.get_image_metadata( - self.context, self.conductor_manager.image_api, - 'fake-image_ref', mox.IsA(objects.Instance)).AndReturn(image) + utils.get_image_from_system_metadata( + inst_obj.system_metadata).AndReturn(image) scheduler_utils.build_request_spec( self.context, image, [inst_obj], @@ -1681,19 +1682,20 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): def test_cold_migrate_no_valid_host_back_in_stopped_state(self): flavor = flavors.get_flavor_by_name('m1.tiny') - inst = fake_instance.fake_db_instance(image_ref='fake-image_ref', - vm_state=vm_states.STOPPED, - instance_type_id=flavor['id']) - inst_obj = objects.Instance._from_db_object( - self.context, objects.Instance(), inst, - expected_attrs=[]) + inst_obj = objects.Instance( + image_ref='fake-image_ref', + vm_state=vm_states.STOPPED, + instance_type_id=flavor['id'], + system_metadata={}, + uuid='fake', + user_id='fake') request_spec = dict(instance_type=dict(extra_specs=dict()), instance_properties=dict()) filter_props = dict(context=None) resvs = 'fake-resvs' image = 'fake-image' - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.conductor.scheduler_client, @@ -1702,9 +1704,8 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): '_set_vm_state_and_notify') self.mox.StubOutWithMock(quota.QUOTAS, 'rollback') - compute_utils.get_image_metadata( - self.context, self.conductor_manager.image_api, - 'fake-image_ref', mox.IsA(objects.Instance)).AndReturn(image) + utils.get_image_from_system_metadata( + inst_obj.system_metadata).AndReturn(image) scheduler_utils.build_request_spec( self.context, image, [inst_obj], @@ -1743,12 +1744,13 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): def test_cold_migrate_no_valid_host_error_msg(self): flavor = flavors.get_flavor_by_name('m1.tiny') - inst = fake_instance.fake_db_instance(image_ref='fake-image_ref', - vm_state=vm_states.STOPPED, - instance_type_id=flavor['id']) - inst_obj = objects.Instance._from_db_object( - self.context, objects.Instance(), inst, - expected_attrs=[]) + inst_obj = objects.Instance( + image_ref='fake-image_ref', + vm_state=vm_states.STOPPED, + instance_type_id=flavor['id'], + system_metadata={}, + uuid='fake', + user_id='fake') request_spec = dict(instance_type=dict(extra_specs=dict()), instance_properties=dict()) filter_props = dict(context=None) @@ -1756,7 +1758,7 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): image = 'fake-image' with contextlib.nested( - mock.patch.object(compute_utils, 'get_image_metadata', + mock.patch.object(utils, 'get_image_from_system_metadata', return_value=image), mock.patch.object(scheduler_utils, 'build_request_spec', return_value=request_spec), @@ -1773,7 +1775,7 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): clean_shutdown=True) self.assertIn('cold migrate', nvh.message) - @mock.patch.object(compute_utils, 'get_image_metadata') + @mock.patch.object(utils, 'get_image_from_system_metadata') @mock.patch('nova.scheduler.utils.build_request_spec') @mock.patch.object(scheduler_utils, 'setup_instance_group') @mock.patch.object(conductor_manager.ComputeTaskManager, @@ -1784,12 +1786,13 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): brs_mock, image_mock): flavor = flavors.get_flavor_by_name('m1.tiny') - inst = fake_instance.fake_db_instance(image_ref='fake-image_ref', - vm_state=vm_states.STOPPED, - instance_type_id=flavor['id']) - inst_obj = objects.Instance._from_db_object( - self.context, objects.Instance(), inst, - expected_attrs=[]) + inst_obj = objects.Instance( + image_ref='fake-image_ref', + vm_state=vm_states.STOPPED, + instance_type_id=flavor['id'], + system_metadata={}, + uuid='fake', + user_id='fake') request_spec = dict(instance_type=dict(extra_specs=dict()), instance_properties=dict()) filter_props = dict(context=None) @@ -1812,11 +1815,14 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): exception, request_spec) def test_cold_migrate_exception_host_in_error_state_and_raise(self): - inst = fake_instance.fake_db_instance(image_ref='fake-image_ref', - vm_state=vm_states.STOPPED) - inst_obj = objects.Instance._from_db_object( - self.context, objects.Instance(), inst, - expected_attrs=[]) + flavor = flavors.get_flavor_by_name('m1.tiny') + inst_obj = objects.Instance( + image_ref='fake-image_ref', + vm_state=vm_states.STOPPED, + instance_type_id=flavor['id'], + system_metadata={}, + uuid='fake', + user_id='fake') request_spec = dict(instance_type=dict(), instance_properties=dict()) filter_props = dict(context=None) @@ -1824,7 +1830,7 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): image = 'fake-image' hosts = [dict(host='host1', nodename=None, limits={})] - self.mox.StubOutWithMock(compute_utils, 'get_image_metadata') + self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata') self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec') self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group') self.mox.StubOutWithMock(self.conductor.scheduler_client, @@ -1837,9 +1843,8 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): '_set_vm_state_and_notify') self.mox.StubOutWithMock(quota.QUOTAS, 'rollback') - compute_utils.get_image_metadata( - self.context, self.conductor_manager.image_api, - 'fake-image_ref', mox.IsA(objects.Instance)).AndReturn(image) + utils.get_image_from_system_metadata( + inst_obj.system_metadata).AndReturn(image) scheduler_utils.build_request_spec( self.context, image, [inst_obj], @@ -1896,12 +1901,14 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): def test_resize_no_valid_host_error_msg(self): flavor = flavors.get_flavor_by_name('m1.tiny') flavor_new = flavors.get_flavor_by_name('m1.small') - inst = fake_instance.fake_db_instance(image_ref='fake-image_ref', - vm_state=vm_states.STOPPED, - instance_type_id=flavor['id']) - inst_obj = objects.Instance._from_db_object( - self.context, objects.Instance(), inst, - expected_attrs=[]) + inst_obj = objects.Instance( + image_ref='fake-image_ref', + vm_state=vm_states.STOPPED, + instance_type_id=flavor['id'], + system_metadata={}, + uuid='fake', + user_id='fake') + request_spec = dict(instance_type=dict(extra_specs=dict()), instance_properties=dict()) filter_props = dict(context=None) @@ -1909,7 +1916,7 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): image = 'fake-image' with contextlib.nested( - mock.patch.object(compute_utils, 'get_image_metadata', + mock.patch.object(utils, 'get_image_from_system_metadata', return_value=image), mock.patch.object(scheduler_utils, 'build_request_spec', return_value=request_spec), diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 964843e018f5..d0130f961a3a 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -51,7 +51,6 @@ from nova.compute import cpumodel from nova.compute import manager from nova.compute import power_state from nova.compute import task_states -from nova.compute import utils as compute_utils from nova.compute import vm_mode from nova.compute import vm_states from nova import context @@ -8274,7 +8273,8 @@ class LibvirtConnTestCase(test.NoDBTestCase): @mock.patch.object(FakeVirtDomain, 'attachDevice') @mock.patch.object(FakeVirtDomain, 'ID', return_value=1) - @mock.patch.object(compute_utils, 'get_image_metadata', return_value=None) + @mock.patch.object(utils, 'get_image_from_system_metadata', + return_value=None) def test_attach_sriov_ports(self, mock_get_image_metadata, mock_ID, @@ -8287,13 +8287,14 @@ class LibvirtConnTestCase(test.NoDBTestCase): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr._attach_sriov_ports(self.context, instance, guest, network_info) - mock_get_image_metadata.assert_called_once_with(self.context, - drvr._image_api, instance['image_ref'], instance) + mock_get_image_metadata.assert_called_once_with( + instance.system_metadata) self.assertTrue(mock_attachDevice.called) @mock.patch.object(FakeVirtDomain, 'attachDevice') @mock.patch.object(FakeVirtDomain, 'ID', return_value=1) - @mock.patch.object(compute_utils, 'get_image_metadata', return_value=None) + @mock.patch.object(utils, 'get_image_from_system_metadata', + return_value=None) def test_attach_sriov_ports_with_info_cache(self, mock_get_image_metadata, mock_ID, @@ -8308,14 +8309,15 @@ class LibvirtConnTestCase(test.NoDBTestCase): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr._attach_sriov_ports(self.context, instance, guest, None) - mock_get_image_metadata.assert_called_once_with(self.context, - drvr._image_api, instance['image_ref'], instance) + mock_get_image_metadata.assert_called_once_with( + instance.system_metadata) self.assertTrue(mock_attachDevice.called) @mock.patch.object(host.Host, 'has_min_version', return_value=True) @mock.patch.object(FakeVirtDomain, 'detachDeviceFlags') - @mock.patch.object(compute_utils, 'get_image_metadata', return_value=None) + @mock.patch.object(utils, 'get_image_from_system_metadata', + return_value=None) def test_detach_sriov_ports(self, mock_get_image_metadata, mock_detachDeviceFlags, @@ -8331,8 +8333,8 @@ class LibvirtConnTestCase(test.NoDBTestCase): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr._detach_sriov_ports(self.context, instance, domain) - mock_get_image_metadata.assert_called_once_with(mock.ANY, - drvr._image_api, instance['image_ref'], instance) + mock_get_image_metadata.assert_called_once_with( + instance.system_metadata) self.assertTrue(mock_detachDeviceFlags.called) def test_resume(self): @@ -8358,7 +8360,7 @@ class LibvirtConnTestCase(test.NoDBTestCase): mock.patch.object(drvr, '_attach_pci_devices'), mock.patch.object(pci_manager, 'get_instance_pci_devs', return_value='fake_pci_devs'), - mock.patch.object(compute_utils, 'get_image_metadata'), + mock.patch.object(utils, 'get_image_from_system_metadata'), mock.patch.object(blockinfo, 'get_disk_info'), ) as (_get_existing_domain_xml, _create_domain_and_network, _attach_pci_devices, get_instance_pci_devs, get_image_metadata, @@ -11844,7 +11846,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): fake_enable_hairpin) self.stubs.Set(self.drvr, 'get_info', fake_get_info) - self.stubs.Set(compute_utils, 'get_image_metadata', lambda *a: {}) + self.stubs.Set(utils, 'get_image_from_system_metadata', lambda *a: {}) with utils.tempdir() as tmpdir: self.flags(instances_path=tmpdir) @@ -11877,6 +11879,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): return None context = 'fake_context' + instance = self._create_instance() self.mox.StubOutWithMock(libvirt_utils, 'get_instance_path') self.mox.StubOutWithMock(os.path, 'exists') self.mox.StubOutWithMock(shutil, 'rmtree') @@ -11890,7 +11893,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): self.stubs.Set(loopingcall, 'FixedIntervalLoopingCall', lambda *a, **k: FakeLoopingCall()) - libvirt_utils.get_instance_path({}).AndReturn('/fake/foo') + libvirt_utils.get_instance_path(instance).AndReturn('/fake/foo') os.path.exists('/fake/foo_resize').AndReturn(backup_made) if backup_made: if del_inst_failed: @@ -11902,7 +11905,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): self.mox.ReplayAll() - self.drvr.finish_revert_migration(context, {}, []) + self.drvr.finish_revert_migration(context, instance, []) def test_finish_revert_migration_after_crash(self): self._test_finish_revert_migration_after_crash(backup_made=True) @@ -11930,7 +11933,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase): with contextlib.nested( mock.patch.object(drvr, '_create_domain_and_network'), - mock.patch.object(compute_utils, 'get_image_metadata', + mock.patch.object(utils, 'get_image_from_system_metadata', return_value=image_meta), mock.patch.object(drvr, '_get_guest_xml', side_effect=fake_get_guest_xml)): @@ -12664,14 +12667,6 @@ class LibvirtDriverTestCase(test.NoDBTestCase): instance = objects.Instance(uuid='fake-uuid', id=1) self.assertTrue(drvr.instance_on_disk(instance)) - @mock.patch("nova.compute.utils.get_image_metadata") - def test_prepare_args_for_get_config(self, mock_image): - instance = self._create_instance() - - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI()) - - drvr._prepare_args_for_get_config(self.context, instance) - def test_get_interfaces(self): dom_xml = """ @@ -13659,6 +13654,9 @@ class LibvirtSnapshotTests(_BaseSnapshotTests): def test_ami(self): # Assign different image_ref from nova/images/fakes for testing ami self.instance_ref.image_ref = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77' + self.instance_ref.system_metadata = \ + utils.get_system_metadata_from_image( + {'disk_format': 'ami'}) self._test_snapshot(disk_format='ami') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 1ec5baaaa4e9..5cbe8e8bc551 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -1288,7 +1288,8 @@ class LibvirtDriver(driver.ComputeDriver): raise exception.InterfaceDetachFailed( instance_uuid=instance.uuid) - def _create_snapshot_metadata(self, base, instance, img_fmt, snp_name): + def _create_snapshot_metadata(self, image_meta, instance, + img_fmt, snp_name): metadata = {'is_public': False, 'status': 'active', 'name': snp_name, @@ -1304,12 +1305,13 @@ class LibvirtDriver(driver.ComputeDriver): metadata['properties']['os_type'] = instance.os_type # NOTE(vish): glance forces ami disk format to be ami - if base.get('disk_format') == 'ami': + if image_meta.get('disk_format') == 'ami': metadata['disk_format'] = 'ami' else: metadata['disk_format'] = img_fmt - metadata['container_format'] = base.get('container_format', 'bare') + metadata['container_format'] = image_meta.get( + 'container_format', 'bare') return metadata @@ -1328,10 +1330,8 @@ class LibvirtDriver(driver.ComputeDriver): except exception.InstanceNotFound: raise exception.InstanceNotRunning(instance_id=instance.uuid) - base_image_ref = instance.image_ref - - base = compute_utils.get_image_metadata( - context, self._image_api, base_image_ref, instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) snapshot = self._image_api.get(context, image_id) @@ -1344,7 +1344,7 @@ class LibvirtDriver(driver.ComputeDriver): if image_format == 'lvm' or image_format == 'rbd': image_format = 'raw' - metadata = self._create_snapshot_metadata(base, + metadata = self._create_snapshot_metadata(image_meta, instance, image_format, snapshot['name']) @@ -1418,7 +1418,7 @@ class LibvirtDriver(driver.ComputeDriver): # NOTE(xqueralt): libvirt needs o+x in the temp directory os.chmod(tmpdir, 0o701) self._live_snapshot(context, instance, virt_dom, disk_path, - out_path, image_format, base) + out_path, image_format, image_meta) else: snapshot_backend.snapshot_extract(out_path, image_format) finally: @@ -2138,17 +2138,6 @@ class LibvirtDriver(driver.ComputeDriver): # Convert the system metadata to image metadata image_meta = utils.get_image_from_system_metadata( instance.system_metadata) - # NOTE(stpierre): In certain cases -- e.g., when booting a - # guest to restore its state after restarting - # Nova compute -- the context is not - # populated, which causes this (and - # _create_images_and_backing below) to error. - if not image_meta and context.auth_token is not None: - image_ref = instance.get('image_ref') - image_meta = compute_utils.get_image_metadata(context, - self._image_api, - image_ref, - instance) instance_dir = libvirt_utils.get_instance_path(instance) fileutils.ensure_tree(instance_dir) @@ -2326,8 +2315,8 @@ class LibvirtDriver(driver.ComputeDriver): def resume(self, context, instance, network_info, block_device_info=None): """resume the specified instance.""" - image_meta = compute_utils.get_image_metadata(context, - self._image_api, instance.image_ref, instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) disk_info = blockinfo.get_disk_info( CONF.libvirt.virt_type, instance, image_meta, @@ -3043,12 +3032,6 @@ class LibvirtDriver(driver.ComputeDriver): {'dev': pci_devs, 'dom': dom.ID()}) raise - def _prepare_args_for_get_config(self, context, instance): - image_ref = instance.image_ref - image_meta = compute_utils.get_image_metadata( - context, self._image_api, image_ref, instance) - return instance.flavor, image_meta - @staticmethod def _has_sriov_port(network_info): for vif in network_info: @@ -3067,14 +3050,14 @@ class LibvirtDriver(driver.ComputeDriver): return if self._has_sriov_port(network_info): - flavor, image_meta = self._prepare_args_for_get_config(context, - instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) for vif in network_info: if vif['vnic_type'] == network_model.VNIC_TYPE_DIRECT: cfg = self.vif_driver.get_config(instance, vif, image_meta, - flavor, + instance.flavor, CONF.libvirt.virt_type) LOG.debug('Attaching SR-IOV port %(port)s to %(dom)s', {'port': vif, 'dom': dom.ID()}) @@ -3096,14 +3079,14 @@ class LibvirtDriver(driver.ComputeDriver): raise exception.PciDeviceDetachFailed(reason=reason, dev=network_info) - flavor, image_meta = self._prepare_args_for_get_config(context, - instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) for vif in network_info: if vif['vnic_type'] == network_model.VNIC_TYPE_DIRECT: cfg = self.vif_driver.get_config(instance, vif, image_meta, - flavor, + instance.flavor, CONF.libvirt.virt_type) dom.detachDeviceFlags(cfg.to_xml(), libvirt.VIR_DOMAIN_AFFECT_LIVE) @@ -6575,11 +6558,8 @@ class LibvirtDriver(driver.ComputeDriver): self._cleanup_failed_migration(inst_base) utils.execute('mv', inst_base_resize, inst_base) - image_ref = instance.get('image_ref') - image_meta = compute_utils.get_image_metadata(context, - self._image_api, - image_ref, - instance) + image_meta = utils.get_image_from_system_metadata( + instance.system_metadata) disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type, instance,