diff options
author | Brent Eagles <beagles@redhat.com> | 2013-06-06 15:33:42 -0230 |
---|---|---|
committer | Brent Eagles <beagles@redhat.com> | 2013-06-25 15:43:27 -0230 |
commit | db3989586a8d5bbbcf857b9294a124ecc5fc57e8 (patch) | |
tree | ca857e6ef4dbd6074a54259b6e94543e29e88372 | |
parent | 9331c5c1115c7d8cc5bcab71b1100eeea1ce72fe (diff) | |
download | nova-db3989586a8d5bbbcf857b9294a124ecc5fc57e8.tar.gz nova-db3989586a8d5bbbcf857b9294a124ecc5fc57e8.tar.xz nova-db3989586a8d5bbbcf857b9294a124ecc5fc57e8.zip |
Refresh volume connections when starting instances
This patches adds network and block device information to the signature
of the power_on method on the virtualization driver. The relevant call
sites are also modified to provide the required information. The libvirt
implementation of power_on has been altered to re-establish network and
volume related connections.
Fixes bug: 1188326
Change-Id: If617b570e082e3aa321414a2680a3aa0754f6153
-rwxr-xr-x | nova/compute/manager.py | 16 | ||||
-rw-r--r-- | nova/tests/api/ec2/test_cloud.py | 3 | ||||
-rw-r--r-- | nova/tests/compute/test_compute.py | 3 | ||||
-rw-r--r-- | nova/tests/virt/hyperv/test_hypervapi.py | 21 | ||||
-rw-r--r-- | nova/tests/virt/test_virt_drivers.py | 24 | ||||
-rw-r--r-- | nova/tests/virt/vmwareapi/test_vmwareapi.py | 14 | ||||
-rwxr-xr-x | nova/virt/baremetal/driver.py | 6 | ||||
-rwxr-xr-x | nova/virt/driver.py | 3 | ||||
-rwxr-xr-x | nova/virt/fake.py | 2 | ||||
-rwxr-xr-x | nova/virt/hyperv/driver.py | 3 | ||||
-rwxr-xr-x | nova/virt/libvirt/driver.py | 12 | ||||
-rwxr-xr-x | nova/virt/powervm/driver.py | 3 | ||||
-rwxr-xr-x | nova/virt/vmwareapi/driver.py | 10 | ||||
-rw-r--r-- | nova/virt/vmwareapi/vmops.py | 16 | ||||
-rwxr-xr-x | nova/virt/xenapi/driver.py | 3 |
15 files changed, 100 insertions, 39 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 22881f5bd..a242a121d 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1540,7 +1540,14 @@ class ComputeManager(manager.SchedulerDependentManager): def start_instance(self, context, instance): """Starting an instance on this host.""" self._notify_about_instance_usage(context, instance, "power_on.start") - self.driver.power_on(instance) + + network_info = self._get_instance_nw_info(context, instance) + block_device_info = self._get_instance_volume_block_device_info( + context, instance) + self.driver.power_on(context, instance, + self._legacy_nw_info(network_info), + block_device_info) + current_power_state = self._get_power_state(context, instance) instance.power_state = current_power_state instance.vm_state = vm_states.ACTIVE @@ -1595,7 +1602,12 @@ class ComputeManager(manager.SchedulerDependentManager): except NotImplementedError: # Fallback to just powering on the instance if the hypervisor # doesn't implement the restore method - self.driver.power_on(instance) + network_info = self._get_instance_nw_info(context, instance) + block_device_info = self._get_instance_volume_block_device_info( + context, instance) + self.driver.power_on(context, instance, + self._legacy_nw_info(network_info), + block_device_info) current_power_state = self._get_power_state(context, instance) instance = self._instance_update(context, instance['uuid'], power_state=current_power_state, diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py index 22a6947f2..560474847 100644 --- a/nova/tests/api/ec2/test_cloud.py +++ b/nova/tests/api/ec2/test_cloud.py @@ -2137,7 +2137,8 @@ class CloudTestCase(test.TestCase): virt_driver = {} - def fake_power_on(self, instance): + def fake_power_on(self, context, instance, network_info, + block_device_info): virt_driver['powered_on'] = True self.stubs.Set(fake_virt.FakeDriver, 'power_on', fake_power_on) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 7953f8b63..ee3f1e28a 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -1427,7 +1427,8 @@ class ComputeTestCase(BaseTestCase): called = {'power_on': False} - def fake_driver_power_on(self, instance): + def fake_driver_power_on(self, context, instance, network_info, + block_device_info): called['power_on'] = True self.stubs.Set(nova.virt.fake.FakeDriver, 'power_on', diff --git a/nova/tests/virt/hyperv/test_hypervapi.py b/nova/tests/virt/hyperv/test_hypervapi.py index cfc79c388..9f2d745ff 100644 --- a/nova/tests/virt/hyperv/test_hypervapi.py +++ b/nova/tests/virt/hyperv/test_hypervapi.py @@ -495,13 +495,24 @@ class HyperVAPITestCase(test.TestCase): constants.HYPERV_VM_STATE_DISABLED) def test_power_on(self): - self._test_vm_state_change(self._conn.power_on, - constants.HYPERV_VM_STATE_DISABLED, - constants.HYPERV_VM_STATE_ENABLED) + self._instance_data = self._get_instance_data() + network_info = fake_network.fake_get_instance_nw_info(self.stubs, + spectacular=True) + vmutils.VMUtils.set_vm_state(mox.Func(self._check_instance_name), + constants.HYPERV_VM_STATE_ENABLED) + self._mox.ReplayAll() + self._conn.power_on(self._context, self._instance_data, network_info) + self._mox.VerifyAll() def test_power_on_already_running(self): - self._test_vm_state_change(self._conn.power_on, None, - constants.HYPERV_VM_STATE_ENABLED) + self._instance_data = self._get_instance_data() + network_info = fake_network.fake_get_instance_nw_info(self.stubs, + spectacular=True) + vmutils.VMUtils.set_vm_state(mox.Func(self._check_instance_name), + constants.HYPERV_VM_STATE_ENABLED) + self._mox.ReplayAll() + self._conn.power_on(self._context, self._instance_data, network_info) + self._mox.VerifyAll() def test_reboot(self): diff --git a/nova/tests/virt/test_virt_drivers.py b/nova/tests/virt/test_virt_drivers.py index 47f983258..5c2df9854 100644 --- a/nova/tests/virt/test_virt_drivers.py +++ b/nova/tests/virt/test_virt_drivers.py @@ -311,13 +311,14 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase): @catch_notimplementederror def test_power_on_running(self): instance_ref, network_info = self._get_running_instance() - self.connection.power_on(instance_ref) + self.connection.power_on(self.ctxt, instance_ref, + network_info, None) @catch_notimplementederror def test_power_on_powered_off(self): instance_ref, network_info = self._get_running_instance() self.connection.power_off(instance_ref) - self.connection.power_on(instance_ref) + self.connection.power_on(self.ctxt, instance_ref, network_info, None) @catch_notimplementederror def test_soft_delete(self): @@ -407,7 +408,24 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase): self.connection.attach_volume({'driver_volume_type': 'fake'}, instance_ref, '/dev/sda') - self.connection.power_on(instance_ref) + + bdm = { + 'root_device_name': None, + 'swap': None, + 'ephemerals': [], + 'block_device_mapping': [{ + 'instance_uuid': instance_ref['uuid'], + 'connection_info': {'driver_volume_type': 'fake'}, + 'mount_device': '/dev/sda', + 'delete_on_termination': False, + 'virtual_name': None, + 'snapshot_id': None, + 'volume_id': 'abcdedf', + 'volume_size': None, + 'no_device': None + }] + } + self.connection.power_on(self.ctxt, instance_ref, network_info, bdm) self.connection.detach_volume({'driver_volume_type': 'fake'}, instance_ref, '/dev/sda') diff --git a/nova/tests/virt/vmwareapi/test_vmwareapi.py b/nova/tests/virt/vmwareapi/test_vmwareapi.py index 5ba2f98af..62db10535 100644 --- a/nova/tests/virt/vmwareapi/test_vmwareapi.py +++ b/nova/tests/virt/vmwareapi/test_vmwareapi.py @@ -335,14 +335,14 @@ class VMwareAPIVMTestCase(test.TestCase): self.conn.power_off(self.instance) info = self.conn.get_info({'uuid': 'fake-uuid'}) self._check_vm_info(info, power_state.SHUTDOWN) - self.conn.power_on(self.instance) + self.conn.power_on(self.context, self.instance, self.network_info) info = self.conn.get_info({'uuid': 'fake-uuid'}) self._check_vm_info(info, power_state.RUNNING) def test_power_on_non_existent(self): self._create_instance_in_the_db() self.assertRaises(exception.InstanceNotFound, self.conn.power_on, - self.instance) + self.context, self.instance, self.network_info) def test_power_off(self): self._create_vm() @@ -427,7 +427,7 @@ class VMwareAPIVMTestCase(test.TestCase): self.assertEquals(4, step) self.assertEqual(vmops.RESIZE_TOTAL_STEPS, total_steps) - self.stubs.Set(self.conn._vmops, "power_on", fake_power_on) + self.stubs.Set(self.conn._vmops, "_power_on", fake_power_on) self.stubs.Set(self.conn._vmops, "_update_instance_progress", fake_vmops_update_instance_progress) @@ -439,6 +439,7 @@ class VMwareAPIVMTestCase(test.TestCase): instance=self.instance, disk_info=None, network_info=None, + block_device_info=None, image_meta=None, power_on=power_on) # verify the results @@ -475,15 +476,20 @@ class VMwareAPIVMTestCase(test.TestCase): self.assertEquals(self.vm_name, vm_name) return vmwareapi_fake._get_objects("VirtualMachine")[0] + def fake_get_vm_ref_from_uuid(session, vm_uuid): + return vmwareapi_fake._get_objects("VirtualMachine")[0] + def fake_call_method(*args, **kwargs): pass def fake_wait_for_task(*args, **kwargs): pass - self.stubs.Set(self.conn._vmops, "power_on", fake_power_on) + self.stubs.Set(self.conn._vmops, "_power_on", fake_power_on) self.stubs.Set(self.conn._vmops, "_get_orig_vm_name_label", fake_get_orig_vm_name_label) + self.stubs.Set(vm_util, "get_vm_ref_from_uuid", + fake_get_vm_ref_from_uuid) self.stubs.Set(vm_util, "get_vm_ref_from_name", fake_get_vm_ref_from_name) self.stubs.Set(self.conn._session, "_call_method", fake_call_method) diff --git a/nova/virt/baremetal/driver.py b/nova/virt/baremetal/driver.py index 4e8543c3e..703cc0980 100755 --- a/nova/virt/baremetal/driver.py +++ b/nova/virt/baremetal/driver.py @@ -250,7 +250,8 @@ class BareMetalDriver(driver.ComputeDriver): ) self.driver.activate_bootloader(context, node, instance, network_info=network_info) - self.power_on(instance, node) + self.power_on(context, instance, network_info, block_device_info, + node) self.driver.activate_node(context, node, instance) _update_state(context, node, instance, baremetal_states.ACTIVE) except Exception: @@ -331,7 +332,8 @@ class BareMetalDriver(driver.ComputeDriver): "for instance %r") % instance['uuid']) pm.stop_console() - def power_on(self, instance, node=None): + def power_on(self, context, instance, network_info, block_device_info=None, + node=None): """Power on the specified instance.""" if not node: node = _get_baremetal_node_by_instance_uuid(instance['uuid']) diff --git a/nova/virt/driver.py b/nova/virt/driver.py index fbc2a5640..7b2185f52 100755 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -425,7 +425,8 @@ class ComputeDriver(object): """Power off the specified instance.""" raise NotImplementedError() - def power_on(self, instance): + def power_on(self, context, instance, network_info, + block_device_info=None): """Power on the specified instance.""" raise NotImplementedError() diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 801c8e827..1d8943101 100755 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -182,7 +182,7 @@ class FakeDriver(driver.ComputeDriver): def power_off(self, instance): pass - def power_on(self, instance): + def power_on(self, context, instance, network_info, block_device_info): pass def soft_delete(self, instance): diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py index 675f36f54..e0f533db6 100755 --- a/nova/virt/hyperv/driver.py +++ b/nova/virt/hyperv/driver.py @@ -103,7 +103,8 @@ class HyperVDriver(driver.ComputeDriver): def power_off(self, instance): self._vmops.power_off(instance) - def power_on(self, instance): + def power_on(self, context, instance, network_info, + block_device_info=None): self._vmops.power_on(instance) def live_migration(self, context, instance_ref, dest, post_method, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 6a93d92ae..f4ba24cc4 100755 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -1465,13 +1465,13 @@ class LibvirtDriver(driver.ComputeDriver): """Power off the specified instance.""" self._destroy(instance) - def power_on(self, instance): + def power_on(self, context, instance, network_info, + block_device_info=None): """Power on the specified instance.""" - dom = self._lookup_by_name(instance['name']) - self._create_domain(domain=dom, instance=instance) - timer = loopingcall.FixedIntervalLoopingCall(self._wait_for_running, - instance) - timer.start(interval=0.5).wait() + # We use _hard_reboot here to ensure that all backing files, + # network, and block device connections, etc. are established + # and available before we attempt to start the instance. + self._hard_reboot(context, instance, network_info, block_device_info) def suspend(self, instance): """Suspend the specified instance.""" diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py index c2cee276d..e49bbb209 100755 --- a/nova/virt/powervm/driver.py +++ b/nova/virt/powervm/driver.py @@ -191,7 +191,8 @@ class PowerVMDriver(driver.ComputeDriver): """Power off the specified instance.""" self._powervm.power_off(instance['name']) - def power_on(self, instance): + def power_on(self, context, instance, network_info, + block_device_info=None): """Power on the specified instance.""" self._powervm.power_on(instance['name']) diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index 3cf9d32b4..1f91e5ab2 100755 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -218,9 +218,10 @@ class VMwareESXDriver(driver.ComputeDriver): """Power off the specified instance.""" self._vmops.power_off(instance) - def power_on(self, instance): + def power_on(self, context, instance, network_info, + block_device_info=None): """Power on the specified instance.""" - self._vmops.power_on(instance) + self._vmops._power_on(instance) def poll_rebooting_instances(self, timeout, instances): """Poll for rebooting instances.""" @@ -379,7 +380,8 @@ class VMwareVCDriver(VMwareESXDriver): def finish_revert_migration(self, instance, network_info, block_device_info=None, power_on=True): """Finish reverting a resize, powering back on the instance.""" - self._vmops.finish_revert_migration(instance, power_on) + self._vmops.finish_revert_migration(instance, network_info, + block_device_info, power_on) def finish_migration(self, context, migration, instance, disk_info, network_info, image_meta, resize_instance=False, @@ -387,7 +389,7 @@ class VMwareVCDriver(VMwareESXDriver): """Completes a resize, turning on the migrated instance.""" self._vmops.finish_migration(context, migration, instance, disk_info, network_info, image_meta, resize_instance, - power_on) + block_device_info, power_on) def live_migration(self, context, instance_ref, dest, post_method, recover_method, block_migration=False, diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index c58aac219..1afead6b9 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -807,7 +807,7 @@ class VMwareVMOps(object): instance['name'] = instance['name'] + self._rescue_suffix self.destroy(instance, None) instance['name'] = instance_orig_name - self.power_on(instance) + self._power_on(instance) def power_off(self, instance): """Power off the specified instance.""" @@ -832,7 +832,7 @@ class VMwareVMOps(object): LOG.debug(_("VM was already in powered off state. So returning " "without doing anything"), instance=instance) - def power_on(self, instance): + def _power_on(self, instance): """Power on the specified instance.""" vm_ref = vm_util.get_vm_ref(self._session, instance) @@ -851,6 +851,9 @@ class VMwareVMOps(object): self._session._wait_for_task(instance['uuid'], poweron_task) LOG.debug(_("Powered on the VM"), instance=instance) + def power_on(self, context, instance, network_info, block_device_info): + self._power_on(instance) + def _get_orig_vm_name_label(self, instance): return instance['name'] + '-orig' @@ -954,7 +957,8 @@ class VMwareVMOps(object): if network_info: self.unplug_vifs(instance, network_info) - def finish_revert_migration(self, instance, power_on=True): + def finish_revert_migration(self, instance, network_info, + block_device_info, power_on=True): """Finish reverting a resize.""" # The original vm was suffixed with '-orig'; find it using # the old suffix, remove the suffix, then power it back on. @@ -972,15 +976,15 @@ class VMwareVMOps(object): LOG.debug(_("Renamed the VM from %s") % name_label, instance=instance) if power_on: - self.power_on(instance) + self._power_on(instance) def finish_migration(self, context, migration, instance, disk_info, network_info, image_meta, resize_instance=False, - power_on=True): + block_device_info=None, power_on=True): """Completes a resize, turning on the migrated instance.""" # 4. Start VM if power_on: - self.power_on(instance) + self._power_on(instance) self._update_instance_progress(context, instance, step=4, total_steps=RESIZE_TOTAL_STEPS) diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py index 12a087929..37aed9812 100755 --- a/nova/virt/xenapi/driver.py +++ b/nova/virt/xenapi/driver.py @@ -266,7 +266,8 @@ class XenAPIDriver(driver.ComputeDriver): """Power off the specified instance.""" self._vmops.power_off(instance) - def power_on(self, instance): + def power_on(self, context, instance, network_info, + block_device_info=None): """Power on the specified instance.""" self._vmops.power_on(instance) |