Merge "VMware: upload images to temporary directory"
This commit is contained in:
commit
1e74b8677a
@ -244,7 +244,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
||||
host_password='test_pass',
|
||||
cluster_name='test_cluster',
|
||||
use_linked_clone=False, group='vmware')
|
||||
self.flags(vnc_enabled=False)
|
||||
self.flags(vnc_enabled=False,
|
||||
image_cache_subdirectory_name='vmware_base')
|
||||
self.user_id = 'fake'
|
||||
self.project_id = 'fake'
|
||||
self.node_name = 'test_url'
|
||||
@ -404,18 +405,21 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
||||
|
||||
self._create_vm()
|
||||
inst_file_path = '[%s] %s/fake_name.vmdk' % (self.ds, self.uuid)
|
||||
cache_file_path = '[%s] vmware_base/fake_image_uuid.vmdk' % self.ds
|
||||
cache = ('[%s] vmware_base/fake_image_uuid/fake_image_uuid.vmdk' %
|
||||
self.ds)
|
||||
self.assertTrue(vmwareapi_fake.get_file(inst_file_path))
|
||||
self.assertTrue(vmwareapi_fake.get_file(cache_file_path))
|
||||
self.assertTrue(vmwareapi_fake.get_file(cache))
|
||||
|
||||
def test_cache_dir_disk_created(self):
|
||||
"""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 = '[%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))
|
||||
file = ('[%s] vmware_base/fake_image_uuid/fake_image_uuid.vmdk' %
|
||||
self.ds)
|
||||
root = ('[%s] vmware_base/fake_image_uuid/fake_image_uuid.80.vmdk' %
|
||||
self.ds)
|
||||
self.assertTrue(vmwareapi_fake.get_file(file))
|
||||
self.assertTrue(vmwareapi_fake.get_file(root))
|
||||
|
||||
def test_spawn(self):
|
||||
self._create_vm()
|
||||
@ -457,8 +461,11 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
||||
self.wait_task = self.conn._session._wait_for_task
|
||||
self.call_method = self.conn._session._call_method
|
||||
self.task_ref = None
|
||||
cached_image = '[%s] vmware_base/fake_image_uuid.80.vmdk' % self.ds
|
||||
tmp_file = '[%s] vmware_base/fake_image_uuid.80-flat.vmdk' % self.ds
|
||||
id = 'fake_image_uuid'
|
||||
cached_image = '[%s] vmware_base/%s/%s.80.vmdk' % (self.ds,
|
||||
id, id)
|
||||
tmp_file = '[%s] vmware_base/%s/%s.80-flat.vmdk' % (self.ds,
|
||||
id, id)
|
||||
|
||||
def fake_wait_for_task(instance_uuid, task_ref):
|
||||
if task_ref == self.task_ref:
|
||||
@ -1164,6 +1171,7 @@ class VMwareAPIHostTestCase(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(VMwareAPIHostTestCase, self).setUp()
|
||||
self.flags(image_cache_subdirectory_name='vmware_base')
|
||||
self.flags(host_ip='test_url',
|
||||
host_username='test_username',
|
||||
host_password='test_pass', group='vmware')
|
||||
@ -1221,7 +1229,8 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
|
||||
cluster_name2 = 'test_cluster2'
|
||||
self.flags(cluster_name=[cluster_name, cluster_name2],
|
||||
task_poll_interval=10, datastore_regex='.*', group='vmware')
|
||||
self.flags(vnc_enabled=False)
|
||||
self.flags(vnc_enabled=False,
|
||||
image_cache_subdirectory_name='vmware_base')
|
||||
vmwareapi_fake.reset(vc=True)
|
||||
self.conn = driver.VMwareVCDriver(None, False)
|
||||
self.node_name = self.conn._resources.keys()[0]
|
||||
@ -1343,11 +1352,11 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
|
||||
# Check calls for delete vmdk and -flat.vmdk pair
|
||||
self.conn._vmops._delete_datastore_file(
|
||||
mox.IgnoreArg(),
|
||||
"[%s] vmware-tmp/%s-flat.vmdk" % (self.ds, uuid_str),
|
||||
"[%s] vmware_temp/%s-flat.vmdk" % (self.ds, uuid_str),
|
||||
mox.IgnoreArg()).AndReturn(None)
|
||||
self.conn._vmops._delete_datastore_file(
|
||||
mox.IgnoreArg(),
|
||||
"[%s] vmware-tmp/%s.vmdk" % (self.ds, uuid_str),
|
||||
"[%s] vmware_temp/%s.vmdk" % (self.ds, uuid_str),
|
||||
mox.IgnoreArg()).AndReturn(None)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
@ -254,10 +254,11 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
||||
'backing': {
|
||||
'datastore': {
|
||||
"summary.type": "VMFS",
|
||||
"summary.freeSpace": 536870912000,
|
||||
"summary.capacity": 1099511627776,
|
||||
"summary.accessible":true,
|
||||
"summary.name": "fake-ds"
|
||||
"summary.name": "fake-ds",
|
||||
"summary.capacity": 1099511627776,
|
||||
"summary.freeSpace": 536870912000,
|
||||
"browser": ""
|
||||
},
|
||||
'fileName': '/tmp/foo.iso',
|
||||
'obj_name': 'ns0: VirtualCdromIsoBackingInfo'
|
||||
|
@ -544,6 +544,7 @@ class Datastore(ManagedObject):
|
||||
self.set("summary.capacity", capacity * unit.Gi)
|
||||
self.set("summary.freeSpace", free * unit.Gi)
|
||||
self.set("summary.accessible", True)
|
||||
self.set("browser", "")
|
||||
|
||||
|
||||
class HostNetworkSystem(ManagedObject):
|
||||
@ -1054,6 +1055,23 @@ class FakeVim(object):
|
||||
task_mdo = create_task(method, "error")
|
||||
return task_mdo.obj
|
||||
|
||||
def _move_file(self, method, *args, **kwargs):
|
||||
source = kwargs.get('sourceName')
|
||||
destination = kwargs.get('destinationName')
|
||||
new_files = []
|
||||
if source != destination:
|
||||
for file in _db_content.get("files"):
|
||||
if source in file:
|
||||
new_file = file.replace(source, destination)
|
||||
new_files.append(new_file)
|
||||
# if source is not a file then the children will also
|
||||
# be deleted
|
||||
_remove_file(source)
|
||||
for file in new_files:
|
||||
_add_file(file)
|
||||
task_mdo = create_task(method, "success")
|
||||
return task_mdo.obj
|
||||
|
||||
def _make_dir(self, method, *args, **kwargs):
|
||||
"""Creates a directory in the datastore."""
|
||||
ds_path = kwargs.get("name")
|
||||
@ -1181,6 +1199,9 @@ class FakeVim(object):
|
||||
elif attr_name == "SearchDatastore_Task":
|
||||
return lambda *args, **kwargs: self._search_ds(attr_name,
|
||||
*args, **kwargs)
|
||||
elif attr_name == "MoveDatastoreFile_Task":
|
||||
return lambda *args, **kwargs: self._move_file(attr_name,
|
||||
*args, **kwargs)
|
||||
elif attr_name == "MakeDirectory":
|
||||
return lambda *args, **kwargs: self._make_dir(attr_name,
|
||||
*args, **kwargs)
|
||||
|
@ -71,7 +71,6 @@ VMWARE_POWER_STATES = {
|
||||
'poweredOff': power_state.SHUTDOWN,
|
||||
'poweredOn': power_state.RUNNING,
|
||||
'suspended': power_state.SUSPENDED}
|
||||
VMWARE_PREFIX = 'vmware'
|
||||
|
||||
VMWARE_LINKED_CLONE = 'vmware_linked_clone'
|
||||
|
||||
@ -93,8 +92,8 @@ class VMwareVMOps(object):
|
||||
self._volumeops = volumeops
|
||||
self._cluster = cluster
|
||||
self._datastore_regex = datastore_regex
|
||||
self._instance_path_base = (VMWARE_PREFIX +
|
||||
CONF.image_cache_subdirectory_name)
|
||||
self._base_folder = CONF.image_cache_subdirectory_name
|
||||
self._tmp_folder = 'vmware_temp'
|
||||
self._default_root_device = 'vda'
|
||||
self._rescue_suffix = '-rescue'
|
||||
self._poll_rescue_last_ran = None
|
||||
@ -313,7 +312,7 @@ class VMwareVMOps(object):
|
||||
vnc_port = self._get_vnc_port(vm_ref)
|
||||
self._set_vnc_config(client_factory, instance, vnc_port)
|
||||
|
||||
def _create_virtual_disk():
|
||||
def _create_virtual_disk(folder, virtual_disk_path):
|
||||
"""Create a virtual disk of the size of flat vmdk file."""
|
||||
# Create a Virtual Disk of the size of the flat vmdk file. This is
|
||||
# done just to generate the meta-data file whose specifics
|
||||
@ -321,6 +320,12 @@ class VMwareVMOps(object):
|
||||
# storage adapter type.
|
||||
# Here we assume thick provisioning and lsiLogic for the adapter
|
||||
# type
|
||||
LOG.debug(_("Creating temporary folder for %(folder)s on "
|
||||
"datastore %(datastore)s."),
|
||||
{'folder': folder, 'datastore': data_store_name})
|
||||
self._mkdir(vm_util.build_datastore_path(data_store_name,
|
||||
folder),
|
||||
data_store_ref)
|
||||
LOG.debug(_("Creating Virtual Disk of size "
|
||||
"%(vmdk_file_size_in_kb)s KB and adapter type "
|
||||
"%(adapter_type)s on the ESX host local store "
|
||||
@ -336,7 +341,7 @@ class VMwareVMOps(object):
|
||||
self._session._get_vim(),
|
||||
"CreateVirtualDisk_Task",
|
||||
service_content.virtualDiskManager,
|
||||
name=uploaded_vmdk_path,
|
||||
name=virtual_disk_path,
|
||||
datacenter=dc_info.ref,
|
||||
spec=vmdk_create_spec)
|
||||
self._session._wait_for_task(instance['uuid'], vmdk_create_task)
|
||||
@ -348,9 +353,30 @@ class VMwareVMOps(object):
|
||||
"data_store_name": data_store_name},
|
||||
instance=instance)
|
||||
|
||||
def _fetch_image_on_esx_datastore():
|
||||
"""Fetch image from Glance to ESX datastore."""
|
||||
LOG.debug(_("Downloading image file data %(image_ref)s to the ESX "
|
||||
def _move_image_to_cache_folder(tmp_folder, base_folder):
|
||||
LOG.debug(_("Moving temporary folder %(tmp)s to cache "
|
||||
"folder %(cache)s."),
|
||||
{'tmp': tmp_folder, 'cache': base_folder})
|
||||
vmdk_move_task = self._session._call_method(
|
||||
self._session._get_vim(),
|
||||
"MoveDatastoreFile_Task",
|
||||
service_content.fileManager,
|
||||
sourceName=vm_util.build_datastore_path(data_store_name,
|
||||
tmp_folder),
|
||||
sourceDatacenter=dc_info.ref,
|
||||
destinationName=vm_util.build_datastore_path(data_store_name,
|
||||
base_folder),
|
||||
destinationDatacenter=dc_info.ref)
|
||||
# TODO(garyk): ensure that _wait_for_task raises an exception that
|
||||
# can be specifically treated here.
|
||||
try:
|
||||
self._session._wait_for_task(instance['uuid'], vmdk_move_task)
|
||||
except Exception as e:
|
||||
LOG.warning(_("File moving failed - %s"), e)
|
||||
|
||||
def _fetch_image_on_datastore():
|
||||
"""Fetch image from Glance to datastore."""
|
||||
LOG.debug(_("Downloading image file data %(image_ref)s to the "
|
||||
"data store %(data_store_name)s") %
|
||||
{'image_ref': instance['image_ref'],
|
||||
'data_store_name': data_store_name},
|
||||
@ -371,7 +397,7 @@ class VMwareVMOps(object):
|
||||
cookies=cookies,
|
||||
file_path=upload_vmdk_name)
|
||||
LOG.debug(_("Downloaded image file data %(image_ref)s to "
|
||||
"%(upload_vmdk_name)s on the ESX data store "
|
||||
"%(upload_vmdk_name)s on the data store "
|
||||
"%(data_store_name)s") %
|
||||
{'image_ref': instance['image_ref'],
|
||||
'upload_vmdk_name': upload_vmdk_name,
|
||||
@ -421,8 +447,8 @@ class VMwareVMOps(object):
|
||||
image_linked_clone,
|
||||
CONF.vmware.use_linked_clone
|
||||
)
|
||||
upload_folder = self._instance_path_base
|
||||
upload_name = instance['image_ref']
|
||||
upload_folder = '%s/%s' % (self._base_folder, upload_name)
|
||||
|
||||
# The vmdk meta-data file
|
||||
uploaded_vmdk_name = "%s/%s.vmdk" % (upload_folder, upload_name)
|
||||
@ -435,6 +461,11 @@ class VMwareVMOps(object):
|
||||
if not (self._check_if_folder_file_exists(
|
||||
data_store_ref, data_store_name,
|
||||
upload_folder, upload_name + ".vmdk")):
|
||||
# Upload will be done to the self._tmp_folder and then moved
|
||||
# to the self._base_folder
|
||||
tmp_upload_folder = '%s/%s' % (self._tmp_folder,
|
||||
uuidutils.generate_uuid())
|
||||
upload_folder = '%s/%s' % (tmp_upload_folder, upload_name)
|
||||
|
||||
# Naming the VM files in correspondence with the VM instance
|
||||
# The flat vmdk file name
|
||||
@ -450,23 +481,33 @@ class VMwareVMOps(object):
|
||||
sparse_uploaded_vmdk_path = vm_util.build_datastore_path(
|
||||
data_store_name,
|
||||
sparse_uploaded_vmdk_name)
|
||||
|
||||
vmdk_name = "%s/%s.vmdk" % (upload_folder, upload_name)
|
||||
vmdk_path = vm_util.build_datastore_path(data_store_name,
|
||||
vmdk_name)
|
||||
if disk_type != "sparse":
|
||||
# Create a flat virtual disk and retain the metadata file.
|
||||
_create_virtual_disk()
|
||||
_create_virtual_disk(upload_folder, vmdk_path)
|
||||
self._delete_datastore_file(instance,
|
||||
flat_uploaded_vmdk_path,
|
||||
dc_info.ref)
|
||||
|
||||
_fetch_image_on_esx_datastore()
|
||||
_fetch_image_on_datastore()
|
||||
|
||||
if disk_type == "sparse":
|
||||
# Copy the sparse virtual disk to a thin virtual disk.
|
||||
disk_type = "thin"
|
||||
_copy_virtual_disk(sparse_uploaded_vmdk_path,
|
||||
uploaded_vmdk_path)
|
||||
_copy_virtual_disk(sparse_uploaded_vmdk_path, vmdk_path)
|
||||
self._delete_datastore_file(instance,
|
||||
sparse_uploaded_vmdk_path,
|
||||
dc_info.ref)
|
||||
|
||||
base_folder = '%s/%s' % (self._base_folder, upload_name)
|
||||
_move_image_to_cache_folder(upload_folder, base_folder)
|
||||
self._delete_datastore_file(instance,
|
||||
vm_util.build_datastore_path(data_store_name,
|
||||
tmp_upload_folder),
|
||||
dc_info.ref)
|
||||
else:
|
||||
# linked clone base disk exists
|
||||
if disk_type == "sparse":
|
||||
@ -480,7 +521,7 @@ class VMwareVMOps(object):
|
||||
dest_folder = instance['uuid']
|
||||
dest_name = instance['name']
|
||||
dest_vmdk_name = "%s/%s.vmdk" % (dest_folder,
|
||||
dest_name)
|
||||
dest_name)
|
||||
dest_vmdk_path = vm_util.build_datastore_path(
|
||||
data_store_name, dest_vmdk_name)
|
||||
_copy_virtual_disk(uploaded_vmdk_path, dest_vmdk_path)
|
||||
@ -490,6 +531,7 @@ class VMwareVMOps(object):
|
||||
self._extend_virtual_disk(instance, root_gb_in_kb,
|
||||
root_vmdk_path, dc_info.ref)
|
||||
else:
|
||||
upload_folder = '%s/%s' % (self._base_folder, upload_name)
|
||||
root_vmdk_name = "%s/%s.%s.vmdk" % (upload_folder, upload_name,
|
||||
root_gb)
|
||||
root_vmdk_path = vm_util.build_datastore_path(data_store_name,
|
||||
@ -509,11 +551,16 @@ class VMwareVMOps(object):
|
||||
sourceDatacenter=dc_info.ref,
|
||||
destName=root_vmdk_path,
|
||||
destSpec=copy_spec)
|
||||
self._session._wait_for_task(instance['uuid'],
|
||||
vmdk_copy_task)
|
||||
try:
|
||||
self._session._wait_for_task(instance['uuid'],
|
||||
vmdk_copy_task)
|
||||
except Exception as e:
|
||||
LOG.warning(_("Root disk file creation "
|
||||
"failed - %s"), e)
|
||||
if root_gb_in_kb > vmdk_file_size_in_kb:
|
||||
self._extend_virtual_disk(instance, root_gb_in_kb,
|
||||
root_vmdk_path, dc_info.ref)
|
||||
root_vmdk_path,
|
||||
dc_info.ref)
|
||||
|
||||
# Attach the root disk to the VM.
|
||||
self._volumeops.attach_disk_to_vm(
|
||||
@ -737,10 +784,10 @@ class VMwareVMOps(object):
|
||||
"browser")
|
||||
# Check if the vmware-tmp folder exists or not. If not, create one
|
||||
tmp_folder_path = vm_util.build_datastore_path(datastore_name,
|
||||
"vmware-tmp")
|
||||
self._tmp_folder)
|
||||
if not self._path_exists(ds_browser, tmp_folder_path):
|
||||
self._mkdir(vm_util.build_datastore_path(datastore_name,
|
||||
"vmware-tmp"),
|
||||
self._tmp_folder),
|
||||
ds_ref)
|
||||
return ds_ref
|
||||
|
||||
@ -751,9 +798,9 @@ class VMwareVMOps(object):
|
||||
# name clashes.
|
||||
random_name = uuidutils.generate_uuid()
|
||||
dest_vmdk_file_path = vm_util.build_datastore_path(datastore_name,
|
||||
"vmware-tmp/%s.vmdk" % random_name)
|
||||
"%s/%s.vmdk" % (self._tmp_folder, random_name))
|
||||
dest_vmdk_data_file_path = vm_util.build_datastore_path(datastore_name,
|
||||
"vmware-tmp/%s-flat.vmdk" % random_name)
|
||||
"%s/%s-flat.vmdk" % (self._tmp_folder, random_name))
|
||||
dc_info = self.get_datacenter_ref_and_name(ds_ref)
|
||||
|
||||
def _copy_vmdk_content():
|
||||
@ -798,7 +845,7 @@ class VMwareVMOps(object):
|
||||
data_center_name=dc_info.name,
|
||||
datastore_name=datastore_name,
|
||||
cookies=cookies,
|
||||
file_path="vmware-tmp/%s-flat.vmdk" % random_name)
|
||||
file_path="%s/%s-flat.vmdk" % (self._tmp_folder, random_name))
|
||||
LOG.debug(_("Uploaded image %s") % image_id,
|
||||
instance=instance)
|
||||
|
||||
@ -1531,7 +1578,7 @@ class VMwareVMOps(object):
|
||||
self._session._call_method(self._session._get_vim(), "MakeDirectory",
|
||||
self._session._get_vim().get_service_content().fileManager,
|
||||
name=ds_path, datacenter=dc_info.ref,
|
||||
createParentDirectories=False)
|
||||
createParentDirectories=True)
|
||||
LOG.debug(_("Created directory with path %s") % ds_path)
|
||||
|
||||
def _check_if_folder_file_exists(self, ds_ref, ds_name,
|
||||
@ -1544,8 +1591,10 @@ class VMwareVMOps(object):
|
||||
folder_exists, file_exists = self._path_file_exists(ds_browser,
|
||||
folder_path,
|
||||
file_name)
|
||||
# Ensure that the cache folder exists
|
||||
if not folder_exists:
|
||||
self._mkdir(vm_util.build_datastore_path(ds_name, folder_name),
|
||||
self._mkdir(vm_util.build_datastore_path(ds_name,
|
||||
self._base_folder),
|
||||
ds_ref)
|
||||
|
||||
return file_exists
|
||||
|
Loading…
Reference in New Issue
Block a user