Skip to content

Commit a958dc5

Browse files
committed
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
1 parent f7e7a07 commit a958dc5

File tree

10 files changed

+48
-25
lines changed

10 files changed

+48
-25
lines changed

nova/tests/unit/virt/libvirt/test_driver.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12857,7 +12857,7 @@ def fake_lookup(_uuid):
1285712857
mock_stat.assert_called_once_with(path)
1285812858
mock_get_size.assert_called_once_with(path)
1285912859

12860-
def test_spawn_with_network_info(self):
12860+
def test_spawn_with_network_info(self, power_on=True):
1286112861
def fake_getLibVersion():
1286212862
return fakelibvirt.FAKE_LIBVIRT_VERSION
1286312863

@@ -12918,19 +12918,29 @@ def fake_baselineCPU(cpu, flag):
1291812918
):
1291912919
self.flags(instances_path=tmpdir)
1292012920

12921-
hw_running = hardware.InstanceInfo(state=power_state.RUNNING)
12922-
mock_get_info.return_value = hw_running
12921+
if power_on:
12922+
hw_running = hardware.InstanceInfo(state=power_state.RUNNING)
12923+
mock_get_info.return_value = hw_running
12924+
else:
12925+
# Avoid a test timeout since _wait_for_boot is threaded.
12926+
mock_get_info.side_effect = Exception('do not call get_info')
1292312927
mock_build_device_metadata.return_value = None
1292412928

1292512929
del mock_orig_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
1292612930

1292712931
drvr.spawn(self.context, instance, image_meta, [], 'herp', {},
12928-
network_info=network_info)
12932+
network_info=network_info, power_on=power_on)
1292912933

12930-
mock_get_info.assert_called_once_with(instance)
12934+
if power_on:
12935+
mock_get_info.assert_called_once_with(instance)
12936+
else:
12937+
mock_get_info.assert_not_called()
1293112938
mock_build_device_metadata.assert_called_once_with(self.context,
1293212939
instance)
1293312940

12941+
def test_spawn_power_on_false(self):
12942+
self.test_spawn_with_network_info(power_on=False)
12943+
1293412944
# Methods called directly by spawn()
1293512945
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_guest_xml')
1293612946
@mock.patch.object(libvirt_driver.LibvirtDriver,

nova/virt/driver.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,12 @@ def failed_spawn_cleanup(self, instance):
342342

343343
def spawn(self, context, instance, image_meta, injected_files,
344344
admin_password, allocations, network_info=None,
345-
block_device_info=None):
345+
block_device_info=None, power_on=True):
346346
"""Create a new instance/VM/domain on the virtualization platform.
347347
348348
Once this successfully completes, the instance should be
349-
running (power_state.RUNNING).
349+
running (power_state.RUNNING) if ``power_on`` is True, else the
350+
instance should be stopped (power_state.SHUTDOWN).
350351
351352
If this fails, any partial instance should be completely
352353
cleaned up, and the virtualization platform should be in the state
@@ -366,6 +367,8 @@ def spawn(self, context, instance, image_meta, injected_files,
366367
:param network_info: instance network information
367368
:param block_device_info: Information about block devices to be
368369
attached to the instance.
370+
:param power_on: True if the instance should be powered on, False
371+
otherwise
369372
"""
370373
raise NotImplementedError()
371374

nova/virt/fake.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def unplug_vifs(self, instance, network_info):
179179

180180
def spawn(self, context, instance, image_meta, injected_files,
181181
admin_password, allocations, network_info=None,
182-
block_device_info=None):
182+
block_device_info=None, power_on=True):
183183

