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:
parent
c12a78b35d
commit
c7d77624b7
|
@ -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')
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue