def receive_image(self, image_id, datastore_id, imported_vm_name, metadata, manifest): """ Creates an image using the data from the imported vm. This is run at the destination host end of the host-to-host image transfer. """ vm = self._vim_client.get_vm_obj_in_cache(imported_vm_name) vmx_os_path = datastore_to_os_path(vm.config.files.vmPathName) vm_dir = os.path.dirname(vmx_os_path) vm.Unregister() if self.check_image_dir(image_id, datastore_id): self._logger.info("Image %s on datastore %s already exists" % (image_id, datastore_id)) raise DiskAlreadyExistException() self._move_image(image_id, datastore_id, vm_dir) # Save raw manifest manifest_path = os_image_manifest_path(datastore_id, image_id) with open(manifest_path, "w") as f: f.write(manifest) # Save raw metadata metadata_path = os_metadata_path(datastore_id, image_id, IMAGE_FOLDER_NAME) with open(metadata_path, "w") as f: f.write(metadata) self._create_image_timestamp_file_from_ids(datastore_id, image_id)
def _create_tmp_image(self, source_datastore, source_id, dest_datastore, dest_id): """ Copy an image into a temp location. 1. Lock a tmp image destination file with an exclusive lock. This is to prevent the GC thread from garbage collecting directories that are actively being used. The temp directory name contains a random UUID to prevent collisions with concurrent copies 2. Create the temp directory. 3. Copy the metadata file over. 4. Copy the vmdk over. @return the tmp image directory on success. """ source = vmdk_path(source_datastore, source_id, IMAGE_FOLDER_NAME) temp_dest = tmp_image_path(dest_datastore, dest_id) ds_type = self._get_datastore_type(dest_datastore) tmp_image_dir_path = os.path.dirname(datastore_to_os_path(temp_dest)) # Try grabbing the lock on the temp directory if it fails # (very unlikely) someone else is copying an image just retry # later. with FileBackedLock(tmp_image_dir_path, ds_type): source_meta = os_metadata_path(source_datastore, source_id, IMAGE_FOLDER_NAME) # Create the temp directory mkdir_p(tmp_image_dir_path) # Copy the metadata file if it exists. if os.path.exists(source_meta): try: dest_meta = os.path.join(tmp_image_dir_path, metadata_filename(dest_id)) shutil.copy(source_meta, dest_meta) except: self._logger.exception("Failed to copy metadata file %s", source_meta) raise # Copy the manifest file if it exists source_manifest = os_image_manifest_path(source_datastore, source_id) if os.path.exists(source_manifest): try: dest_manifest = os.path.join(tmp_image_dir_path, manifest_filename(dest_id)) shutil.copy(source_manifest, dest_manifest) except: # Swallow it. Not critical. pass # Create the timestamp file self._create_image_timestamp_file(tmp_image_dir_path) _vd_spec = self._prepare_virtual_disk_spec( vim.VirtualDiskManager.VirtualDiskType.thin, vim.VirtualDiskManager.VirtualDiskAdapterType.lsiLogic ) self._manage_disk( vim.VirtualDiskManager.CopyVirtualDisk_Task, sourceName=source, destName=temp_dest, destSpec=_vd_spec ) return tmp_image_dir_path
def _read_metadata(self, image_datastore, image_id): try: # Transfer raw manifest manifest_path = os_image_manifest_path(image_datastore, image_id) with open(manifest_path) as f: manifest = f.read() # Transfer raw metadata metadata_path = os_metadata_path(image_datastore, image_id, IMAGE_FOLDER_NAME) with open(metadata_path, 'r') as f: metadata = f.read() return manifest, metadata except: self._logger.exception("Failed to read metadata") raise
def get_image_manifest(self, image_id): # This is a shortcut for ttylinux. ttylinux doesn't have manifest file. if image_id == "ttylinux": return ImageType.CLOUD, ImageReplication.EAGER # TODO(mmutsuzaki) We should iterate over all the image datastores # until we find one that has the image. image_ds = list(self._ds_manager.image_datastores())[0] manifest_path = os_image_manifest_path(image_ds, image_id) if not os.path.isfile(manifest_path): self._logger.info("Manifest file %s not found" % manifest_path) return None, None self._logger.info("Loading manifest %s" % manifest_path) data = self._load_json(manifest_path) type = ImageType._NAMES_TO_VALUES[data["imageType"]] replication = ImageReplication._NAMES_TO_VALUES[data["imageReplication"]] return type, replication
def get_image_manifest(self, image_id): # This is a shortcut for ttylinux. ttylinux doesn't have manifest file. if image_id == "ttylinux": return ImageType.CLOUD, ImageReplication.EAGER # TODO(mmutsuzaki) We should iterate over all the image datastores # until we find one that has the image. image_ds = list(self._ds_manager.image_datastores())[0] manifest_path = os_image_manifest_path(image_ds, image_id) if not os.path.isfile(manifest_path): self._logger.info("Manifest file %s not found" % manifest_path) return None, None self._logger.info("Loading manifest %s" % manifest_path) data = self._load_json(manifest_path) type = ImageType._NAMES_TO_VALUES[data["imageType"]] replication = ImageReplication._NAMES_TO_VALUES[ data["imageReplication"]] return type, replication
def test_os_image_manifest_path(self, datastore, image_id, expected): assert_that(os_image_manifest_path(datastore, image_id), equal_to(expected))