Merge "VMware: fix bug when more than one datacenter exists" into stable/havana
This commit is contained in:
commit
2c44ed7587
|
@ -42,7 +42,7 @@ class ConfigDriveTestCase(test.NoDBTestCase):
|
|||
host_password='test_pass',
|
||||
use_linked_clone=False, group='vmware')
|
||||
self.flags(vnc_enabled=False)
|
||||
vmwareapi_fake.reset()
|
||||
vmwareapi_fake.reset(vc=True)
|
||||
stubs.set_stubs(self.stubs)
|
||||
nova.tests.image.fake.stub_out_image_service(self.stubs)
|
||||
self.conn = driver.VMwareVCDriver(fake.FakeVirtAPI)
|
||||
|
@ -117,6 +117,7 @@ class ConfigDriveTestCase(test.NoDBTestCase):
|
|||
mox.IgnoreArg(),
|
||||
mox.IgnoreArg(),
|
||||
mox.IgnoreArg(),
|
||||
mox.IgnoreArg(),
|
||||
mox.IgnoreArg())
|
||||
self.conn._vmops._attach_cdrom_to_vm(mox.IgnoreArg(),
|
||||
mox.IgnoreArg(),
|
||||
|
|
|
@ -205,10 +205,11 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
self.user_id = 'fake'
|
||||
self.project_id = 'fake'
|
||||
self.node_name = 'test_url'
|
||||
self.ds = 'ds1'
|
||||
self.context = context.RequestContext(self.user_id, self.project_id)
|
||||
vmwareapi_fake.reset()
|
||||
db_fakes.stub_out_db_instance_api(self.stubs)
|
||||
stubs.set_stubs(self.stubs)
|
||||
vmwareapi_fake.reset()
|
||||
self.conn = driver.VMwareESXDriver(fake.FakeVirtAPI)
|
||||
# NOTE(vish): none of the network plugging code is actually
|
||||
# being tested
|
||||
|
@ -359,8 +360,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
"""
|
||||
|
||||
self._create_vm()
|
||||
inst_file_path = '[fake-ds] %s/fake_name.vmdk' % self.uuid
|
||||
cache_file_path = '[fake-ds] vmware_base/fake_image_uuid.vmdk'
|
||||
inst_file_path = '[%s] %s/fake_name.vmdk' % (self.ds, self.uuid)
|
||||
cache_file_path = '[%s] vmware_base/fake_image_uuid.vmdk' % self.ds
|
||||
self.assertTrue(vmwareapi_fake.get_file(inst_file_path))
|
||||
self.assertTrue(vmwareapi_fake.get_file(cache_file_path))
|
||||
|
||||
|
@ -368,8 +369,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
"""Test image disk is cached when use_linked_clone is True."""
|
||||
self.flags(use_linked_clone=True, group='vmware')
|
||||
self._create_vm()
|
||||
cache_file_path = '[fake-ds] vmware_base/fake_image_uuid.vmdk'
|
||||
cache_root_path = '[fake-ds] vmware_base/fake_image_uuid.80.vmdk'
|
||||
cache_file_path = '[%s] vmware_base/fake_image_uuid.vmdk' % self.ds
|
||||
cache_root_path = '[%s] vmware_base/fake_image_uuid.80.vmdk' % self.ds
|
||||
self.assertTrue(vmwareapi_fake.get_file(cache_file_path))
|
||||
self.assertTrue(vmwareapi_fake.get_file(cache_root_path))
|
||||
|
||||
|
@ -1129,9 +1130,14 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
|
|||
self.flags(cluster_name=[cluster_name, cluster_name2],
|
||||
task_poll_interval=10, datastore_regex='.*', group='vmware')
|
||||
self.flags(vnc_enabled=False)
|
||||
vmwareapi_fake.reset(vc=True)
|
||||
self.conn = driver.VMwareVCDriver(None, False)
|
||||
self.node_name = self.conn._resources.keys()[0]
|
||||
self.node_name2 = self.conn._resources.keys()[1]
|
||||
if cluster_name2 in self.node_name2:
|
||||
self.ds = 'ds1'
|
||||
else:
|
||||
self.ds = 'ds2'
|
||||
self.vnc_host = 'ha-host'
|
||||
|
||||
def tearDown(self):
|
||||
|
@ -1245,11 +1251,11 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
|
|||
# Check calls for delete vmdk and -flat.vmdk pair
|
||||
self.conn._vmops._delete_datastore_file(
|
||||
mox.IgnoreArg(),
|
||||
"[fake-ds] vmware-tmp/%s-flat.vmdk" % uuid_str,
|
||||
"[%s] vmware-tmp/%s-flat.vmdk" % (self.ds, uuid_str),
|
||||
mox.IgnoreArg()).AndReturn(None)
|
||||
self.conn._vmops._delete_datastore_file(
|
||||
mox.IgnoreArg(),
|
||||
"[fake-ds] vmware-tmp/%s.vmdk" % uuid_str,
|
||||
"[%s] vmware-tmp/%s.vmdk" % (self.ds, uuid_str),
|
||||
mox.IgnoreArg()).AndReturn(None)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
@ -1311,3 +1317,10 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
|
|||
def test_confirm_migration(self):
|
||||
self._create_vm()
|
||||
self.conn.confirm_migration(self.context, self.instance, None)
|
||||
|
||||
def test_datastore_dc_map(self):
|
||||
vmops = self.conn._resources[self.node_name]['vmops']
|
||||
self.assertEqual({}, vmops._datastore_dc_mapping)
|
||||
self._create_vm()
|
||||
# currently there are 2 data stores
|
||||
self.assertEqual(2, len(vmops._datastore_dc_mapping))
|
||||
|
|
|
@ -48,8 +48,28 @@ def log_db_contents(msg=None):
|
|||
{'text': msg or "", 'content': pprint.pformat(_db_content)})
|
||||
|
||||
|
||||
def reset():
|
||||
def reset(vc=False):
|
||||
"""Resets the db contents."""
|
||||
cleanup()
|
||||
create_network()
|
||||
create_host_network_system()
|
||||
create_host_storage_system()
|
||||
create_host()
|
||||
ds_ref1 = create_datastore('ds1', 1024, 500)
|
||||
if vc:
|
||||
create_host()
|
||||
ds_ref2 = create_datastore('ds2', 1024, 500)
|
||||
create_datacenter('dc1', ds_ref1)
|
||||
if vc:
|
||||
create_datacenter('dc2', ds_ref2)
|
||||
create_res_pool()
|
||||
if vc:
|
||||
create_cluster('test_cluster', ds_ref1)
|
||||
create_cluster('test_cluster2', ds_ref2)
|
||||
|
||||
|
||||
def cleanup():
|
||||
"""Clear the db contents."""
|
||||
for c in _CLASSES:
|
||||
# We fake the datastore by keeping the file references as a list of
|
||||
# names in the db
|
||||
|
@ -57,22 +77,6 @@ def reset():
|
|||
_db_content[c] = []
|
||||
else:
|
||||
_db_content[c] = {}
|
||||
create_network()
|
||||
create_host_network_system()
|
||||
create_host_storage_system()
|
||||
create_host()
|
||||
create_host()
|
||||
create_datacenter()
|
||||
create_datastore()
|
||||
create_res_pool()
|
||||
create_cluster('test_cluster')
|
||||
create_cluster('test_cluster2')
|
||||
|
||||
|
||||
def cleanup():
|
||||
"""Clear the db contents."""
|
||||
for c in _CLASSES:
|
||||
_db_content[c] = {}
|
||||
|
||||
|
||||
def _create_object(table, table_obj):
|
||||
|
@ -498,7 +502,7 @@ class ClusterComputeResource(ManagedObject):
|
|||
class Datastore(ManagedObject):
|
||||
"""Datastore class."""
|
||||
|
||||
def __init__(self, name="fake-ds"):
|
||||
def __init__(self, name="fake-ds", capacity=1024, free=500):
|
||||
super(Datastore, self).__init__("ds")
|
||||
self.set("summary.type", "VMFS")
|
||||
self.set("summary.name", name)
|
||||
|
@ -680,7 +684,7 @@ class HostSystem(ManagedObject):
|
|||
class Datacenter(ManagedObject):
|
||||
"""Datacenter class."""
|
||||
|
||||
def __init__(self, name="ha-datacenter"):
|
||||
def __init__(self, name="ha-datacenter", ds_ref=None):
|
||||
super(Datacenter, self).__init__("dc")
|
||||
self.set("name", name)
|
||||
self.set("vmFolder", "vm_folder_ref")
|
||||
|
@ -690,6 +694,9 @@ class Datacenter(ManagedObject):
|
|||
network_do = DataObject()
|
||||
network_do.ManagedObjectReference = [net_ref]
|
||||
self.set("network", network_do)
|
||||
datastore = DataObject()
|
||||
datastore.ManagedObjectReference = [ds_ref]
|
||||
self.set("datastore", datastore)
|
||||
|
||||
|
||||
class Task(ManagedObject):
|
||||
|
@ -719,14 +726,15 @@ def create_host():
|
|||
_create_object('HostSystem', host_system)
|
||||
|
||||
|
||||
def create_datacenter():
|
||||
data_center = Datacenter()
|
||||
def create_datacenter(name, ds_ref=None):
|
||||
data_center = Datacenter(name, ds_ref)
|
||||
_create_object('Datacenter', data_center)
|
||||
|
||||
|
||||
def create_datastore():
|
||||
data_store = Datastore()
|
||||
def create_datastore(name, capacity, free):
|
||||
data_store = Datastore(name, capacity, free)
|
||||
_create_object('Datastore', data_store)
|
||||
return data_store.obj
|
||||
|
||||
|
||||
def create_res_pool():
|
||||
|
@ -739,11 +747,11 @@ def create_network():
|
|||
_create_object('Network', network)
|
||||
|
||||
|
||||
def create_cluster(name):
|
||||
def create_cluster(name, ds_ref):
|
||||
cluster = ClusterComputeResource(name=name)
|
||||
cluster._add_host(_get_object_refs("HostSystem")[0])
|
||||
cluster._add_host(_get_object_refs("HostSystem")[1])
|
||||
cluster._add_datastore(_get_object_refs("Datastore")[0])
|
||||
cluster._add_datastore(ds_ref)
|
||||
cluster._add_root_resource_pool(_get_object_refs("ResourcePool")[0])
|
||||
_create_object('ClusterComputeResource', cluster)
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ Class for VM tasks like spawn, snapshot, suspend, resume etc.
|
|||
"""
|
||||
|
||||
import base64
|
||||
import collections
|
||||
import copy
|
||||
import os
|
||||
import time
|
||||
|
@ -76,6 +77,9 @@ VMWARE_LINKED_CLONE = 'vmware_linked_clone'
|
|||
|
||||
RESIZE_TOTAL_STEPS = 4
|
||||
|
||||
DcInfo = collections.namedtuple('DcInfo',
|
||||
['ref', 'name', 'vmFolder'])
|
||||
|
||||
|
||||
class VMwareVMOps(object):
|
||||
"""Management class for VM-related tasks."""
|
||||
|
@ -94,6 +98,7 @@ class VMwareVMOps(object):
|
|||
self._rescue_suffix = '-rescue'
|
||||
self._poll_rescue_last_ran = None
|
||||
self._is_neutron = utils.is_neutron()
|
||||
self._datastore_dc_mapping = {}
|
||||
|
||||
def list_instances(self):
|
||||
"""Lists the VM instances that are registered with the ESX host."""
|
||||
|
@ -192,6 +197,7 @@ class VMwareVMOps(object):
|
|||
datastore_regex=self._datastore_regex)
|
||||
data_store_ref = ds[0]
|
||||
data_store_name = ds[1]
|
||||
dc_info = self.get_datacenter_ref_and_name(data_store_ref)
|
||||
|
||||
#TODO(hartsocks): this pattern is confusing, reimplement as methods
|
||||
# The use of nested functions in this file makes for a confusing and
|
||||
|
@ -240,7 +246,6 @@ class VMwareVMOps(object):
|
|||
raise exception.InstanceUnacceptable(instance_id=instance['uuid'],
|
||||
reason=reason)
|
||||
|
||||
vm_folder_ref = self._get_vmfolder_ref()
|
||||
node_mo_id = vm_util.get_mo_id_from_instance(instance)
|
||||
res_pool_ref = vm_util.get_res_pool_ref(self._session,
|
||||
self._cluster, node_mo_id)
|
||||
|
@ -278,7 +283,7 @@ class VMwareVMOps(object):
|
|||
# Create the VM on the ESX host
|
||||
vm_create_task = self._session._call_method(
|
||||
self._session._get_vim(),
|
||||
"CreateVM_Task", vm_folder_ref,
|
||||
"CreateVM_Task", dc_info.vmFolder,
|
||||
config=config_spec, pool=res_pool_ref)
|
||||
self._session._wait_for_task(instance['uuid'], vm_create_task)
|
||||
|
||||
|
@ -322,7 +327,7 @@ class VMwareVMOps(object):
|
|||
"CreateVirtualDisk_Task",
|
||||
service_content.virtualDiskManager,
|
||||
name=uploaded_vmdk_path,
|
||||
datacenter=dc_ref,
|
||||
datacenter=dc_info.ref,
|
||||
spec=vmdk_create_spec)
|
||||
self._session._wait_for_task(instance['uuid'], vmdk_create_task)
|
||||
LOG.debug(_("Created Virtual Disk of size %(vmdk_file_size_in_kb)s"
|
||||
|
@ -351,7 +356,7 @@ class VMwareVMOps(object):
|
|||
instance['image_ref'],
|
||||
instance,
|
||||
host=self._session._host_ip,
|
||||
data_center_name=self._get_datacenter_ref_and_name()[1],
|
||||
data_center_name=dc_info.name,
|
||||
datastore_name=data_store_name,
|
||||
cookies=cookies,
|
||||
file_path=upload_vmdk_name)
|
||||
|
@ -386,7 +391,7 @@ class VMwareVMOps(object):
|
|||
"CopyVirtualDisk_Task",
|
||||
service_content.virtualDiskManager,
|
||||
sourceName=source,
|
||||
sourceDatacenter=self._get_datacenter_ref_and_name()[0],
|
||||
sourceDatacenter=dc_info.ref,
|
||||
destName=dest,
|
||||
destSpec=vmdk_copy_spec)
|
||||
self._session._wait_for_task(instance['uuid'], vmdk_copy_task)
|
||||
|
@ -435,14 +440,12 @@ class VMwareVMOps(object):
|
|||
sparse_uploaded_vmdk_path = vm_util.build_datastore_path(
|
||||
data_store_name,
|
||||
sparse_uploaded_vmdk_name)
|
||||
dc_ref = self._get_datacenter_ref_and_name()[0]
|
||||
|
||||
if disk_type != "sparse":
|
||||
# Create a flat virtual disk and retain the metadata file.
|
||||
_create_virtual_disk()
|
||||
self._delete_datastore_file(instance,
|
||||
flat_uploaded_vmdk_path,
|
||||
dc_ref)
|
||||
dc_info.ref)
|
||||
|
||||
_fetch_image_on_esx_datastore()
|
||||
|
||||
|
@ -453,7 +456,7 @@ class VMwareVMOps(object):
|
|||
uploaded_vmdk_path)
|
||||
self._delete_datastore_file(instance,
|
||||
sparse_uploaded_vmdk_path,
|
||||
dc_ref)
|
||||
dc_info.ref)
|
||||
else:
|
||||
# linked clone base disk exists
|
||||
if disk_type == "sparse":
|
||||
|
@ -475,7 +478,7 @@ class VMwareVMOps(object):
|
|||
root_vmdk_path = dest_vmdk_path
|
||||
if root_gb_in_kb > vmdk_file_size_in_kb:
|
||||
self._extend_virtual_disk(instance, root_gb_in_kb,
|
||||
root_vmdk_path, dc_ref)
|
||||
root_vmdk_path, dc_info.ref)
|
||||
else:
|
||||
root_vmdk_name = "%s/%s.%s.vmdk" % (upload_folder, upload_name,
|
||||
root_gb)
|
||||
|
@ -485,7 +488,6 @@ class VMwareVMOps(object):
|
|||
data_store_ref, data_store_name,
|
||||
upload_folder,
|
||||
upload_name + ".%s.vmdk" % root_gb):
|
||||
dc_ref = self._get_datacenter_ref_and_name()[0]
|
||||
LOG.debug(_("Copying root disk of size %sGb"), root_gb)
|
||||
copy_spec = self.get_copy_virtual_disk_spec(
|
||||
client_factory, adapter_type, disk_type)
|
||||
|
@ -494,14 +496,14 @@ class VMwareVMOps(object):
|
|||
"CopyVirtualDisk_Task",
|
||||
service_content.virtualDiskManager,
|
||||
sourceName=uploaded_vmdk_path,
|
||||
sourceDatacenter=dc_ref,
|
||||
sourceDatacenter=dc_info.ref,
|
||||
destName=root_vmdk_path,
|
||||
destSpec=copy_spec)
|
||||
self._session._wait_for_task(instance['uuid'],
|
||||
vmdk_copy_task)
|
||||
if root_gb_in_kb > vmdk_file_size_in_kb:
|
||||
self._extend_virtual_disk(instance, root_gb_in_kb,
|
||||
root_vmdk_path, dc_ref)
|
||||
root_vmdk_path, dc_info.ref)
|
||||
|
||||
# Attach the root disk to the VM.
|
||||
self._volumeops.attach_disk_to_vm(
|
||||
|
@ -514,6 +516,7 @@ class VMwareVMOps(object):
|
|||
injected_files,
|
||||
admin_password,
|
||||
data_store_name,
|
||||
dc_info.name,
|
||||
instance['uuid'],
|
||||
cookies)
|
||||
uploaded_iso_path = vm_util.build_datastore_path(
|
||||
|
@ -545,7 +548,7 @@ class VMwareVMOps(object):
|
|||
_power_on_vm()
|
||||
|
||||
def _create_config_drive(self, instance, injected_files, admin_password,
|
||||
data_store_name, upload_folder, cookies):
|
||||
data_store_name, dc_name, upload_folder, cookies):
|
||||
if CONF.config_drive_format != 'iso9660':
|
||||
reason = (_('Invalid config_drive_format "%s"') %
|
||||
CONF.config_drive_format)
|
||||
|
@ -564,8 +567,6 @@ class VMwareVMOps(object):
|
|||
with utils.tempdir() as tmp_path:
|
||||
tmp_file = os.path.join(tmp_path, 'configdrive.iso')
|
||||
cdb.make_drive(tmp_file)
|
||||
dc_name = self._get_datacenter_ref_and_name()[1]
|
||||
|
||||
upload_iso_path = "%s/configdrive.iso" % (
|
||||
upload_folder)
|
||||
vmware_images.upload_iso_to_datastore(
|
||||
|
@ -733,9 +734,11 @@ class VMwareVMOps(object):
|
|||
"vmware-tmp")
|
||||
if not self._path_exists(ds_browser, tmp_folder_path):
|
||||
self._mkdir(vm_util.build_datastore_path(datastore_name,
|
||||
"vmware-tmp"))
|
||||
"vmware-tmp"),
|
||||
ds_ref)
|
||||
return ds_ref
|
||||
|
||||
_check_if_tmp_folder_exists()
|
||||
ds_ref = _check_if_tmp_folder_exists()
|
||||
|
||||
# Generate a random vmdk file name to which the coalesced vmdk content
|
||||
# will be copied to. A random name is chosen so that we don't have
|
||||
|
@ -745,7 +748,7 @@ class VMwareVMOps(object):
|
|||
"vmware-tmp/%s.vmdk" % random_name)
|
||||
dest_vmdk_data_file_path = vm_util.build_datastore_path(datastore_name,
|
||||
"vmware-tmp/%s-flat.vmdk" % random_name)
|
||||
dc_ref = self._get_datacenter_ref_and_name()[0]
|
||||
dc_info = self.get_datacenter_ref_and_name(ds_ref)
|
||||
|
||||
def _copy_vmdk_content():
|
||||
# Copy the contents of the disk (or disks, if there were snapshots
|
||||
|
@ -760,9 +763,9 @@ class VMwareVMOps(object):
|
|||
"CopyVirtualDisk_Task",
|
||||
service_content.virtualDiskManager,
|
||||
sourceName=vmdk_file_path_before_snapshot,
|
||||
sourceDatacenter=dc_ref,
|
||||
sourceDatacenter=dc_info.ref,
|
||||
destName=dest_vmdk_file_path,
|
||||
destDatacenter=dc_ref,
|
||||
destDatacenter=dc_info.ref,
|
||||
destSpec=copy_spec,
|
||||
force=False)
|
||||
self._session._wait_for_task(instance['uuid'], copy_disk_task)
|
||||
|
@ -785,7 +788,7 @@ class VMwareVMOps(object):
|
|||
adapter_type=adapter_type,
|
||||
image_version=1,
|
||||
host=self._session._host_ip,
|
||||
data_center_name=self._get_datacenter_ref_and_name()[1],
|
||||
data_center_name=dc_info.name,
|
||||
datastore_name=datastore_name,
|
||||
cookies=cookies,
|
||||
file_path="vmware-tmp/%s-flat.vmdk" % random_name)
|
||||
|
@ -807,7 +810,7 @@ class VMwareVMOps(object):
|
|||
# is retained too by design since it makes little sense to remove
|
||||
# it when the data disk it refers to still lingers.
|
||||
for f in dest_vmdk_data_file_path, dest_vmdk_file_path:
|
||||
self._delete_datastore_file(instance, f, dc_ref)
|
||||
self._delete_datastore_file(instance, f, dc_info.ref)
|
||||
|
||||
_clean_temp_data()
|
||||
|
||||
|
@ -899,12 +902,14 @@ class VMwareVMOps(object):
|
|||
"""
|
||||
try:
|
||||
vm_ref = vm_util.get_vm_ref(self._session, instance)
|
||||
lst_properties = ["config.files.vmPathName", "runtime.powerState"]
|
||||
lst_properties = ["config.files.vmPathName", "runtime.powerState",
|
||||
"datastore"]
|
||||
props = self._session._call_method(vim_util,
|
||||
"get_object_properties",
|
||||
None, vm_ref, "VirtualMachine", lst_properties)
|
||||
query = {'runtime.powerState': None,
|
||||
'config.files.vmPathName': None}
|
||||
'config.files.vmPathName': None,
|
||||
'datastore': None}
|
||||
self._get_values_from_object_properties(props, query)
|
||||
pwr_state = query['runtime.powerState']
|
||||
vm_config_pathname = query['config.files.vmPathName']
|
||||
|
@ -944,13 +949,16 @@ class VMwareVMOps(object):
|
|||
"datastore %(datastore_name)s") %
|
||||
{'datastore_name': datastore_name},
|
||||
instance=instance)
|
||||
ds_ref_ret = query['datastore']
|
||||
ds_ref = ds_ref_ret.ManagedObjectReference[0]
|
||||
dc_info = self.get_datacenter_ref_and_name(ds_ref)
|
||||
vim = self._session._get_vim()
|
||||
delete_task = self._session._call_method(
|
||||
vim,
|
||||
"DeleteDatastoreFile_Task",
|
||||
vim.get_service_content().fileManager,
|
||||
name=dir_ds_compliant_path,
|
||||
datacenter=self._get_datacenter_ref_and_name()[0])
|
||||
datacenter=dc_info.ref)
|
||||
self._session._wait_for_task(instance['uuid'], delete_task)
|
||||
LOG.debug(_("Deleted contents of the VM from "
|
||||
"datastore %(datastore_name)s") %
|
||||
|
@ -1163,14 +1171,14 @@ class VMwareVMOps(object):
|
|||
client_factory = self._session._get_vim().client.factory
|
||||
rel_spec = vm_util.relocate_vm_spec(client_factory, ds_ref, host_ref)
|
||||
clone_spec = vm_util.clone_vm_spec(client_factory, rel_spec)
|
||||
vm_folder_ref = self._get_vmfolder_ref()
|
||||
dc_info = self.get_datacenter_ref_and_name(ds_ref)
|
||||
|
||||
# 3. Clone VM on ESX host
|
||||
LOG.debug(_("Cloning VM to host %s") % dest, instance=instance)
|
||||
vm_clone_task = self._session._call_method(
|
||||
self._session._get_vim(),
|
||||
"CloneVM_Task", vm_ref,
|
||||
folder=vm_folder_ref,
|
||||
folder=dc_info.vmFolder,
|
||||
name=instance['uuid'],
|
||||
spec=clone_spec)
|
||||
self._session._wait_for_task(instance['uuid'], vm_clone_task)
|
||||
|
@ -1432,12 +1440,18 @@ class VMwareVMOps(object):
|
|||
"port - %(port)s") % {'port': port},
|
||||
instance=instance)
|
||||
|
||||
def _get_datacenter_ref_and_name(self):
|
||||
def get_datacenter_ref_and_name(self, ds_ref):
|
||||
"""Get the datacenter name and the reference."""
|
||||
dc_obj = self._session._call_method(vim_util, "get_objects",
|
||||
"Datacenter", ["name"])
|
||||
vm_util._cancel_retrieve_if_necessary(self._session, dc_obj)
|
||||
return dc_obj.objects[0].obj, dc_obj.objects[0].propSet[0].val
|
||||
map = self._datastore_dc_mapping.get(ds_ref.value)
|
||||
if not map:
|
||||
dc_obj = self._session._call_method(vim_util, "get_objects",
|
||||
"Datacenter", ["name"])
|
||||
vm_util._cancel_retrieve_if_necessary(self._session, dc_obj)
|
||||
map = DcInfo(ref=dc_obj.objects[0].obj,
|
||||
name=dc_obj.objects[0].propSet[0].val,
|
||||
vmFolder=self._get_vmfolder_ref())
|
||||
self._datastore_dc_mapping[ds_ref.value] = map
|
||||
return map
|
||||
|
||||
def _get_host_ref_from_name(self, host_name):
|
||||
"""Get reference to the host with the name specified."""
|
||||
|
@ -1521,17 +1535,17 @@ class VMwareVMOps(object):
|
|||
task_info.result.file[0].path == file_name)
|
||||
return True, file_exists
|
||||
|
||||
def _mkdir(self, ds_path):
|
||||
def _mkdir(self, ds_path, ds_ref):
|
||||
"""
|
||||
Creates a directory at the path specified. If it is just "NAME",
|
||||
then a directory with this name is created at the topmost level of the
|
||||
DataStore.
|
||||
"""
|
||||
LOG.debug(_("Creating directory with path %s") % ds_path)
|
||||
dc_ref = self._get_datacenter_ref_and_name()[0]
|
||||
dc_info = self.get_datacenter_ref_and_name(ds_ref)
|
||||
self._session._call_method(self._session._get_vim(), "MakeDirectory",
|
||||
self._session._get_vim().get_service_content().fileManager,
|
||||
name=ds_path, datacenter=dc_ref,
|
||||
name=ds_path, datacenter=dc_info.ref,
|
||||
createParentDirectories=False)
|
||||
LOG.debug(_("Created directory with path %s") % ds_path)
|
||||
|
||||
|
@ -1549,7 +1563,8 @@ class VMwareVMOps(object):
|
|||
folder_path,
|
||||
file_name)
|
||||
if not folder_exists:
|
||||
self._mkdir(vm_util.build_datastore_path(ds_name, folder_name))
|
||||
self._mkdir(vm_util.build_datastore_path(ds_name, folder_name),
|
||||
ds_ref)
|
||||
|
||||
return file_exists
|
||||
|
||||
|
@ -1586,3 +1601,43 @@ class VMwareVCVMOps(VMwareVMOps):
|
|||
# VirtualDiskManager.CopyVirtualDisk is called on VC. The behavior of a
|
||||
# spec-less copy is to consolidate to the target disk while keeping its
|
||||
# disk and adapter type unchanged.
|
||||
|
||||
def _update_datacenter_cache_from_objects(self, dcs):
|
||||
"""Updates the datastore/datacenter cache."""
|
||||
|
||||
while dcs:
|
||||
token = vm_util._get_token(dcs)
|
||||
for dco in dcs.objects:
|
||||
name = None
|
||||
vmFolder = None
|
||||
dc_ref = dco.obj
|
||||
ds_refs = []
|
||||
for p in dco.propSet:
|
||||
if p.name == 'name':
|
||||
name = p.val
|
||||
if p.name == 'datastore':
|
||||
datastore_refs = p.val.ManagedObjectReference
|
||||
for ds in datastore_refs:
|
||||
ds_refs.append(ds.value)
|
||||
if p.name == 'vmFolder':
|
||||
vmFolder = p.val
|
||||
for ds_ref in ds_refs:
|
||||
self._datastore_dc_mapping[ds_ref] = DcInfo(ref=dc_ref,
|
||||
name=name, vmFolder=vmFolder)
|
||||
|
||||
if token:
|
||||
dcs = self._session._call_method(vim_util,
|
||||
"continue_to_get_objects",
|
||||
token)
|
||||
else:
|
||||
break
|
||||
|
||||
def get_datacenter_ref_and_name(self, ds_ref):
|
||||
"""Get the datacenter name and the reference."""
|
||||
dc_info = self._datastore_dc_mapping.get(ds_ref.value)
|
||||
if not dc_info:
|
||||
dcs = self._session._call_method(vim_util, "get_objects",
|
||||
"Datacenter", ["name", "datastore", "vmFolder"])
|
||||
self._update_datacenter_cache_from_objects(dcs)
|
||||
dc_info = self._datastore_dc_mapping.get(ds_ref.value)
|
||||
return dc_info
|
||||
|
|
Loading…
Reference in New Issue