184184
if network_info:
185185
for vif in network_info:
@@ -191,7 +191,7 @@ def spawn(self, context, instance, image_meta, injected_files,
191191
self._interfaces[vif['id']] = vif
192192

193193
uuid = instance.uuid
194-
state = power_state.RUNNING
194+
state = power_state.RUNNING if power_on else power_state.SHUTDOWN
195195
flavor = instance.flavor
196196
self.resources.claim(
197197
vcpus=flavor.vcpus,
@@ -593,7 +593,7 @@ def finish_migration(self, context, migration, instance, disk_info,
593593
# claim resources and track the instance on this "hypervisor".
594594
self.spawn(context, instance, image_meta, injected_files,
595595
admin_password, allocations,
596-
block_device_info=block_device_info)
596+
block_device_info=block_device_info, power_on=power_on)
597597

598598
def confirm_migration(self, context, migration, instance, network_info):
599599
# Confirm migration cleans up the guest from the source host so just
@@ -764,15 +764,16 @@ class FakeRescheduleDriver(FakeDriver):
764764

765765
def spawn(self, context, instance, image_meta, injected_files,
766766
admin_password, allocations, network_info=None,
767-
block_device_info=None):
767+
block_device_info=None, power_on=True):
768768
if not self.rescheduled.get(instance.uuid, False):
769769
# We only reschedule on the first time something hits spawn().
770770
self.rescheduled[instance.uuid] = True
771771
raise exception.ComputeResourcesUnavailable(
772772
reason='FakeRescheduleDriver')
773773
super(FakeRescheduleDriver, self).spawn(
774774
context, instance, image_meta, injected_files,
775-
admin_password, allocations, network_info, block_device_info)
775+
admin_password, allocations, network_info, block_device_info,
776+
power_on)
776777

777778

778779
class FakeRescheduleDriverWithNestedCustomResources(
@@ -786,7 +787,7 @@ class FakeBuildAbortDriver(FakeDriver):
786787
"""
787788
def spawn(self, context, instance, image_meta, injected_files,
788789
admin_password, allocations, network_info=None,
789-
block_device_info=None):
790+
block_device_info=None, power_on=True):
790791
raise exception.BuildAbortException(
791792
instance_uuid=instance.uuid, reason='FakeBuildAbortDriver')
792793

@@ -802,14 +803,15 @@ class FakeUnshelveSpawnFailDriver(FakeDriver):
802803
"""
803804
def spawn(self, context, instance, image_meta, injected_files,
804805
admin_password, allocations, network_info=None,
805-
block_device_info=None):
806+
block_device_info=None, power_on=True):
806807
if instance.vm_state == vm_states.SHELVED_OFFLOADED:
807808
raise exception.VirtualInterfaceCreateException(
808809
'FakeUnshelveSpawnFailDriver')
809810
# Otherwise spawn normally during the initial build.
810811
super(FakeUnshelveSpawnFailDriver, self).spawn(
811812
context, instance, image_meta, injected_files,
812-
admin_password, allocations, network_info, block_device_info)
813+
admin_password, allocations, network_info, block_device_info,
814+
power_on)
813815

814816

815817
class FakeUnshelveSpawnFailDriverWithNestedCustomResources(

nova/virt/hyperv/driver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def list_instances(self):
159159

160160
def spawn(self, context, instance, image_meta, injected_files,
161161
admin_password, allocations, network_info=None,
162-
block_device_info=None):
162+
block_device_info=None, power_on=True):
163163
self._vmops.spawn(context, instance, image_meta, injected_files,
164164
admin_password, network_info, block_device_info)
165165

nova/virt/ironic/driver.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ def _generate_configdrive(self, context, instance, node, network_info,
11121112

11131113
def spawn(self, context, instance, image_meta, injected_files,
11141114
admin_password, allocations, network_info=None,
1115-
block_device_info=None):
1115+
block_device_info=None, power_on=True):
11161116
"""Deploy an instance.
11171117
11181118
:param context: The security context.
@@ -1129,6 +1129,8 @@ def spawn(self, context, instance, image_meta, injected_files,
11291129
:param network_info: Instance network information.
11301130
:param block_device_info: Instance block device
11311131
information.
1132+
:param power_on: True if the instance should be powered on, False
1133+
otherwise
11321134
"""
11331135
LOG.debug('Spawn called for instance', instance=instance)
11341136

