def create_disk_from_image(self, context, instance, image_meta): """Creates a boot disk and links the specified image to it. If the specified image has not already been uploaded, an Image LU is created for it. A Disk LU is then created for the instance and linked to the Image LU. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. :param nova.objects.ImageMeta image_meta: The metadata of the image of the instance. :return: The backing pypowervm LU storage object that was created. """ LOG.info('SSP: Create boot disk from image %s.', image_meta.id, instance=instance) image_lu = tsk_cs.get_or_upload_image_lu( self._tier, pvm_u.sanitize_file_name_for_api( image_meta.name, prefix=DiskType.IMAGE + '_', suffix='_' + image_meta.checksum), random.choice(self._vios_uuids), IterableToFileAdapter( IMAGE_API.download(context, image_meta.id)), image_meta.size, upload_type=tsk_stg.UploadType.IO_STREAM) boot_lu_name = pvm_u.sanitize_file_name_for_api( instance.name, prefix=DiskType.BOOT + '_') LOG.info('SSP: Disk name is %s', boot_lu_name, instance=instance) return tsk_stg.crt_lu( self._tier, boot_lu_name, instance.flavor.root_gb, typ=pvm_stg.LUType.DISK, clone=image_lu)[1]
def _create_cfg_dr_iso(self, instance, injected_files, network_info, admin_pass=None): """Creates an ISO file that contains the injected files. Used for config drive. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param admin_pass: Optional password to inject for the VM. :return iso_path: The path to the ISO :return file_name: The file name for the ISO """ LOG.info("Creating config drive.", instance=instance) extra_md = {} if admin_pass is not None: extra_md['admin_pass'] = admin_pass # Sanitize the vifs for the network config network_info = self._sanitize_network_info(network_info) inst_md = instance_metadata.InstanceMetadata(instance, content=injected_files, extra_md=extra_md, network_info=network_info) if not os.path.exists(_VOPT_TMPDIR): os.mkdir(_VOPT_TMPDIR) file_name = pvm_util.sanitize_file_name_for_api( instance.name, prefix='cfg_', suffix='.iso', max_len=pvm_const.MaxLen.VOPT_NAME) iso_path = os.path.join(_VOPT_TMPDIR, file_name) with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb: LOG.info("Config drive ISO being built in %s.", iso_path, instance=instance) # There may be an OSError exception when create the config drive. # If so, retry the operation before raising. @retrying.retry( retry_on_exception=lambda exc: isinstance(exc, OSError), stop_max_attempt_number=2) def _make_cfg_drive(iso_path): cdb.make_drive(iso_path) try: _make_cfg_drive(iso_path) return iso_path, file_name except OSError: with excutils.save_and_reraise_exception(logger=LOG): LOG.exception("Config drive ISO could not be built", instance=instance)
def test_sanitize_file_name_for_api(self): allc = ''.join(map(chr, range(256))) self.assertEqual('foo', util.sanitize_file_name_for_api('foo')) self.assertEqual( 'config_foo.iso', util.sanitize_file_name_for_api('foo', prefix='config_', suffix='.iso')) self.assertEqual( '______________________________________________._0123456789_______' 'ABCDEFGHIJKLMN', util.sanitize_file_name_for_api(allc)) self.assertEqual( 'OPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz_____________________' '______________', util.sanitize_file_name_for_api(allc[79:])) self.assertEqual( '_________________________________________________________________' '______________', util.sanitize_file_name_for_api(allc[158:])) self.assertEqual('___________________', util.sanitize_file_name_for_api(allc[237:])) self.assertEqual( (dummyuuid1 + dummyuuid2[:7] + dummyuuid1).replace('-', '_'), util.sanitize_file_name_for_api(dummyuuid2, prefix=dummyuuid1, suffix=dummyuuid1)) self.assertEqual( 'I____________', util.sanitize_file_name_for_api( u'I \u611B \u01A4\u0177\u03C1\uFF4F\u05E9\u5DF3' u'\u5C3A\uFF56\uFF4D')) self.assertRaises(ValueError, util.sanitize_file_name_for_api, allc, prefix=allc, suffix=allc) self.assertRaises(ValueError, util.sanitize_file_name_for_api, '') # Non-default max_len values self.assertEqual( 'abcdefghijklmno', util.sanitize_file_name_for_api('abcdefghijklmnopqrstuvwxyz', max_len=const.MaxLen.VDISK_NAME)) self.assertEqual( 'abcdefghijklmnopqrstuvwxyz0123456789A', util.sanitize_file_name_for_api( 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNO', max_len=const.MaxLen.VOPT_NAME))
def _get_image_name(image_meta, max_len=pvm_const.MaxLen.FILENAME_DEFAULT): """Generate a name for a virtual storage copy of an image. :param nova.objects.ImageMeta image_meta: The metadata of the image of the instance. :param max_len: Maximum string length for the resulting image name. :return: String name for the image on the server. """ return pvm_util.sanitize_file_name_for_api( image_meta.name, prefix=DiskType.IMAGE + '_', suffix='_' + image_meta.checksum, max_len=max_len)
def test_sanitize_file_name_for_api(self): allc = ''.join(map(chr, range(256))) self.assertEqual('foo', util.sanitize_file_name_for_api('foo')) self.assertEqual( 'config_foo.iso', util.sanitize_file_name_for_api( 'foo', prefix='config_', suffix='.iso')) self.assertEqual( '______________________________________________._0123456789_______' 'ABCDEFGHIJKLMN', util.sanitize_file_name_for_api(allc)) self.assertEqual( 'OPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz_____________________' '______________', util.sanitize_file_name_for_api(allc[79:]) ) self.assertEqual( '_________________________________________________________________' '______________', util.sanitize_file_name_for_api(allc[158:]) ) self.assertEqual('___________________', util.sanitize_file_name_for_api(allc[237:])) self.assertEqual( (dummyuuid1 + dummyuuid2[:7] + dummyuuid1).replace('-', '_'), util.sanitize_file_name_for_api( dummyuuid2, prefix=dummyuuid1, suffix=dummyuuid1)) self.assertEqual('I____________', util.sanitize_file_name_for_api( u'I \u611B \u01A4\u0177\u03C1\uFF4F\u05E9\u5DF3' u'\u5C3A\uFF56\uFF4D')) self.assertRaises(ValueError, util.sanitize_file_name_for_api, allc, prefix=allc, suffix=allc) self.assertRaises(ValueError, util.sanitize_file_name_for_api, '') # Non-default max_len values self.assertEqual('abcdefghijklmno', util.sanitize_file_name_for_api( 'abcdefghijklmnopqrstuvwxyz', max_len=const.MaxLen.VDISK_NAME)) self.assertEqual( 'abcdefghijklmnopqrstuvwxyz0123456789A', util.sanitize_file_name_for_api( 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNO', max_len=const.MaxLen.VOPT_NAME))
def create_cfg_drv_vopt(self, instance, injected_files, network_info, stg_ftsk, admin_pass=None, mgmt_cna=None): """Create the config drive virtual optical and attach to VM. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param stg_ftsk: FeedTask to defer storage connectivity operations. :param admin_pass: (Optional) password to inject for the VM. :param mgmt_cna: (Optional) The management (RMC) CNA wrapper. """ # If there is a management client network adapter, then we should # convert that to a VIF and add it to the network info if mgmt_cna is not None: network_info = copy.deepcopy(network_info) network_info.append(self._mgmt_cna_to_vif(mgmt_cna)) # Pick a file name for when we upload the media to VIOS file_name = pvm_util.sanitize_file_name_for_api( instance.uuid.replace('-', ''), prefix='cfg_', suffix='.iso', max_len=pvm_const.MaxLen.VOPT_NAME) # Create and upload the media with tempfile.NamedTemporaryFile(mode='rb') as fh: self._create_cfg_dr_iso(instance, injected_files, network_info, fh.name, admin_pass=admin_pass) vopt, f_uuid = tsk_stg.upload_vopt(self.adapter, self.vios_uuid, fh, file_name, os.path.getsize(fh.name)) # Define the function to build and add the mapping def add_func(vios_w): LOG.info("Adding cfg drive mapping to Virtual I/O Server %s.", vios_w.name, instance=instance) mapping = tsk_map.build_vscsi_mapping(None, vios_w, vm.get_pvm_uuid(instance), vopt) return tsk_map.add_map(vios_w, mapping) # Add the subtask to create the mapping when the FeedTask runs stg_ftsk.wrapper_tasks[self.vios_uuid].add_functor_subtask(add_func)
def _create_cfg_dr_iso(self, instance, injected_files, network_info, admin_pass=None): """Creates an ISO file that contains the injected files. Used for config drive. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param admin_pass: Optional password to inject for the VM. :return iso_path: The path to the ISO :return file_name: The file name for the ISO """ LOG.info(_LI("Creating config drive for instance: %s"), instance.name, instance=instance) extra_md = {} if admin_pass is not None: extra_md['admin_pass'] = admin_pass # Sanitize the vifs for the network config network_info = self._sanitize_network_info(network_info) inst_md = instance_metadata.InstanceMetadata(instance, content=injected_files, extra_md=extra_md, network_info=network_info) # Make sure the path exists. im_path = CONF.powervm.image_meta_local_path if not os.path.exists(im_path): os.mkdir(im_path) file_name = pvm_util.sanitize_file_name_for_api( instance.name, prefix=CFG_DRV_PREFIX, suffix=CFG_DRV_SUFFIX, max_len=pvm_const.MaxLen.VOPT_NAME) iso_path = os.path.join(im_path, file_name) with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb: LOG.info(_LI("Config drive ISO being built for instance %(inst)s " "building to path %(iso_path)s."), { 'inst': instance.name, 'iso_path': iso_path }, instance=instance) cdb.make_drive(iso_path) return iso_path, file_name
def get_name_by_uuid(disk_type, uuid, short=False): """Generate a name for a DiskType using a given uuid. :param disk_type: One of the DiskType enum values. :param uuid: The uuid to use for the name :param short: If True the generate name will be limited to 15 characters. If False it will be limited by the API. :return: A name base off of disk_type and uuid. """ prefix = '%s_' % (disk_type[0] if short else disk_type) return pvm_util.sanitize_file_name_for_api( uuid, prefix=prefix, max_len=pvm_const.MaxLen.VDISK_NAME if short else pvm_const.MaxLen.FILENAME_DEFAULT)
def create_disk_from_image(self, context, instance, image_meta): """Creates a boot disk and links the specified image to it. If the specified image has not already been uploaded, an Image LU is created for it. A Disk LU is then created for the instance and linked to the Image LU. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. :param nova.objects.ImageMeta image_meta: The metadata of the image of the instance. :return: The backing pypowervm LU storage object that was created. """ LOG.info('SSP: Create boot disk from image %s.', image_meta.id, instance=instance) image_lu = tsk_cs.get_or_upload_image_lu( self._tier, pvm_u.sanitize_file_name_for_api(image_meta.name, prefix=disk_drv.DiskType.IMAGE + '_', suffix='_' + image_meta.checksum), random.choice(self._vios_uuids), disk_drv.IterableToFileAdapter( IMAGE_API.download(context, image_meta.id)), image_meta.size, upload_type=tsk_stg.UploadType.IO_STREAM) boot_lu_name = pvm_u.sanitize_file_name_for_api( instance.name, prefix=disk_drv.DiskType.BOOT + '_') LOG.info('SSP: Disk name is %s', boot_lu_name, instance=instance) return tsk_stg.crt_lu(self._tier, boot_lu_name, instance.flavor.root_gb, typ=pvm_stg.LUType.DISK, clone=image_lu)[1]
def _create_cfg_dr_iso(self, instance, injected_files, network_info, admin_pass=None): """Creates an ISO file that contains the injected files. Used for config drive. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param admin_pass: Optional password to inject for the VM. :return iso_path: The path to the ISO :return file_name: The file name for the ISO """ LOG.info("Creating config drive.", instance=instance) extra_md = {} if admin_pass is not None: extra_md['admin_pass'] = admin_pass # Sanitize the vifs for the network config network_info = self._sanitize_network_info(network_info) inst_md = instance_metadata.InstanceMetadata(instance, content=injected_files, extra_md=extra_md, network_info=network_info) if not os.path.exists(_VOPT_TMPDIR): os.mkdir(_VOPT_TMPDIR) file_name = pvm_util.sanitize_file_name_for_api( instance.name, prefix='cfg_', suffix='.iso', max_len=pvm_const.MaxLen.VOPT_NAME) iso_path = os.path.join(_VOPT_TMPDIR, file_name) with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb: LOG.info("Config drive ISO being built in %s.", iso_path, instance=instance) # There may be an OSError exception when create the config drive. # If so, retry the operation before raising. @retrying.retry(retry_on_exception=lambda exc: isinstance( exc, OSError), stop_max_attempt_number=2) def _make_cfg_drive(iso_path): cdb.make_drive(iso_path) try: _make_cfg_drive(iso_path) return iso_path, file_name except OSError: with excutils.save_and_reraise_exception(logger=LOG): LOG.exception("Config drive ISO could not be built", instance=instance)
def _get_disk_name(disk_type, instance, short=False): """Generate a name for a virtual disk associated with an instance. :param disk_type: One of the DiskType enum values. :param instance: The instance for which the disk is to be created. :param short: If True, the generated name will be limited to 15 characters (the limit for virtual disk). If False, it will be limited by the API (79 characters currently). :return: """ prefix = "%s_" % (disk_type[0] if short else disk_type) base = "%s_%s" % (instance.name[:8], instance.uuid[:4]) if short else instance.name return pvm_util.sanitize_file_name_for_api( base, prefix=prefix, max_len=pvm_const.MaxLen.VDISK_NAME if short else pvm_const.MaxLen.FILENAME_DEFAULT )
def _get_disk_name(disk_type, instance, short=False): """Generate a name for a virtual disk associated with an instance. :param disk_type: One of the DiskType enum values. :param instance: The instance for which the disk is to be created. :param short: If True, the generated name will be limited to 15 characters (the limit for virtual disk). If False, it will be limited by the API (79 characters currently). :return: """ prefix = '%s_' % (disk_type[0] if short else disk_type) base = ('%s_%s' % (instance.name[:8], instance.uuid[:4]) if short else instance.name) return pvm_util.sanitize_file_name_for_api( base, prefix=prefix, max_len=pvm_const.MaxLen.VDISK_NAME if short else pvm_const.MaxLen.FILENAME_DEFAULT)
def create_cfg_drv_vopt(self, instance, injected_files, network_info, stg_ftsk, admin_pass=None, mgmt_cna=None): """Create the config drive virtual optical and attach to VM. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param stg_ftsk: FeedTask to defer storage connectivity operations. :param admin_pass: (Optional) password to inject for the VM. :param mgmt_cna: (Optional) The management (RMC) CNA wrapper. """ # If there is a management client network adapter, then we should # convert that to a VIF and add it to the network info if mgmt_cna is not None: network_info = copy.deepcopy(network_info) network_info.append(self._mgmt_cna_to_vif(mgmt_cna)) # Pick a file name for when we upload the media to VIOS file_name = pvm_util.sanitize_file_name_for_api( instance.uuid.replace('-', ''), prefix='cfg_', suffix='.iso', max_len=pvm_const.MaxLen.VOPT_NAME) # Create and upload the media with tempfile.NamedTemporaryFile(mode='rb') as fh: self._create_cfg_dr_iso(instance, injected_files, network_info, fh.name, admin_pass=admin_pass) vopt, f_uuid = tsk_stg.upload_vopt( self.adapter, self.vios_uuid, fh, file_name, os.path.getsize(fh.name)) # Define the function to build and add the mapping def add_func(vios_w): LOG.info("Adding cfg drive mapping to Virtual I/O Server %s.", vios_w.name, instance=instance) mapping = tsk_map.build_vscsi_mapping( None, vios_w, vm.get_pvm_uuid(instance), vopt) return tsk_map.add_map(vios_w, mapping) # Add the subtask to create the mapping when the FeedTask runs stg_ftsk.wrapper_tasks[self.vios_uuid].add_functor_subtask(add_func)
def _create_cfg_dr_iso(self, instance, injected_files, network_info, admin_pass=None): """Creates an ISO file that contains the injected files. Used for config drive. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param admin_pass: Optional password to inject for the VM. :return iso_path: The path to the ISO :return file_name: The file name for the ISO """ LOG.info(_LI("Creating config drive for instance: %s"), instance.name) extra_md = {} if admin_pass is not None: extra_md['admin_pass'] = admin_pass inst_md = instance_metadata.InstanceMetadata(instance, content=injected_files, extra_md=extra_md, network_info=network_info) # Make sure the path exists. im_path = CONF.powervm.image_meta_local_path if not os.path.exists(im_path): os.mkdir(im_path) file_name = pvm_util.sanitize_file_name_for_api( instance.name, prefix='cfg_', suffix='.iso', max_len=pvm_const.MaxLen.VOPT_NAME) iso_path = os.path.join(im_path, file_name) with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb: LOG.info(_LI("Config drive ISO being built for instance %(inst)s " "building to path %(iso_path)s."), {'inst': instance.name, 'iso_path': iso_path}) cdb.make_drive(iso_path) return iso_path, file_name
def _get_disk_name(disk_type, instance): """Generate a name for a virtual disk associated with an instance.""" return pvm_util.sanitize_file_name_for_api(instance.name, prefix=disk_type + '_')
def _get_image_name(image_meta): """Generate a name for a virtual storage copy of an image.""" return pvm_util.sanitize_file_name_for_api(image_meta['name'], prefix=DiskType.IMAGE + '_')
def _create_cfg_dr_iso(self, instance, injected_files, network_info, admin_pass=None): """Creates an ISO file that contains the injected files. Used for config drive. :param instance: The VM instance from OpenStack. :param injected_files: A list of file paths that will be injected into the ISO. :param network_info: The network_info from the nova spawn method. :param admin_pass: Optional password to inject for the VM. :return iso_path: The path to the ISO :return file_name: The file name for the ISO """ LOG.info("Creating config drive.", instance=instance) extra_md = {} if admin_pass is not None: extra_md['admin_pass'] = admin_pass # Sanitize the vifs for the network config network_info = self._sanitize_network_info(network_info) inst_md = instance_metadata.InstanceMetadata(instance, content=injected_files, extra_md=extra_md, network_info=network_info) # Make sure the path exists. im_path = CONF.powervm.image_meta_local_path if not os.path.exists(im_path): os.mkdir(im_path) file_name = pvm_util.sanitize_file_name_for_api( instance.name, prefix=CFG_DRV_PREFIX, suffix=CFG_DRV_SUFFIX, max_len=pvm_const.MaxLen.VOPT_NAME) iso_path = os.path.join(im_path, file_name) with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb: LOG.info("Config drive ISO building to path %(iso_path)s.", {'iso_path': iso_path}, instance=instance) # In case, if there's an OSError related failure while # creating config drive, retry make drive operation. def _retry_on_oserror(exc): return isinstance(exc, OSError) @retrying.retry(retry_on_exception=_retry_on_oserror, stop_max_attempt_number=2) def _make_cfg_drive(iso_path): cdb.make_drive(iso_path) try: _make_cfg_drive(iso_path) return iso_path, file_name except OSError: with excutils.save_and_reraise_exception(logger=LOG): # If we get here, that means there's an exception during # second attempt, log the same and fail the deploy # operation. LOG.exception("Config drive ISO could not be built.", instance=instance)
def _get_image_name(image_meta): """Generate a name for a virtual storage copy of an image.""" return pvm_util.sanitize_file_name_for_api(image_meta.name, prefix=DiskType.IMAGE + '_', suffix='_' + image_meta.checksum)
def _get_image_name(image_meta, max_len=pvm_const.MaxLen.FILENAME_DEFAULT): """Generate a name for a virtual storage copy of an image.""" return pvm_util.sanitize_file_name_for_api( image_meta.name, prefix=DiskType.IMAGE + '_', suffix='_' + image_meta.checksum, max_len=max_len)
def get_cfg_drv_name(instance): return pvm_util.sanitize_file_name_for_api( instance.uuid.replace('-', ''), prefix='cfg_', suffix='.iso', max_len=pvm_const.MaxLen.VOPT_NAME)
def _get_image_name(image_meta): """Generate a name for a virtual storage copy of an image.""" return pvm_util.sanitize_file_name_for_api(image_meta["name"], prefix=DiskType.IMAGE + "_")
def get_or_upload_image_lu(tier, luname, vios_uuid, io_handle, b_size, upload_type=tsk_stg.UploadType.IO_STREAM_BUILDER): """Ensures our SSP has an LU containing the specified image. If an LU of type IMAGE with the specified luname already exists in our SSP, return it. Otherwise, create it, prime it with the image contents provided via stream_func, and return it. This method assumes that consumers employ a naming convention such that an LU with a given name represents the same data (size and content) no matter where/when it's created/uploaded - for example, by including the image's MD5 checksum in the name. This method is designed to coordinate the upload of a particular image LU across multiple hosts which use the same SSP, but otherwise can not communicate with each other. :param tier: Tier EntryWrapper of the Shared Storage Pool Tier on which the image LU is to be hosted. :param luname: The name of the image LU. Note that the name may be shortened to satisfy length restrictions. :param vios_uuid: The UUID of the Virtual I/O Server through which the upload should be performed, if necessary. :param io_handle: The I/O handle (as defined by the upload_type). This is only used if the image_lu needs to be uploaded. :param b_size: Integer size, in bytes, of the image provided by stream_func's return value. :param upload_type: (Optional, Default: IO_STREAM_BUILDER) Defines the way in which the LU should be uploaded. Refer to the UploadType enumeration for valid upload mechanisms. It defaults to IO_STREAM_BUILDER for legacy reasons. :return: LUEnt EntryWrapper representing the image LU. """ # Marker (upload-in-progress) LU name prefixed with 'partxxxxxxxx' prefix = 'part%s' % uuid.uuid4().hex[:8] # Ensure the marker LU name won't be too long luname = u.sanitize_file_name_for_api(luname, max_len=c.MaxLen.FILENAME_DEFAULT - len(prefix)) mkr_luname = prefix + luname first = True while True: # (Re)fetch the list of image LUs whose name *contains* luname. lus = _find_lus(tier, luname) # Does the LU already exist in its final, uploaded form? If so, then # only that LU will exist, with an exact name match. if len(lus) == 1 and lus[0].name == luname: LOG.info(_('Using already-uploaded image LU %s.'), luname) return lus[0] # Is there an upload in progress? if _upload_in_progress(lus, luname, first): first = False _sleep_for_upload() continue # No upload in progress (at least as of when we grabbed the feed). LOG.info(_('Creating marker LU %s'), mkr_luname) tier, mkrlu = tsk_stg.crt_lu(tier, mkr_luname, MKRSZ, typ=IMGTYP) # We must remove the marker LU if # a) anything fails beyond this point; or # b) we successfully upload the image LU. try: # If another process (possibly on another host) created a marker LU # at the same time, there could be multiple marker LUs out there. # We all use _upload_conflict to decide which one of us gets to do # the upload. if _upload_conflict(tier, luname, mkr_luname): _sleep_for_upload() continue # Okay, we won. Do the actual upload. LOG.info(_('Uploading to image LU %(lu)s (marker %(mkr)s).'), { 'lu': luname, 'mkr': mkr_luname }) # Create the new Logical Unit. The LU size needs to be decimal GB. tier, new_lu = tsk_stg.crt_lu(tier, luname, u.convert_bytes_to_gb(b_size, dp=2), typ=IMGTYP) try: tsk_stg.upload_lu(vios_uuid, new_lu, io_handle, b_size, upload_type=upload_type) except Exception as exc: LOG.exception(exc) # We need to remove the LU so it doesn't block others # attempting to use the same one. LOG.exception(_('Removing failed LU %s.'), luname) new_lu.delete() raise return new_lu finally: # Signal completion, or clean up, by removing the marker LU. mkrlu.delete()
def _get_image_name(image_meta): """Generate a name for a virtual storage copy of an image.""" return pvm_util.sanitize_file_name_for_api( image_meta.name, prefix=DiskType.IMAGE + '_', suffix='_' + image_meta.checksum)