compute: remove get_image_metadata method

The get_image_metadata method has some unhelpful semantics
where it takes the image metadata from the instance's
system metadata record, and then overwrites it with the
current metadata associated with the original image.

The result is that, if the image metadata in glance was
changed after the instance was first booted, Nova will
end up making decisions based on image metadata that does
not correspond to that which the instance was booted with.
Since the image metadata controls many aspects of hardware
configuration, this could lead to incorrect behaviour when
modifying hardware later, eg disk/vif/pci hotplug.

What is worse, is that some of the nova operations will
update the instance system metadata when completed, thus
permanently overwriting the original image metadata with
the new data.

Almost all code which operates against an existing instance
is updated to use nova.utils.get_image_from_system_metadata.
The exception is the rescue codepath, which must use the
metadata associated with the new rescue image.

The nova.compute.utils.get_image_metadata method can thus
be removed from use, avoiding the problematic logic.

Closes-bug: #1460079
Change-Id: I35c9d26e3967e93a2c368c3f9fdc807a69816dd2
This commit is contained in:
Daniel P. Berrange 2015-06-01 16:18:30 +01:00
parent 9fc47e6346
commit 77ecc3d8c5
12 changed files with 150 additions and 354 deletions

View File

@ -2167,9 +2167,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", {})

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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])

View File

@ -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, [], [])

View File

@ -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(

View File

@ -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):

View File

@ -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(

View File

@ -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),

View File

@ -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
@ -8339,7 +8338,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,
@ -8352,13 +8352,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,
@ -8373,14 +8374,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,
@ -8396,8 +8398,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):
@ -8423,7 +8425,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,
@ -11909,7 +11911,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)
@ -11942,6 +11944,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')
@ -11955,7 +11958,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:
@ -11967,7 +11970,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)
@ -11995,7 +11998,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)):
@ -12729,14 +12732,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 = """
<domain type="qemu">
@ -13724,6 +13719,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')

View File

@ -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,