From cebcb28357131a2bf4761bbddebbedf2a7951a11 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Thu, 20 Mar 2014 12:58:03 -0700 Subject: [PATCH] VMware: spawn refactor - phase 1 - execute_create_vm Moves the inner function "execute_create_vm" from the spawn method to vm_util. Additionally, return the vm_ref after VM creation so an extra call to retrieve the vm_ref does not need to take place after the fact. partial blueprint vmware-spawn-refactor Co-authored-by: Tracy Jones Change-Id: I67c3c8c14b6c01b160611cc001d51f1da29ffb24 --- nova/tests/virt/vmwareapi/test_vm_util.py | 46 +++++++++++++++++++++++ nova/virt/vmwareapi/fake.py | 2 +- nova/virt/vmwareapi/vm_util.py | 12 ++++++ nova/virt/vmwareapi/vmops.py | 27 ++----------- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/nova/tests/virt/vmwareapi/test_vm_util.py b/nova/tests/virt/vmwareapi/test_vm_util.py index 84392dc38b24..446814dba0f7 100644 --- a/nova/tests/virt/vmwareapi/test_vm_util.py +++ b/nova/tests/virt/vmwareapi/test_vm_util.py @@ -17,6 +17,7 @@ import collections import re +import contextlib import mock from nova import exception @@ -39,6 +40,9 @@ class fake_session(object): self.ind = (self.ind + 1) % len(self.ret) return self.ret[self.ind - 1] + def _wait_for_task(self): + pass + def _get_vim(self): fake_vim = fake.DataObject() client = fake.DataObject() @@ -632,6 +636,48 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): result = re.sub(r'\s+', '', repr(result)) self.assertEqual(expected, result) + def test_create_vm(self): + + method_list = ['CreateVM_Task', 'get_dynamic_property'] + + def fake_call_method(module, method, *args, **kwargs): + expected_method = method_list.pop(0) + self.assertEqual(expected_method, method) + if (expected_method == 'CreateVM_Task'): + return 'fake_create_vm_task' + elif (expected_method == 'get_dynamic_property'): + task_info = mock.Mock(state="success", result="fake_vm_ref") + return task_info + else: + self.fail('Should not get here....') + + def fake_wait_for_task(self, *args): + task_info = mock.Mock(state="success", result="fake_vm_ref") + return task_info + + session = fake_session() + fake_instance = mock.MagicMock() + fake_call_mock = mock.Mock(side_effect=fake_call_method) + fake_wait_mock = mock.Mock(side_effect=fake_wait_for_task) + with contextlib.nested( + mock.patch.object(session, '_wait_for_task', + fake_wait_mock), + mock.patch.object(session, '_call_method', + fake_call_mock) + ) as (wait_for_task, call_method): + vm_ref = vm_util.create_vm( + session, + fake_instance, + 'fake_vm_folder', + 'fake_config_spec', + 'fake_res_pool_ref') + self.assertEqual('fake_vm_ref', vm_ref) + + call_method.assert_called_once_with(mock.ANY, 'CreateVM_Task', + 'fake_vm_folder', config='fake_config_spec', + pool='fake_res_pool_ref') + wait_for_task.assert_called_once_with('fake_create_vm_task') + def test_convert_vif_model(self): expected = "VirtualE1000" result = vm_util._convert_vif_model(network_model.VIF_MODEL_E1000) diff --git a/nova/virt/vmwareapi/fake.py b/nova/virt/vmwareapi/fake.py index 182c4b716794..bb5ee7dca2a8 100644 --- a/nova/virt/vmwareapi/fake.py +++ b/nova/virt/vmwareapi/fake.py @@ -1098,7 +1098,7 @@ class FakeVim(object): _create_object("VirtualMachine", virtual_machine) res_pool = _get_object(pool) res_pool.vm.ManagedObjectReference.append(virtual_machine.obj) - task_mdo = create_task(method, "success") + task_mdo = create_task(method, "success", result=virtual_machine.obj) return task_mdo.obj def _reconfig_vm(self, method, *args, **kwargs): diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py index 73168c4e742c..aa950aae5f30 100644 --- a/nova/virt/vmwareapi/vm_util.py +++ b/nova/virt/vmwareapi/vm_util.py @@ -1379,6 +1379,18 @@ def get_vmdk_adapter_type(adapter_type): return vmdk_adapter_type +def create_vm(session, instance, vm_folder, config_spec, res_pool_ref): + """Create VM on ESX host.""" + LOG.debug(_("Creating VM on the ESX host"), instance=instance) + vm_create_task = session._call_method( + session._get_vim(), + "CreateVM_Task", vm_folder, + config=config_spec, pool=res_pool_ref) + task_info = session._wait_for_task(vm_create_task) + LOG.debug(_("Created VM on the ESX host"), instance=instance) + return task_info.result + + def clone_vmref_for_instance(session, instance, vm_ref, host_ref, ds_ref, vmfolder_ref): """Clone VM and link the cloned VM to the instance. diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 2b2c5db4a410..84ef490c8b9a 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -259,33 +259,14 @@ class VMwareVMOps(object): # for example when the spawn of a rescue instance takes place. if not instance_name: instance_name = instance['uuid'] - # Get the create vm config spec + + # Create the VM config_spec = vm_util.get_vm_create_spec( client_factory, instance, instance_name, data_store_name, vif_infos, os_type) - def _execute_create_vm(): - """Create VM on ESX host.""" - LOG.debug(_("Creating VM on the ESX host"), instance=instance) - # Create the VM on the ESX host - vm_create_task = self._session._call_method( - self._session._get_vim(), - "CreateVM_Task", dc_info.vmFolder, - config=config_spec, pool=res_pool_ref) - self._session._wait_for_task(vm_create_task) - - LOG.debug(_("Created VM on the ESX host"), instance=instance) - - _execute_create_vm() - - # In the case of a rescue disk the instance_name is not the same as - # instance UUID. In this case the VM reference is accessed via the - # instance name. - if instance_name != instance['uuid']: - vm_ref = vm_util.get_vm_ref_from_name(self._session, - instance_name) - else: - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.create_vm(self._session, instance, dc_info.vmFolder, + config_spec, res_pool_ref) # Set the machine.id parameter of the instance to inject # the NIC configuration inside the VM