Update driver interface

spawn() now accepts the "power_on" flag, allowing instances to be
created without being turned on. This is part of the cross-cell
migration workflow.

Change-Id: Ifd18a69f476ebbfb4ee6ec34abb03da0d2e30ceb
This commit is contained in:
Lucian Petrut 2019-09-03 13:10:26 +03:00
parent 20ee0665c5
commit cb203978f2
6 changed files with 39 additions and 25 deletions

View File

@ -41,10 +41,10 @@ class HyperVClusterDriver(driver.HyperVDriver):
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):
super(HyperVClusterDriver, self).spawn(
context, instance, image_meta, injected_files, admin_password,
allocations, network_info, block_device_info)
allocations, network_info, block_device_info, power_on)
self._clops.add_to_cluster(instance)
def destroy(self, context, instance, network_info, block_device_info=None,

View File

@ -183,10 +183,11 @@ 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):
image_meta = self._recreate_image_meta(context, instance, image_meta)
self._vmops.spawn(context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info)
admin_password, network_info, block_device_info,
power_on)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):

View File

@ -287,7 +287,8 @@ class VMOps(object):
@check_admin_permissions
def spawn(self, context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info=None):
admin_password, network_info, block_device_info=None,
power_on=True):
"""Create a new VM and start it."""
LOG.info("Spawning new instance", instance=instance)
@ -331,9 +332,10 @@ class VMOps(object):
# vifs are already plugged in at this point. We waited on the vif
# plug event previously when we created the instance. Skip the
# plug vifs during power on in this case
self.power_on(instance,
network_info=network_info,
should_plug_vifs=False)
if power_on:
self.power_on(instance,
network_info=network_info,
should_plug_vifs=False)
except Exception:
with excutils.save_and_reraise_exception():
self.destroy(instance, network_info, block_device_info)

View File

@ -74,13 +74,15 @@ class HyperVClusterTestCase(test_base.HyperVBaseTestCase):
mock.sentinel.admin_pass,
mock.sentinel.allocations,
mock.sentinel.network_info,
mock.sentinel.block_dev_info)
mock.sentinel.block_dev_info,
mock.sentinel.power_on)
mock_superclass_spawn.assert_called_once_with(
self.context, mock.sentinel.fake_instance,
mock.sentinel.image_meta, mock.sentinel.injected_files,
mock.sentinel.admin_pass, mock.sentinel.allocations,
mock.sentinel.network_info, mock.sentinel.block_dev_info)
mock.sentinel.network_info, mock.sentinel.block_dev_info,
mock.sentinel.power_on)
self.driver._clops.add_to_cluster.assert_called_once_with(
mock.sentinel.fake_instance)

View File

@ -158,7 +158,8 @@ class HyperVDriverTestCase(test_base.HyperVBaseTestCase):
mock.sentinel.image_meta, mock.sentinel.injected_files,
mock.sentinel.admin_password, mock.sentinel.allocations,
mock.sentinel.network_info,
mock.sentinel.block_device_info)
mock.sentinel.block_device_info,
mock.sentinel.power_on)
mock_recreate_img_meta.assert_called_once_with(
mock.sentinel.context, mock.sentinel.instance,
@ -167,7 +168,8 @@ class HyperVDriverTestCase(test_base.HyperVBaseTestCase):
mock.sentinel.context, mock.sentinel.instance,
mock_recreate_img_meta.return_value, mock.sentinel.injected_files,
mock.sentinel.admin_password, mock.sentinel.network_info,
mock.sentinel.block_device_info)
mock.sentinel.block_device_info,
mock.sentinel.power_on)
def test_reboot(self):
self.driver.reboot(

View File

@ -486,8 +486,9 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
mock_create_config_drive, mock_attach_config_drive,
mock_set_boot_order,
mock_power_on, mock_destroy, mock_plug_vifs,
exists, configdrive_required, fail,
fake_vm_gen=constants.VM_GEN_2):
exists=False, configdrive_required=True, fail=None,
fake_vm_gen=constants.VM_GEN_2,
power_on=True):
mock_instance = fake_instance.fake_instance_obj(self.context)
mock_image_meta = mock.MagicMock()
root_device_info = mock.sentinel.ROOT_DEV_INFO
@ -516,7 +517,8 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
else:
self._vmops.spawn(self.context, mock_instance, mock_image_meta,
[mock.sentinel.FILE], mock.sentinel.PASSWORD,
mock.sentinel.network_info, block_device_info)
mock.sentinel.network_info, block_device_info,
power_on=power_on)
self._vmops._vmutils.vm_exists.assert_called_once_with(
mock_instance.name)
self._vmops._pathutils.get_instance_dir.assert_called_once_with(
@ -552,23 +554,28 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
mock_instance, fake_config_drive_path, fake_vm_gen)
mock_set_boot_order.assert_called_once_with(
mock_instance.name, fake_vm_gen, block_device_info)
mock_power_on.assert_called_once_with(
mock_instance,
network_info=mock.sentinel.network_info,
should_plug_vifs=False)
if power_on:
mock_power_on.assert_called_once_with(
mock_instance,
network_info=mock.sentinel.network_info,
should_plug_vifs=False)
else:
mock_power_on.assert_not_called()
def test_spawn(self):
self._test_spawn(exists=False, configdrive_required=True, fail=None)
self._test_spawn()
def test_spawn_instance_exists(self):
self._test_spawn(exists=True, configdrive_required=True, fail=None)
self._test_spawn(exists=True)
def test_spawn_create_instance_exception(self):
self._test_spawn(exists=False, configdrive_required=True,
fail=os_win_exc.HyperVException)
self._test_spawn(fail=os_win_exc.HyperVException)
def test_spawn_not_required(self):
self._test_spawn(exists=False, configdrive_required=False, fail=None)
def test_spawn_cfgdrive_not_required(self):
self._test_spawn(configdrive_required=False)
def test_spawn_without_powering_on(self):
self._test_spawn(power_on=False)
def test_spawn_no_admin_permissions(self):
self._vmops._vmutils.check_admin_permissions.side_effect = (