def test_split_datastore_path(self): test1 = '[datastore1] myfolder/mysubfolder/myvm.vmx' (datastore, folder, file_name) = volumeops.split_datastore_path(test1) self.assertEqual(datastore, 'datastore1') self.assertEqual(folder, 'myfolder/mysubfolder/') self.assertEqual(file_name, 'myvm.vmx') test2 = '[datastore2 ] myfolder/myvm.vmdk' (datastore, folder, file_name) = volumeops.split_datastore_path(test2) self.assertEqual(datastore, 'datastore2') self.assertEqual(folder, 'myfolder/') self.assertEqual(file_name, 'myvm.vmdk') test3 = 'myfolder/myvm.vmdk' self.assertRaises(IndexError, volumeops.split_datastore_path, test3)
def test_split_datastore_path(self): test1 = '[datastore1] myfolder/mysubfolder/myvm.vmx' (datastore, folder, file_name) = volumeops.split_datastore_path(test1) self.assertEqual(datastore, 'datastore1') self.assertEqual(folder, 'myfolder/mysubfolder/') self.assertEqual(file_name, 'myvm.vmx') test2 = '[datastore2 ] myfolder/myvm.vmdk' (datastore, folder, file_name) = volumeops.split_datastore_path(test2) self.assertEqual(datastore, 'datastore2') self.assertEqual(folder, 'myfolder/') self.assertEqual(file_name, 'myvm.vmdk') test3 = 'myfolder/myvm.vmdk' self.assertRaises(IndexError, volumeops.split_datastore_path, test3)
def test_split_datastore_path(self): test1 = "[datastore1] myfolder/mysubfolder/myvm.vmx" (datastore, folder, file_name) = volumeops.split_datastore_path(test1) self.assertEqual(datastore, "datastore1") self.assertEqual(folder, "myfolder/mysubfolder/") self.assertEqual(file_name, "myvm.vmx") test2 = "[datastore2 ] myfolder/myvm.vmdk" (datastore, folder, file_name) = volumeops.split_datastore_path(test2) self.assertEqual(datastore, "datastore2") self.assertEqual(folder, "myfolder/") self.assertEqual(file_name, "myvm.vmdk") test3 = "myfolder/myvm.vmdk" self.assertRaises(IndexError, volumeops.split_datastore_path, test3)
def _clone_backing_by_copying(self, volume, backing): """Creates volume clone. Here we copy the backing on a datastore under the host and then register the copied backing to the inventory. It is assumed here that all the source backing files are in the same folder on the datastore. :param volume: New Volume object :param backing: Reference to backing entity that must be cloned :return: Reference to the cloned backing """ src_path_name = self.volumeops.get_path_name(backing) (datastore_name, folder_path, filename) = volumeops.split_datastore_path(src_path_name) # Pick a datastore where to create the full clone under same host host = self.volumeops.get_host(backing) (datastores, resource_pool) = self.volumeops.get_dss_rp(host) (folder, summary) = self._get_folder_ds_summary(volume['size'], resource_pool, datastores) src_path = '[%s] %s' % (datastore_name, folder_path) dest_path = '[%s] %s/' % (summary.name, volume['name']) # Copy source backing files to a destination location self.volumeops.copy_backing(src_path, dest_path) # Register the backing to the inventory dest_path_name = '%s%s' % (dest_path, filename) clone = self.volumeops.register_backing(dest_path_name, volume['name'], folder, resource_pool) LOG.info(_("Successfully cloned new backing: %s.") % clone) return clone
def _clone_backing_by_copying(self, volume, backing): """Creates volume clone. Here we copy the backing on a datastore under the host and then register the copied backing to the inventory. It is assumed here that all the source backing files are in the same folder on the datastore. :param volume: New Volume object :param backing: Reference to backing entity that must be cloned :return: Reference to the cloned backing """ src_path_name = self.volumeops.get_path_name(backing) (datastore_name, folder_path, filename) = volumeops.split_datastore_path(src_path_name) # Pick a datastore where to create the full clone under same host host = self.volumeops.get_host(backing) (datastores, resource_pool) = self.volumeops.get_dss_rp(host) (folder, summary) = self._get_folder_ds_summary(volume['size'], resource_pool, datastores) src_path = '[%s] %s' % (datastore_name, folder_path) dest_path = '[%s] %s/' % (summary.name, volume['name']) # Copy source backing files to a destination location self.volumeops.copy_backing(src_path, dest_path) # Register the backing to the inventory dest_path_name = '%s%s' % (dest_path, filename) clone = self.volumeops.register_backing(dest_path_name, volume['name'], folder, resource_pool) LOG.info(_("Successfully cloned new backing: %s.") % clone) return clone
def _get_ds_name_flat_vmdk_path(self, backing, vol_name): """Get datastore name and folder path of the flat VMDK of the backing. :param backing: Reference to the backing entity :param vol_name: Name of the volume :return: datastore name and folder path of the VMDK of the backing """ file_path_name = self.volumeops.get_path_name(backing) (datastore_name, folder_path, _) = volumeops.split_datastore_path(file_path_name) flat_vmdk_path = '%s%s-flat.vmdk' % (folder_path, vol_name) return (datastore_name, flat_vmdk_path)
def _get_ds_name_flat_vmdk_path(self, backing, vol_name): """Get datastore name and folder path of the flat VMDK of the backing. :param backing: Reference to the backing entity :param vol_name: Name of the volume :return: datastore name and folder path of the VMDK of the backing """ file_path_name = self.volumeops.get_path_name(backing) (datastore_name, folder_path, _) = volumeops.split_datastore_path(file_path_name) flat_vmdk_path = '%s%s-flat.vmdk' % (folder_path, vol_name) return (datastore_name, flat_vmdk_path)
def copy_volume_to_image(self, context, volume, image_service, image_meta): """Creates glance image from volume. Steps followed are: 1. Get the name of the vmdk file which the volume points to right now. Can be a chain of snapshots, so we need to know the last in the chain. 2. Create the snapshot. A new vmdk is created which the volume points to now. The earlier vmdk becomes read-only. 3. Call CopyVirtualDisk which coalesces the disk chain to form a single vmdk, rather a .vmdk metadata file and a -flat.vmdk disk data file. 4. Now upload the -flat.vmdk file to the image store. 5. Delete the coalesced .vmdk and -flat.vmdk created. """ LOG.debug(_("Copy Volume: %s to new image.") % volume['name']) VMwareEsxVmdkDriver._validate_disk_format(image_meta['disk_format']) backing = self.volumeops.get_backing(volume['name']) if not backing: LOG.info(_("Backing not found, creating for volume: %s") % volume['name']) backing = self._create_backing_in_inventory(volume) vmdk_file_path = self.volumeops.get_vmdk_path(backing) datastore_name = volumeops.split_datastore_path(vmdk_file_path)[0] # Create a snapshot image_id = image_meta['id'] snapshot_name = "snapshot-%s" % image_id self.volumeops.create_snapshot(backing, snapshot_name, None, True) # Create a copy of the snapshotted vmdk into a tmp file tmp_vmdk_file_path = '[%s] %s.vmdk' % (datastore_name, image_id) host = self.volumeops.get_host(backing) datacenter = self.volumeops.get_dc(host) self.volumeops.copy_vmdk_file(datacenter, vmdk_file_path, tmp_vmdk_file_path) try: # Upload image from copy of -flat.vmdk timeout = self.configuration.vmware_image_transfer_timeout_secs host_ip = self.configuration.vmware_host_ip datacenter_name = self.volumeops.get_entity_name(datacenter) cookies = self.session.vim.client.options.transport.cookiejar flat_vmdk_copy = '%s-flat.vmdk' % image_id vmware_images.upload_image(context, timeout, image_service, image_meta['id'], volume['project_id'], host=host_ip, data_center_name=datacenter_name, datastore_name=datastore_name, cookies=cookies, file_path=flat_vmdk_copy, snapshot_name=image_meta['name'], image_version=1) LOG.info(_("Done copying volume %(vol)s to a new image %(img)s") % {'vol': volume['name'], 'img': image_meta['name']}) finally: # Delete the coalesced .vmdk and -flat.vmdk created self.volumeops.delete_vmdk_file(tmp_vmdk_file_path, datacenter)
def copy_volume_to_image(self, context, volume, image_service, image_meta): """Creates glance image from volume. Upload of only available volume is supported. Steps followed are: 1. Get the name of the vmdk file which the volume points to right now. Can be a chain of snapshots, so we need to know the last in the chain. 2. Call CopyVirtualDisk which coalesces the disk chain to form a single vmdk, rather a .vmdk metadata file and a -flat.vmdk disk data file. 3. Now upload the -flat.vmdk file to the image store. 4. Delete the coalesced .vmdk and -flat.vmdk created. """ if volume['instance_uuid'] or volume['attached_host']: msg = _("Upload to glance of attached volume is not supported.") LOG.error(msg) raise exception.InvalidVolume(msg) LOG.debug(_("Copy Volume: %s to new image.") % volume['name']) VMwareEsxVmdkDriver._validate_disk_format(image_meta['disk_format']) backing = self.volumeops.get_backing(volume['name']) if not backing: LOG.info( _("Backing not found, creating for volume: %s") % volume['name']) backing = self._create_backing_in_inventory(volume) vmdk_file_path = self.volumeops.get_vmdk_path(backing) datastore_name = volumeops.split_datastore_path(vmdk_file_path)[0] # Create a copy of the vmdk into a tmp file image_id = image_meta['id'] tmp_vmdk_file_path = '[%s] %s.vmdk' % (datastore_name, image_id) host = self.volumeops.get_host(backing) datacenter = self.volumeops.get_dc(host) self.volumeops.copy_vmdk_file(datacenter, vmdk_file_path, tmp_vmdk_file_path) try: # Upload image from copy of -flat.vmdk timeout = self.configuration.vmware_image_transfer_timeout_secs host_ip = self.configuration.vmware_host_ip datacenter_name = self.volumeops.get_entity_name(datacenter) cookies = self.session.vim.client.options.transport.cookiejar flat_vmdk_copy = '%s-flat.vmdk' % image_id vmware_images.upload_image(context, timeout, image_service, image_meta['id'], volume['project_id'], host=host_ip, data_center_name=datacenter_name, datastore_name=datastore_name, cookies=cookies, file_path=flat_vmdk_copy, snapshot_name=image_meta['name'], image_version=1) LOG.info( _("Done copying volume %(vol)s to a new image %(img)s") % { 'vol': volume['name'], 'img': image_meta['name'] }) finally: # Delete the coalesced .vmdk and -flat.vmdk created self.volumeops.delete_vmdk_file(tmp_vmdk_file_path, datacenter)