def copy_volume_to_image(self, context, volume, image_service, image_meta): """Creates glance image from volume. Upload of only available volume is supported. The uploaded glance image has a vmdk disk type of "streamOptimized" that can only be downloaded using the HttpNfc API. 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. Use Nfc APIs to upload the contents of the vmdk file to glance. """ # if volume is attached raise exception 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) # validate disk format is vmdk LOG.debug(_("Copy Volume: %s to new image.") % volume['name']) VMwareEsxVmdkDriver._validate_disk_format(image_meta['disk_format']) # get backing vm of volume and its vmdk path 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) # Upload image from vmdk timeout = self.configuration.vmware_image_transfer_timeout_secs host_ip = self.configuration.vmware_host_ip vmware_images.upload_image(context, timeout, image_service, image_meta['id'], volume['project_id'], session=self.session, host=host_ip, vm=backing, vmdk_file_path=vmdk_file_path, vmdk_size=volume['size'] * units.GiB, image_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'] })
def copy_volume_to_image(self, context, volume, image_service, image_meta): """Creates glance image from volume. Upload of only available volume is supported. The uploaded glance image has a vmdk disk type of "streamOptimized" that can only be downloaded using the HttpNfc API. 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. Use Nfc APIs to upload the contents of the vmdk file to glance. """ # if volume is attached raise exception 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) # validate disk format is vmdk LOG.debug(_("Copy Volume: %s to new image.") % volume['name']) VMwareEsxVmdkDriver._validate_disk_format(image_meta['disk_format']) # get backing vm of volume and its vmdk path 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) # Upload image from vmdk timeout = self.configuration.vmware_image_transfer_timeout_secs host_ip = self.configuration.vmware_host_ip vmware_images.upload_image(context, timeout, image_service, image_meta['id'], volume['project_id'], session=self.session, host=host_ip, vm=backing, vmdk_file_path=vmdk_file_path, vmdk_size=volume['size'] * units.GiB, image_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']})
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)