def _start_transfer(read_handle, write_handle, timeout_secs): # read_handle/write_handle could be an NFC lease, so we need to # periodically update its progress read_updater = _create_progress_updater(read_handle) write_updater = _create_progress_updater(write_handle) timer = timeout.Timeout(timeout_secs) try: while True: data = read_handle.read(CHUNK_SIZE) if not data: break write_handle.write(data) except timeout.Timeout as excep: msg = (_('Timeout, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) except Exception as excep: msg = (_('Error, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) finally: timer.cancel() if read_updater: read_updater.stop() if write_updater: write_updater.stop() read_handle.close() write_handle.close()
def _start_transfer(read_handle, write_handle, timeout_secs): # write_handle could be an NFC lease, so we need to periodically # update its progress update_cb = getattr(write_handle, 'update_progress', lambda: None) updater = loopingcall.FixedIntervalLoopingCall(update_cb) timer = timeout.Timeout(timeout_secs) try: updater.start(interval=NFC_LEASE_UPDATE_PERIOD) while True: data = read_handle.read(CHUNK_SIZE) if not data: break write_handle.write(data) except timeout.Timeout as excep: msg = (_('Timeout, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) except Exception as excep: msg = (_('Error, read_handle: "%(src)s", write_handle: "%(dest)s"') % {'src': read_handle, 'dest': write_handle}) LOG.exception(msg) raise exceptions.ImageTransferException(msg, excep) finally: timer.cancel() updater.stop() read_handle.close() write_handle.close()
def _inner(): """Task performing the file read-write operation.""" self._running = True while self._running: try: data = self._input_file.read(rw_handles.READ_CHUNKSIZE) if not data: LOG.debug("File read-write task is done.") self.stop() self._done.send(True) self._output_file.write(data) # update lease progress if applicable if hasattr(self._input_file, "update_progress"): self._input_file.update_progress() if hasattr(self._output_file, "update_progress"): self._output_file.update_progress() greenthread.sleep(FILE_READ_WRITE_TASK_SLEEP_TIME) except Exception as excep: self.stop() excep_msg = _("Error occurred during file read-write " "task.") LOG.exception(excep_msg) excep = exceptions.ImageTransferException(excep_msg, excep) self._done.send_exception(excep)
def get_imported_vm(self): """"Get managed object reference of the VM created for import. :raises: VimException """ if self._get_progress() < 100: excep_msg = _("Incomplete VMDK upload to %s.") % self._url LOG.exception(excep_msg) raise exceptions.ImageTransferException(excep_msg) return self._vm_ref
def download_stream_optimized_image(context, timeout_secs, image_service, image_id, **kwargs): """Download stream optimized image from image service to VMware server. :param context: image service write context :param timeout_secs: time in seconds to wait for the download to complete :param image_service: image service handle :param image_id: ID of the image to be downloaded :param kwargs: keyword arguments to configure the destination VMDK write handle :returns: managed object reference of the VM created for import to VMware server :raises: VimException, VimFaultException, VimAttributeException, VimSessionOverLoadException, VimConnectionException, ImageTransferException, ValueError """ metadata = image_service.show(context, image_id) container_format = metadata.get('container_format') LOG.debug( "Downloading image: %(id)s (container: %(container)s) from image" " service as a stream optimized file.", { 'id': image_id, 'container': container_format }) # TODO(vbala) catch specific exceptions raised by download call read_iter = image_service.download(context, image_id) read_handle = rw_handles.ImageReadHandle(read_iter) if container_format == 'ova': read_handle = _get_vmdk_handle(read_handle) if read_handle is None: raise exceptions.ImageTransferException( _("No vmdk found in the OVA image %s.") % image_id) imported_vm = download_stream_optimized_data(context, timeout_secs, read_handle, **kwargs) LOG.debug( "Downloaded image: %s from image service as a stream " "optimized file.", image_id) return imported_vm
def _start_transfer(context, timeout_secs, read_file_handle, max_data_size, write_file_handle=None, image_service=None, image_id=None, image_meta=None): """Start the image transfer. The image reader reads the data from the image source and writes to the blocking queue. The image source is always a file handle (VmdkReadHandle or ImageReadHandle); therefore, a FileReadWriteTask is created for this transfer. The image writer reads the data from the blocking queue and writes it to the image destination. The image destination is either a file or VMDK in VMware datastore or an image in the image service. If the destination is a file or VMDK in VMware datastore, the method creates a FileReadWriteTask which reads from the blocking queue and writes to either FileWriteHandle or VmdkWriteHandle. In the case of image service as the destination, an instance of ImageWriter task is created which reads from the blocking queue and writes to the image service. :param context: write context needed for the image service :param timeout_secs: time in seconds to wait for the transfer to complete :param read_file_handle: handle to read data from :param max_data_size: maximum transfer size :param write_file_handle: handle to write data to; if this is None, then param image_service and param image_id should be set. :param image_service: image service handle :param image_id: ID of the image in the image service :param image_meta: image meta-data :raises: ImageTransferException, ValueError """ # Create the blocking queue blocking_queue = BlockingQueue(BLOCKING_QUEUE_SIZE, max_data_size) # Create the image reader reader = FileReadWriteTask(read_file_handle, blocking_queue) # Create the image writer if write_file_handle: # File or VMDK in VMware datastore is the image destination writer = FileReadWriteTask(blocking_queue, write_file_handle) elif image_service and image_id: # Image service image is the destination writer = ImageWriter(context, blocking_queue, image_service, image_id, image_meta) else: excep_msg = _("No image destination given.") LOG.error(excep_msg) raise ValueError(excep_msg) # Start the reader and writer LOG.debug("Starting image transfer with reader: %(reader)s and writer: " "%(writer)s", {'reader': reader, 'writer': writer}) reader.start() writer.start() timer = timeout.Timeout(timeout_secs) try: # Wait for the reader and writer to complete reader.wait() writer.wait() except (timeout.Timeout, exceptions.ImageTransferException) as excep: excep_msg = (_("Error occurred during image transfer with reader: " "%(reader)s and writer: %(writer)s") % {'reader': reader, 'writer': writer}) LOG.exception(excep_msg) reader.stop() writer.stop() if isinstance(excep, exceptions.ImageTransferException): raise raise exceptions.ImageTransferException(excep_msg, excep) finally: timer.cancel() read_file_handle.close() if write_file_handle: write_file_handle.close()
def _inner(): """Task performing the image write operation. This method performs image data transfer through an update call. After the update, it waits until the image state becomes 'active', 'killed' or unknown. If the final state is not 'active' an instance of ImageTransferException is thrown. :raises: ImageTransferException """ LOG.debug("Calling image service update on image: %(image)s " "with meta: %(meta)s", {'image': self._image_id, 'meta': self._image_meta}) try: self._image_service.update(self._context, self._image_id, self._image_meta, data=self._input_file) self._running = True while self._running: LOG.debug("Retrieving status of image: %s.", self._image_id) image_meta = self._image_service.show(self._context, self._image_id) image_status = image_meta.get('status') if image_status == 'active': self.stop() LOG.debug("Image: %s is now active.", self._image_id) self._done.send(True) elif image_status == 'killed': self.stop() excep_msg = (_("Image: %s is in killed state.") % self._image_id) LOG.error(excep_msg) excep = exceptions.ImageTransferException(excep_msg) self._done.send_exception(excep) elif image_status in ['saving', 'queued']: LOG.debug("Image: %(image)s is in %(state)s state; " "sleeping for %(sleep)d seconds.", {'image': self._image_id, 'state': image_status, 'sleep': IMAGE_SERVICE_POLL_INTERVAL}) greenthread.sleep(IMAGE_SERVICE_POLL_INTERVAL) else: self.stop() excep_msg = (_("Image: %(image)s is in unknown " "state: %(state)s.") % {'image': self._image_id, 'state': image_status}) LOG.error(excep_msg) excep = exceptions.ImageTransferException(excep_msg) self._done.send_exception(excep) except Exception as excep: self.stop() excep_msg = (_("Error occurred while writing image: %s") % self._image_id) LOG.exception(excep_msg) excep = exceptions.ImageTransferException(excep_msg, excep) self._done.send_exception(excep)