nova/virt/libvirt/driver.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3199,7 +3199,7 @@ def poll_rebooting_instances(self, timeout, instances):
31993199

32003200
def spawn(self, context, instance, image_meta, injected_files,
32013201
admin_password, allocations, network_info=None,
3202-
block_device_info=None):
3202+
block_device_info=None, power_on=True):
32033203
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
32043204
instance,
32053205
image_meta,
@@ -3228,7 +3228,8 @@ def spawn(self, context, instance, image_meta, injected_files,
32283228
context, xml, instance, network_info,
32293229
block_device_info=block_device_info,
32303230
post_xml_callback=gen_confdrive,
3231-
destroy_disks_on_failure=True)
3231+
destroy_disks_on_failure=True,
3232+
power_on=power_on)
32323233
LOG.debug("Guest created on hypervisor", instance=instance)
32333234

32343235
def _wait_for_boot():
@@ -3239,8 +3240,11 @@ def _wait_for_boot():
32393240
LOG.info("Instance spawned successfully.", instance=instance)
32403241
raise loopingcall.LoopingCallDone()
32413242

3242-
timer = loopingcall.FixedIntervalLoopingCall(_wait_for_boot)
3243-
timer.start(interval=0.5).wait()
3243+
if power_on:
3244+
timer = loopingcall.FixedIntervalLoopingCall(_wait_for_boot)
3245+
timer.start(interval=0.5).wait()
3246+
else:
3247+
LOG.info("Instance spawned successfully.", instance=instance)
32443248

32453249
def _get_console_output_file(self, instance, console_log):
32463250
bytes_to_read = MAX_CONSOLE_BYTES

nova/virt/powervm/driver.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def update_provider_tree(self, provider_tree, nodename, allocations=None):
240240

241241
def spawn(self, context, instance, image_meta, injected_files,
242242
admin_password, allocations, network_info=None,
243-
block_device_info=None):
243+
block_device_info=None, power_on=True):
244244
"""Create a new instance/VM/domain on the virtualization platform.
245245
246246
Once this successfully completes, the instance should be
@@ -264,6 +264,8 @@ def spawn(self, context, instance, image_meta, injected_files,
264264
:param network_info: instance network information
265265
:param block_device_info: Information about block devices to be
266266
attached to the instance.
267+
:param power_on: True if the instance should be powered on, False
268+
otherwise
267269
"""
268270
self._log_operation('spawn', instance)
269271
# Define the flow

nova/virt/vmwareapi/driver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ def update_provider_tree(self, provider_tree, nodename, allocations=None):
537537

538538
def spawn(self, context, instance, image_meta, injected_files,
539539
admin_password, allocations, network_info=None,
540-
block_device_info=None):
540+
block_device_info=None, power_on=True):
541541
"""Create VM instance."""
542542
self._vmops.spawn(context, instance, image_meta, injected_files,
543543
admin_password, network_info, block_device_info)

nova/virt/xenapi/driver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def _get_vgpu_info(self, allocations):
212212

213213
def spawn(self, context, instance, image_meta, injected_files,
214214
admin_password, allocations, network_info=None,
215-
block_device_info=None):
215+
block_device_info=None, power_on=True):
216216
"""Create VM instance."""
217217
vgpu_info = self._get_vgpu_info(allocations)
218218
self._vmops.spawn(context, instance, image_meta, injected_files,

nova/virt/zvm/driver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def get_info(self, instance, use_cache=True):
141141

142142
def spawn(self, context, instance, image_meta, injected_files,
143143
admin_password, allocations, network_info=None,
144-
block_device_info=None):
144+
block_device_info=None, power_on=True):
145145

146146
LOG.info("Spawning new instance %s on zVM hypervisor",
147147
instance.name, instance=instance)

0 commit comments

Comments
 (0)