Add power_on kwarg to ComputeDriver.spawn() method
For a cross-cell resize, the equivalent of the "finish_resize" method on the destination compute is going to call the driver spawn() method rather than the finish_migration() method and needs to pass through the power_on value, similar to finish_migration, so that when resizing a stopped server it remains stopped once it is resized. The finish_migration method in the driver behaves very similar to spawn so the semantics are the same. This change updates the spawn method signature for all in-tree compute drivers but only implements the logic for the libvirt driver as that is the only driver (currently) which supports cross-cell resize (note the can_connect_volume method is also necessary for cross-cell resize implementation in the driver). Part of blueprint cross-cell-resize Change-Id: I6929c588dd2e0e805f2e30b2e30d29967469d756
This commit is contained in:
parent
f7e7a07bdd
commit
a958dc5fcc
|
@ -12857,7 +12857,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||
mock_stat.assert_called_once_with(path)
|
||||
mock_get_size.assert_called_once_with(path)
|
||||
|
||||
def test_spawn_with_network_info(self):
|
||||
def test_spawn_with_network_info(self, power_on=True):
|
||||
def fake_getLibVersion():
|
||||
return fakelibvirt.FAKE_LIBVIRT_VERSION
|
||||
|
||||
|
@ -12918,19 +12918,29 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||
):
|
||||
self.flags(instances_path=tmpdir)
|
||||
|
||||
hw_running = hardware.InstanceInfo(state=power_state.RUNNING)
|
||||
mock_get_info.return_value = hw_running
|
||||
if power_on:
|
||||
hw_running = hardware.InstanceInfo(state=power_state.RUNNING)
|
||||
mock_get_info.return_value = hw_running
|
||||
else:
|
||||
# Avoid a test timeout since _wait_for_boot is threaded.
|
||||
mock_get_info.side_effect = Exception('do not call get_info')
|
||||
mock_build_device_metadata.return_value = None
|
||||
|
||||
del mock_orig_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
|
||||
|
||||
drvr.spawn(self.context, instance, image_meta, [], 'herp', {},
|
||||
network_info=network_info)
|
||||
network_info=network_info, power_on=power_on)
|
||||
|
||||
mock_get_info.assert_called_once_with(instance)
|
||||
if power_on:
|
||||
mock_get_info.assert_called_once_with(instance)
|
||||
else:
|
||||
mock_get_info.assert_not_called()
|
||||
mock_build_device_metadata.assert_called_once_with(self.context,
|
||||
instance)
|
||||
|
||||
def test_spawn_power_on_false(self):
|
||||
self.test_spawn_with_network_info(power_on=False)
|
||||
|
||||
# Methods called directly by spawn()
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_guest_xml')
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||
|
|
|
@ -342,11 +342,12 @@ class ComputeDriver(object):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
"""Create a new instance/VM/domain on the virtualization platform.
|
||||
|
||||
Once this successfully completes, the instance should be
|
||||
running (power_state.RUNNING).
|
||||
running (power_state.RUNNING) if ``power_on`` is True, else the
|
||||
instance should be stopped (power_state.SHUTDOWN).
|
||||
|
||||
If this fails, any partial instance should be completely
|
||||
cleaned up, and the virtualization platform should be in the state
|
||||
|
@ -366,6 +367,8 @@ class ComputeDriver(object):
|
|||
:param network_info: instance network information
|
||||
:param block_device_info: Information about block devices to be
|
||||
attached to the instance.
|
||||
:param power_on: True if the instance should be powered on, False
|
||||
otherwise
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ class FakeDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
|
||||
if network_info:
|
||||
for vif in network_info:
|
||||
|
@ -191,7 +191,7 @@ class FakeDriver(driver.ComputeDriver):
|
|||
self._interfaces[vif['id']] = vif
|
||||
|
||||
uuid = instance.uuid
|
||||
state = power_state.RUNNING
|
||||
state = power_state.RUNNING if power_on else power_state.SHUTDOWN
|
||||
flavor = instance.flavor
|
||||
self.resources.claim(
|
||||
vcpus=flavor.vcpus,
|
||||
|
@ -593,7 +593,7 @@ class FakeDriver(driver.ComputeDriver):
|
|||
# claim resources and track the instance on this "hypervisor".
|
||||
self.spawn(context, instance, image_meta, injected_files,
|
||||
admin_password, allocations,
|
||||
block_device_info=block_device_info)
|
||||
block_device_info=block_device_info, power_on=power_on)
|
||||
|
||||
def confirm_migration(self, context, migration, instance, network_info):
|
||||
# Confirm migration cleans up the guest from the source host so just
|
||||
|
@ -764,7 +764,7 @@ class FakeRescheduleDriver(FakeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
if not self.rescheduled.get(instance.uuid, False):
|
||||
# We only reschedule on the first time something hits spawn().
|
||||
self.rescheduled[instance.uuid] = True
|
||||
|
@ -772,7 +772,8 @@ class FakeRescheduleDriver(FakeDriver):
|
|||
reason='FakeRescheduleDriver')
|
||||
super(FakeRescheduleDriver, self).spawn(
|
||||
context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info, block_device_info)
|
||||
admin_password, allocations, network_info, block_device_info,
|
||||
power_on)
|
||||
|
||||
|
||||
class FakeRescheduleDriverWithNestedCustomResources(
|
||||
|
@ -786,7 +787,7 @@ class FakeBuildAbortDriver(FakeDriver):
|
|||
"""
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
raise exception.BuildAbortException(
|
||||
instance_uuid=instance.uuid, reason='FakeBuildAbortDriver')
|
||||
|
||||
|
@ -802,14 +803,15 @@ class FakeUnshelveSpawnFailDriver(FakeDriver):
|
|||
"""
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
if instance.vm_state == vm_states.SHELVED_OFFLOADED:
|
||||
raise exception.VirtualInterfaceCreateException(
|
||||
'FakeUnshelveSpawnFailDriver')
|
||||
# Otherwise spawn normally during the initial build.
|
||||
super(FakeUnshelveSpawnFailDriver, self).spawn(
|
||||
context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info, block_device_info)
|
||||
admin_password, allocations, network_info, block_device_info,
|
||||
power_on)
|
||||
|
||||
|
||||
class FakeUnshelveSpawnFailDriverWithNestedCustomResources(
|
||||
|
|
|
@ -159,7 +159,7 @@ class HyperVDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
self._vmops.spawn(context, instance, image_meta, injected_files,
|
||||
admin_password, network_info, block_device_info)
|
||||
|
||||
|
|
|
@ -1112,7 +1112,7 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
"""Deploy an instance.
|
||||
|
||||
:param context: The security context.
|
||||
|
@ -1129,6 +1129,8 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||
:param network_info: Instance network information.
|
||||
:param block_device_info: Instance block device
|
||||
information.
|
||||
:param power_on: True if the instance should be powered on, False
|
||||
otherwise
|
||||
"""
|
||||
LOG.debug('Spawn called for instance', instance=instance)
|
||||
|
||||
|
|
|
@ -3199,7 +3199,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
|
||||
instance,
|
||||
image_meta,
|
||||
|
@ -3228,7 +3228,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
context, xml, instance, network_info,
|
||||
block_device_info=block_device_info,
|
||||
post_xml_callback=gen_confdrive,
|
||||
destroy_disks_on_failure=True)
|
||||
destroy_disks_on_failure=True,
|
||||
power_on=power_on)
|
||||
LOG.debug("Guest created on hypervisor", instance=instance)
|
||||
|
||||
def _wait_for_boot():
|
||||
|
@ -3239,8 +3240,11 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
LOG.info("Instance spawned successfully.", instance=instance)
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
timer = loopingcall.FixedIntervalLoopingCall(_wait_for_boot)
|
||||
timer.start(interval=0.5).wait()
|
||||
if power_on:
|
||||
timer = loopingcall.FixedIntervalLoopingCall(_wait_for_boot)
|
||||
timer.start(interval=0.5).wait()
|
||||
else:
|
||||
LOG.info("Instance spawned successfully.", instance=instance)
|
||||
|
||||
def _get_console_output_file(self, instance, console_log):
|
||||
bytes_to_read = MAX_CONSOLE_BYTES
|
||||
|
|
|
@ -240,7 +240,7 @@ class PowerVMDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
"""Create a new instance/VM/domain on the virtualization platform.
|
||||
|
||||
Once this successfully completes, the instance should be
|
||||
|
@ -264,6 +264,8 @@ class PowerVMDriver(driver.ComputeDriver):
|
|||
:param network_info: instance network information
|
||||
:param block_device_info: Information about block devices to be
|
||||
attached to the instance.
|
||||
:param power_on: True if the instance should be powered on, False
|
||||
otherwise
|
||||
"""
|
||||
self._log_operation('spawn', instance)
|
||||
# Define the flow
|
||||
|
|
|
@ -537,7 +537,7 @@ class VMwareVCDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
"""Create VM instance."""
|
||||
self._vmops.spawn(context, instance, image_meta, injected_files,
|
||||
admin_password, network_info, block_device_info)
|
||||
|
|
|
@ -212,7 +212,7 @@ class XenAPIDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
"""Create VM instance."""
|
||||
vgpu_info = self._get_vgpu_info(allocations)
|
||||
self._vmops.spawn(context, instance, image_meta, injected_files,
|
||||
|
|
|
@ -141,7 +141,7 @@ class ZVMDriver(driver.ComputeDriver):
|
|||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None):
|
||||
block_device_info=None, power_on=True):
|
||||
|
||||
LOG.info("Spawning new instance %s on zVM hypervisor",
|
||||
instance.name, instance=instance)
|
||||
|
|
Loading…
Reference in New Issue