Merge "VMware: upload images to temporary directory"

This commit is contained in:
Jenkins 2014-01-19 06:31:20 +00:00 committed by Gerrit Code Review
commit 1e74b8677a
4 changed files with 120 additions and 40 deletions

View File

@ -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()

View File

@ -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'

View File

@ -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)

View File

@ -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":
@ -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)
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