VMWare - Check for compute node before triggering destroy

While booting an instance, if Claim on that compute node is not successful
compute manager triggers a call to destroy instance. Destroy fails since the
compute node (Cluster/ESX host) is set only after claim is successful.
Hence the check for node is made before destroy, to ensure that exception
does not get thrown. This ensures that the instance gets rescheduled
Closes-Bug: #1307408

Change-Id: Iaaf931e9c1e6cf046497e2c64952f92e802ad4be
This commit is contained in:
Sagar Ratnakara Nikam
2014-04-16 14:29:51 +05:30
parent 468b24b43b
commit aadfffaaa6
2 changed files with 104 additions and 3 deletions

View File

@@ -302,6 +302,29 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
nova.tests.image.fake.stub_out_image_service(self.stubs)
self.vnc_host = 'test_url'
self._set_exception_vars()
self.instance_without_compute = {'node': None,
'vm_state': 'building',
'project_id': 'fake',
'user_id': 'fake',
'name': '1',
'display_description': '1',
'kernel_id': '1',
'ramdisk_id': '1',
'mac_addresses': [
{'address': 'de:ad:be:ef:be:ef'}
],
'memory_mb': 8192,
'instance_type': 'm1.large',
'vcpus': 4,
'root_gb': 80,
'image_ref': '1',
'host': 'fake_host',
'task_state':
'scheduling',
'reservation_id': 'r-3t8muvr0',
'id': 1,
'uuid': 'fake-uuid',
'metadata': []}
def tearDown(self):
super(VMwareAPIVMTestCase, self).tearDown()
@@ -1219,9 +1242,25 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
self.assertEqual(len(instances), 0)
def test_destroy_non_existent(self):
self._create_instance()
self.assertIsNone(self.conn.destroy(self.context, self.instance,
self.network_info))
self.destroy_disks = True
with mock.patch.object(self.conn._vmops,
"destroy") as mock_destroy:
self._create_instance()
self.conn.destroy(self.context, self.instance,
self.network_info,
None, self.destroy_disks)
mock_destroy.assert_called_once_with(self.instance,
self.network_info,
self.destroy_disks)
def test_destroy_instance_without_compute(self):
self.destroy_disks = True
with mock.patch.object(self.conn._vmops,
"destroy") as mock_destroy:
self.conn.destroy(self.context, self.instance_without_compute,
self.network_info,
None, self.destroy_disks)
self.assertFalse(mock_destroy.called)
def _rescue(self, config_drive=False):
def fake_attach_disk_to_vm(vm_ref, instance,
@@ -2204,3 +2243,51 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
"instance", [], None)
mock_destroy.assert_called_once_with(self.context,
"instance", [], None)
def test_destroy(self):
self._create_vm()
info = self.conn.get_info({'uuid': self.uuid,
'node': self.instance_node})
self._check_vm_info(info, power_state.RUNNING)
instances = self.conn.list_instances()
self.assertEqual(1, len(instances))
self.conn.destroy(self.context, self.instance, self.network_info)
instances = self.conn.list_instances()
self.assertEqual(0, len(instances))
self.assertIsNone(vm_util.vm_ref_cache_get(self.uuid))
def test_destroy_no_datastore(self):
self._create_vm()
info = self.conn.get_info({'uuid': self.uuid,
'node': self.instance_node})
self._check_vm_info(info, power_state.RUNNING)
instances = self.conn.list_instances()
self.assertEqual(1, len(instances))
# Overwrite the vmPathName
vms = vmwareapi_fake._get_objects("VirtualMachine")
vm = vms.objects[0]
vm.set("config.files.vmPathName", None)
self.conn.destroy(self.context, self.instance, self.network_info)
instances = self.conn.list_instances()
self.assertEqual(0, len(instances))
def test_destroy_non_existent(self):
self.destroy_disks = True
with mock.patch.object(self.conn._vmops,
"destroy") as mock_destroy:
self._create_instance()
self.conn.destroy(self.context, self.instance,
self.network_info,
None, self.destroy_disks)
mock_destroy.assert_called_once_with(self.instance,
self.network_info,
self.destroy_disks)
def test_destroy_instance_without_compute(self):
self.destroy_disks = True
with mock.patch.object(self.conn._vmops,
"destroy") as mock_destroy:
self.conn.destroy(self.context, self.instance_without_compute,
self.network_info,
None, self.destroy_disks)
self.assertFalse(mock_destroy.called)

View File

@@ -182,6 +182,13 @@ class VMwareESXDriver(driver.ComputeDriver):
def destroy(self, context, instance, network_info, block_device_info=None,
destroy_disks=True):
"""Destroy VM instance."""
# Destroy gets triggered when Resource Claim in resource_tracker
# is not successful. When resource claim is not successful,
# node is not set in instance. Perform destroy only if node is set
if not instance['node']:
return
self._vmops.destroy(instance, network_info, destroy_disks)
def cleanup(self, context, instance, network_info, block_device_info=None,
@@ -653,6 +660,13 @@ class VMwareVCDriver(VMwareESXDriver):
def destroy(self, context, instance, network_info, block_device_info=None,
destroy_disks=True):
"""Destroy VM instance."""
# Destroy gets triggered when Resource Claim in resource_tracker
# is not successful. When resource claim is not successful,
# node is not set in instance. Perform destroy only if node is set
if not instance['node']:
return
_vmops = self._get_vmops_for_compute_node(instance['node'])
_vmops.destroy(instance, network_info, destroy_disks)