Compute: update config drive settings on instance

In the case the config drive setting are overridden by either
image properties or the configuration setting then these are updated
on the instance to actually reflect the running VM configuration.

The patch creates a common method for updating instance details
after spawn.

Change-Id: Ia5e36989a7b7543fa77c7c196919f8566e02d28a
Closes-bug: #1403889
This commit is contained in:
Gary Kotton 2015-02-16 03:07:50 -08:00
parent c12a78b35d
commit c7d77624b7
3 changed files with 47 additions and 16 deletions

View File

@ -85,6 +85,7 @@ from nova import safe_utils
from nova.scheduler import rpcapi as scheduler_rpcapi
from nova import utils
from nova.virt import block_device as driver_block_device
from nova.virt import configdrive
from nova.virt import driver
from nova.virt import event as virtevent
from nova.virt import storage_users
@ -1874,6 +1875,13 @@ class ComputeManager(manager.Manager):
instance=instance)
raise exception.InvalidBDM()
def _update_instance_after_spawn(self, context, instance):
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.ACTIVE
instance.task_state = None
instance.launched_at = timeutils.utcnow()
configdrive.update_instance(instance)
@object_compat
def _spawn(self, context, instance, image_meta, network_info,
block_device_info, injected_files, admin_password,
@ -1893,10 +1901,7 @@ class ComputeManager(manager.Manager):
LOG.exception(_LE('Instance failed to spawn'),
instance=instance)
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.ACTIVE
instance.task_state = None
instance.launched_at = timeutils.utcnow()
self._update_instance_after_spawn(context, instance)
def _set_access_ip_values():
"""Add access ip values for a given instance.
@ -2221,10 +2226,7 @@ class ComputeManager(manager.Manager):
# NOTE(alaski): This is only useful during reschedules, remove it now.
instance.system_metadata.pop('network_allocated', None)
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.ACTIVE
instance.task_state = None
instance.launched_at = timeutils.utcnow()
self._update_instance_after_spawn(context, instance)
try:
instance.save(expected_task_state=task_states.SPAWNING)
@ -2882,10 +2884,7 @@ class ComputeManager(manager.Manager):
# NOTE(rpodolyaka): driver doesn't provide specialized version
# of rebuild, fall back to the default implementation
self._rebuild_default_impl(**kwargs)
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.ACTIVE
instance.task_state = None
instance.launched_at = timeutils.utcnow()
self._update_instance_after_spawn(context, instance)
instance.save(expected_task_state=[task_states.REBUILD_SPAWNING])
if orig_vm_state == vm_states.STOPPED:
@ -4340,10 +4339,7 @@ class ComputeManager(manager.Manager):
self.image_api.delete(context, image['id'])
self._unshelve_instance_key_restore(instance, scrubbed_keys)
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.ACTIVE
instance.task_state = None
instance.launched_at = timeutils.utcnow()
self._update_instance_after_spawn(context, instance)
instance.save(expected_task_state=task_states.SPAWNING)
self._notify_about_instance_usage(context, instance, 'unshelve.end')

View File

@ -17,6 +17,7 @@
import os
import tempfile
import mock
from mox3 import mox
from oslo_config import cfg
@ -102,3 +103,26 @@ class ConfigDriveTestCase(test.NoDBTestCase):
inst.system_metadata = {
utils.SM_IMAGE_PROP_PREFIX + 'img_config_drive': 'optional'}
self.assertFalse(configdrive.required_by(inst))
@mock.patch.object(configdrive, 'required_by', return_value=False)
def test_config_drive_update_instance_required_by_false(self,
mock_required):
inst = fake_instance.fake_instance_obj(context.get_admin_context())
inst.config_drive = ''
configdrive.update_instance(inst)
self.assertEqual('', inst.config_drive)
inst.config_drive = True
configdrive.update_instance(inst)
self.assertTrue(inst.config_drive)
@mock.patch.object(configdrive, 'required_by', return_value=True)
def test_config_drive_update_instance(self, mock_required):
inst = fake_instance.fake_instance_obj(context.get_admin_context())
inst.config_drive = ''
configdrive.update_instance(inst)
self.assertTrue(inst.config_drive)
inst.config_drive = True
configdrive.update_instance(inst)
self.assertTrue(inst.config_drive)

View File

@ -190,3 +190,14 @@ def required_by(instance):
strutils.bool_from_string(CONF.force_config_drive) or
image_prop == 'mandatory'
)
def update_instance(instance):
"""Update the instance config_drive setting if necessary
The image or configuration file settings may override the default instance
setting. In this case the instance needs to mirror the actual
virtual machine configuration.
"""
if not instance.config_drive and required_by(instance):
instance.config_drive = True