img_file, volume['name'], volume_id=None, share=share) cloned = True break else: LOG.info( _LI('Image will locally be converted to raw %s'), image_id) dst = '%s/%s' % (dir_path, volume['name']) image_utils.convert_image(img_path, dst, 'raw', run_as_root=run_as_root) data = image_utils.qemu_img_info(dst, run_as_root=run_as_root) if data.file_format != "raw": raise exception.InvalidResults( _("Converted to raw, but" " format is now %s") % data.file_format) else: cloned = True self._register_image_in_cache( volume, image_id) break return cloned def _post_clone_image(self, volume): """Do operations post image cloning.""" LOG.info(_LI('Performing post clone for %s'), volume['name']) vol_path = self.local_path(volume) if self._discover_file_till_timeout(vol_path): self._set_rw_permissions(vol_path) self._resize_image_file(vol_path, volume['size'])
def _copy_from_img_service(self, context, volume, image_service, image_id): """Copies from the image service using copy offload.""" LOG.debug("Trying copy from image service using copy offload.") image_loc = image_service.get_location(context, image_id) locations = self._construct_image_nfs_url(image_loc) src_ip = None selected_loc = None cloned = False # this will match the first location that has a valid IP on cluster for location in locations: conn, dr = self._check_get_nfs_path_segs(location) if conn: try: src_ip = self._get_ip_verify_on_cluster(conn.split(':')[0]) selected_loc = location break except exception.NotFound: pass if src_ip is None: raise exception.NotFound(_("Source host details not found.")) (__, ___, img_file) = selected_loc.rpartition('/') src_path = os.path.join(dr, img_file) dst_ip, vol_path = self._get_destination_ip_and_path(volume) share_path = vol_path.rsplit("/", 1)[0] dst_share = dst_ip + ':' + share_path # tmp file is required to deal with img formats tmp_img_file = six.text_type(uuid.uuid4()) col_path = self.configuration.netapp_copyoffload_tool_path img_info = image_service.show(context, image_id) self._check_share_can_hold_size(dst_share, img_info['size']) run_as_root = self._execute_as_root dst_dir = self._get_mount_point_for_share(dst_share) dst_img_local = os.path.join(dst_dir, tmp_img_file) try: dst_img_serv_path = os.path.join(share_path, tmp_img_file) # Always run copy offload as regular user, it's sufficient # and rootwrap doesn't allow copy offload to run as root # anyways. self._execute(col_path, src_ip, dst_ip, src_path, dst_img_serv_path, run_as_root=False, check_exit_code=0) self._discover_file_till_timeout(dst_img_local, timeout=120) LOG.debug('Copied image %(img)s to tmp file %(tmp)s.', { 'img': image_id, 'tmp': tmp_img_file }) dst_img_cache_local = os.path.join(dst_dir, 'img-cache-%s' % image_id) if img_info['disk_format'] == 'raw': LOG.debug('Image is raw %s.', image_id) self._clone_file_dst_exists(dst_share, tmp_img_file, volume['name'], dest_exists=True) self._move_nfs_file(dst_img_local, dst_img_cache_local) LOG.debug('Copied raw image %(img)s to volume %(vol)s.', { 'img': image_id, 'vol': volume['id'] }) else: LOG.debug('Image will be converted to raw %s.', image_id) img_conv = six.text_type(uuid.uuid4()) dst_img_conv_local = os.path.join(dst_dir, img_conv) # Checking against image size which is approximate check self._check_share_can_hold_size(dst_share, img_info['size']) try: image_utils.convert_image(dst_img_local, dst_img_conv_local, 'raw', run_as_root=run_as_root) data = image_utils.qemu_img_info(dst_img_conv_local, run_as_root=run_as_root) if data.file_format != "raw": raise exception.InvalidResults( _("Converted to raw, but format is now %s.") % data.file_format) else: self._clone_file_dst_exists(dst_share, img_conv, volume['name'], dest_exists=True) self._move_nfs_file(dst_img_conv_local, dst_img_cache_local) LOG.debug( 'Copied locally converted raw image' ' %(img)s to volume %(vol)s.', { 'img': image_id, 'vol': volume['id'] }) finally: if os.path.exists(dst_img_conv_local): self._delete_file_at_path(dst_img_conv_local) cloned = True finally: if os.path.exists(dst_img_local): self._delete_file_at_path(dst_img_local) return cloned
def _copy_from_img_service(self, context, volume, image_service, image_id): """Copies from the image service using copy offload.""" LOG.debug("Trying copy from image service using copy offload.") image_loc = image_service.get_location(context, image_id) image_loc = self._construct_image_nfs_url(image_loc) conn, dr = self._check_get_nfs_path_segs(image_loc) if conn: src_ip = self._get_ip_verify_on_cluster(conn.split(':')[0]) else: raise exception.NotFound(_("Source host details not found.")) (__, ___, img_file) = image_loc.rpartition('/') src_path = os.path.join(dr, img_file) dst_ip = self._get_ip_verify_on_cluster(self._get_host_ip( volume['id'])) # tmp file is required to deal with img formats tmp_img_file = six.text_type(uuid.uuid4()) col_path = self.configuration.netapp_copyoffload_tool_path img_info = image_service.show(context, image_id) dst_share = self._get_provider_location(volume['id']) self._check_share_can_hold_size(dst_share, img_info['size']) run_as_root = self._execute_as_root dst_dir = self._get_mount_point_for_share(dst_share) dst_img_local = os.path.join(dst_dir, tmp_img_file) try: # If src and dst share not equal if (('%s:%s' % (src_ip, dr)) != ('%s:%s' % (dst_ip, self._get_export_path(volume['id'])))): dst_img_serv_path = os.path.join( self._get_export_path(volume['id']), tmp_img_file) self._execute(col_path, src_ip, dst_ip, src_path, dst_img_serv_path, run_as_root=run_as_root, check_exit_code=0) else: self._clone_file_dst_exists(dst_share, img_file, tmp_img_file) self._discover_file_till_timeout(dst_img_local, timeout=120) LOG.debug('Copied image %(img)s to tmp file %(tmp)s.' % { 'img': image_id, 'tmp': tmp_img_file }) dst_img_cache_local = os.path.join(dst_dir, 'img-cache-%s' % image_id) if img_info['disk_format'] == 'raw': LOG.debug('Image is raw %s.', image_id) self._clone_file_dst_exists(dst_share, tmp_img_file, volume['name'], dest_exists=True) self._move_nfs_file(dst_img_local, dst_img_cache_local) LOG.debug('Copied raw image %(img)s to volume %(vol)s.' % { 'img': image_id, 'vol': volume['id'] }) else: LOG.debug('Image will be converted to raw %s.', image_id) img_conv = six.text_type(uuid.uuid4()) dst_img_conv_local = os.path.join(dst_dir, img_conv) # Checking against image size which is approximate check self._check_share_can_hold_size(dst_share, img_info['size']) try: image_utils.convert_image(dst_img_local, dst_img_conv_local, 'raw', run_as_root=run_as_root) data = image_utils.qemu_img_info(dst_img_conv_local, run_as_root=run_as_root) if data.file_format != "raw": raise exception.InvalidResults( _("Converted to raw, but format is now %s.") % data.file_format) else: self._clone_file_dst_exists(dst_share, img_conv, volume['name'], dest_exists=True) self._move_nfs_file(dst_img_conv_local, dst_img_cache_local) LOG.debug('Copied locally converted raw image' ' %(img)s to volume %(vol)s.' % { 'img': image_id, 'vol': volume['id'] }) finally: if os.path.exists(dst_img_conv_local): self._delete_file(dst_img_conv_local) self._post_clone_image(volume) finally: if os.path.exists(dst_img_local): self._delete_file(dst_img_local)