def _check_cacheable(self, specs, type_id): multiattach = volume_types.get_volume_type_extra_specs( type_id, key='multiattach') cacheable = volume_types.get_volume_type_extra_specs(type_id, key='cacheable') isTrue = '<is> True' if (specs.get('multiattach') == isTrue and cacheable == isTrue) or ( specs.get('cacheable') == isTrue and multiattach == isTrue) or (specs.get('cacheable') == isTrue and specs.get('multiattach') == isTrue): expl = _('cacheable cannot be set with multiattach.') raise webob.exc.HTTPBadRequest(explanation=expl) return
def _get_volumetype_extraspecs(self, volume): specs = {} type_id = volume['volume_type_id'] if type_id is not None: specs = volume_types.get_volume_type_extra_specs(type_id) return specs
def _get_volume_type_extra_spec(type_id, spec_key, possible_values, default_value): """Get extra spec value. If the spec value is not present in the input possible_values, then default_value will be returned. If the type_id is None, then default_value is returned. The caller must not consider scope and the implementation adds/removes scope. The scope used here is 'vmware' e.g. key 'vmware:vmdk_type' and so the caller must pass vmdk_type as an input ignoring the scope. :param type_id: Volume type ID :param spec_key: Extra spec key :param possible_values: Permitted values for the extra spec :param default_value: Default value for the extra spec incase of an invalid value or if the entry does not exist :return: extra spec value """ if type_id: spec_key = ('vmware:%s') % spec_key spec_value = volume_types.get_volume_type_extra_specs(type_id, spec_key) if spec_value in possible_values: LOG.debug(_("Returning spec value %s") % spec_value) return spec_value LOG.debug(_("Invalid spec value: %s specified.") % spec_value) # Default we return thin disk type LOG.debug(_("Returning default spec value: %s.") % default_value) return default_value
def from_volume(cls, volume): specs = {} type_id = volume['volume_type_id'] if type_id is not None: specs = volume_types.get_volume_type_extra_specs(type_id) return cls(specs)
def _get_volume_type_extra_spec(type_id, spec_key, possible_values, default_value): """Get extra spec value. If the spec value is not present in the input possible_values, then default_value will be returned. If the type_id is None, then default_value is returned. The caller must not consider scope and the implementation adds/removes scope. The scope used here is 'vmware' e.g. key 'vmware:vmdk_type' and so the caller must pass vmdk_type as an input ignoring the scope. :param type_id: Volume type ID :param spec_key: Extra spec key :param possible_values: Permitted values for the extra spec :param default_value: Default value for the extra spec incase of an invalid value or if the entry does not exist :return: extra spec value """ if type_id: spec_key = ('vmware:%s') % spec_key spec_value = volume_types.get_volume_type_extra_specs( type_id, spec_key) if spec_value in possible_values: LOG.debug(_("Returning spec value %s") % spec_value) return spec_value LOG.debug(_("Invalid spec value: %s specified.") % spec_value) # Default we return thin disk type LOG.debug(_("Returning default spec value: %s.") % default_value) return default_value
def _get_volume_extra_specs(self, volume): """Gets extra specs for the given volume.""" type_id = volume.get('volume_type_id') if type_id: return volume_types.get_volume_type_extra_specs(type_id) return {}
def get_extra_spec(volume, spec_key): spec_value = None type_id = volume.volume_type_id if type_id is not None: extra_specs = volume_types.get_volume_type_extra_specs(type_id) if spec_key in extra_specs: spec_value = extra_specs[spec_key] return spec_value
def mock_volume_types(self, repositories=None): if not repositories: repositories = [fake_repository_name] self.mox.StubOutWithMock(volume_types, 'get_volume_type_extra_specs') for repository in repositories: (volume_types.get_volume_type_extra_specs( fake_volume_type['id'], fake_coraid_repository_key).AndReturn( '<in> {0}'.format(repository)))
def _is_share_volume(self, volume_type_id): if volume_type_id: value = volume_types.get_volume_type_extra_specs(volume_type_id, key='is_shared') if value and value.lower() == 'true': return True return False
def _get_voltype_specs(self, volume): """Get specs suitable for volume creation.""" vtype = volume.get('volume_type_id', None) extra_specs = None if vtype: extra_specs = volume_types.get_volume_type_extra_specs(vtype) return self._get_specs(extra_specs)
def _template_from_volume(self, volume): default = self.configuration.storpool_template vtype = volume['volume_type'] if vtype is not None: specs = volume_types.get_volume_type_extra_specs(vtype['id']) if specs is not None: return specs.get('storpool_template', default) return default
def get_volume_extra_specs(self, volume): if volume is None: return {} type_id = volume.get('volume_type_id') if type_id is None: return {} return volume_types.get_volume_type_extra_specs(type_id)
def _get_repository(self, volume_type): """ Return the ESM Repository from the Volume Type. The ESM Repository is stored into a volume_type_extra_specs key. """ volume_type_id = volume_type["id"] repository_key_name = self.configuration.coraid_repository_key repository = volume_types.get_volume_type_extra_specs(volume_type_id, repository_key_name) return repository
def mock_volume_types(self, repositories=[]): if not repositories: repositories = [fake_repository_name] self.mox.StubOutWithMock(volume_types, "get_volume_type_extra_specs") for repository in repositories: ( volume_types.get_volume_type_extra_specs(fake_volume_type["id"], fake_coraid_repository_key).AndReturn( "<in> {0}".format(repository) ) )
def _get_repository(self, volume_type): """ Return the ESM Repository from the Volume Type. The ESM Repository is stored into a volume_type_extra_specs key. """ volume_type_id = volume_type['id'] repository_key_name = self.configuration.coraid_repository_key repository = volume_types.get_volume_type_extra_specs( volume_type_id, repository_key_name) return repository
def validate_cg_type(group): if not group.get('volume_type_ids'): return for type_id in group.get('volume_type_ids'): if type_id: specs = volume_types.get_volume_type_extra_specs(type_id) extra_specs = common.ExtraSpecs(specs) if extra_specs.provision == storops.VNXProvisionEnum.COMPRESSED: msg = _("Failed to create consistency group %s " "because VNX consistency group cannot " "accept compressed LUNs as members.") % group['id'] raise exception.InvalidInput(reason=msg)
def validate_cg_type(group): if group.get('volume_type_id') is None: return for type_id in group['volume_type_id'].split(","): if type_id: specs = volume_types.get_volume_type_extra_specs(type_id) extra_specs = common.ExtraSpecs(specs) if extra_specs.provision == storops.VNXProvisionEnum.COMPRESSED: msg = _("Failed to create consistency group %s " "because VNX consistency group cannot " "accept compressed LUNs as members." ) % group['id'] raise exception.InvalidInput(reason=msg)
def _get_repository(self, volume_type): """Get the ESM Repository from the Volume Type. The ESM Repository is stored into a volume_type_extra_specs key. """ volume_type_id = volume_type['id'] repository_key_name = self.configuration.coraid_repository_key repository = volume_types.get_volume_type_extra_specs( volume_type_id, repository_key_name) # Remove <in> keyword from repository name if needed if repository.startswith('<in> '): return repository[len('<in> '):] else: return repository
def get_pool(self, volume): if not volume['volume_type']: return 'default' else: metadata = {} type_id = volume['volume_type_id'] if type_id is not None: metadata = volume_types.get_volume_type_extra_specs(type_id) if not metadata.get('service_label'): return 'default' else: if metadata['service_label'] not in \ self.config['services'].keys(): return 'default' else: return metadata['service_label']
def get_pool(config, volume): """Get the pool of a volume. :param config: dictionary containing the configuration parameters :param volume: dictionary volume reference :returns: the pool related to the volume """ if volume.volume_type: metadata = {} type_id = volume.volume_type_id if type_id is not None: metadata = volume_types.get_volume_type_extra_specs(type_id) if metadata.get('service_label'): if metadata['service_label'] in config['services'].keys(): return metadata['service_label'] return 'default'
def get_volumetype_extraspecs(self, volume): """Compare the bit sizes to an approximate. :param volume: the volume dictionary :returns: extraSpecs - the extra specs """ extraSpecs = {} try: type_id = volume['volume_type_id'] if type_id is not None: extraSpecs = volume_types.get_volume_type_extra_specs(type_id) except Exception: pass return extraSpecs
def get_pool(self, volume): if not volume["volume_type"]: return "default" else: metadata = {} type_id = volume["volume_type_id"] if type_id is not None: metadata = volume_types.get_volume_type_extra_specs(type_id) if not metadata.get("service_label"): return "default" else: if metadata["service_label"] not in self.config["services"].keys(): return "default" else: pass return metadata["service_label"]
def get_volumetype_extra_specs(volume, volume_type_id=None): """Gets the extra specs associated with a volume type. :param volume: the volume dictionary :param volume_type_id: Optional override for volume.volume_type_id :returns: dict -- extra_specs - the extra specs :raises: VolumeBackendAPIException """ extra_specs = {} try: if volume_type_id: type_id = volume_type_id else: type_id = volume.volume_type_id if type_id is not None: extra_specs = volume_types.get_volume_type_extra_specs(type_id) except Exception as e: LOG.debug('Exception getting volume type extra specs: %(e)s', {'e': six.text_type(e)}) return extra_specs
def _group_id_for_volume(volume): """Given a Nova volume, find the ID of its storage group in the CMDB. Return None if no storage group is defined for the volume. """ # Support two possibilities: either the storage group ID is a # property of the volume type or it's in the volume's metadata. # The former is recommended and has priority. try: volume_type_id = volume['volume_type']['id'] extra_specs = volume_types.get_volume_type_extra_specs( volume_type_id) gid = extra_specs['sds:storage_group_id'] return gid except: pass groups = [i.value for i in volume.get('volume_metadata') if i.key == 'storage_group'] if groups: gid = groups[0] if len(groups) > 1: LOG.warning(_('More than one storage_group was ' 'detected, using %s') % gid) return gid
def _get_repository(self, volume_type): """Get the ESM Repository from the Volume Type. The ESM Repository is stored into a volume_type_extra_specs key. """ volume_type_id = volume_type['id'] repository_key_name = self.configuration.coraid_repository_key repository = (volume_types.get_volume_type_extra_specs( volume_type_id, repository_key_name) or self.configuration.coraid_default_repository) # if there's no repository still, we cannot move forward if not repository: message = ("The Coraid repository not specified neither " "in Volume Type '%s' key nor in the " "'coraid_default_repository' config option" % self.configuration.coraid_repository_key) raise exception.CoraidException(message=message) # Remove <in> keyword from repository name if needed if repository.startswith('<in> '): return repository[len('<in> '):] else: return repository
def execute(self, context, size, snapshot, image_id, source_volume, availability_zone, volume_type, metadata, key_manager, consistencygroup, cgsnapshot, group, group_snapshot, backup, multiattach=False): utils.check_exclusive_options(snapshot=snapshot, imageRef=image_id, source_volume=source_volume, backup=backup) context.authorize(policy.CREATE_POLICY) # TODO(harlowja): what guarantee is there that the snapshot or source # volume will remain available after we do this initial verification?? snapshot_id = self._extract_snapshot(snapshot) source_volid = self._extract_source_volume(source_volume) backup_id = self._extract_backup(backup) size = self._extract_size(size, source_volume, snapshot, backup) consistencygroup_id = self._extract_consistencygroup(consistencygroup) cgsnapshot_id = self._extract_cgsnapshot(cgsnapshot) group_id = self._extract_group(group) image_meta = self._get_image_metadata(context, image_id, size) image_properties = image_meta.get( 'properties', {}) if image_meta else {} image_volume_type = image_properties.get( 'cinder_img_volume_type', None) if image_properties else None volume_type = self._get_volume_type( context, volume_type, source_volume, snapshot, image_volume_type) volume_type_id = volume_type.get('id') if volume_type else None availability_zones, refresh_az = self._extract_availability_zones( availability_zone, snapshot, source_volume, group, volume_type=volume_type) encryption_key_id = self._get_encryption_key_id( key_manager, context, volume_type_id, snapshot, source_volume, image_meta) if volume_type_id: volume_type = objects.VolumeType.get_by_name_or_id( context, volume_type_id) extra_specs = volume_type.get('extra_specs', {}) # NOTE(tommylikehu): Although the parameter `multiattach` from # create volume API is deprecated now, we still need to consider # it when multiattach is not enabled in volume type. multiattach = (extra_specs.get( 'multiattach', '') == '<is> True' or multiattach) if multiattach and encryption_key_id: msg = _('Multiattach cannot be used with encrypted volumes.') raise exception.InvalidVolume(reason=msg) if multiattach: context.authorize(policy.MULTIATTACH_POLICY) specs = {} if volume_type_id: qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id) if qos_specs['qos_specs']: specs = qos_specs['qos_specs'].get('specs', {}) # Determine default replication status extra_specs = volume_types.get_volume_type_extra_specs( volume_type_id) if not specs: # to make sure we don't pass empty dict specs = None extra_specs = None if vol_utils.is_replicated_spec(extra_specs): replication_status = fields.ReplicationStatus.ENABLED else: replication_status = fields.ReplicationStatus.DISABLED return { 'size': size, 'snapshot_id': snapshot_id, 'source_volid': source_volid, 'volume_type': volume_type, 'volume_type_id': volume_type_id, 'encryption_key_id': encryption_key_id, 'qos_specs': specs, 'consistencygroup_id': consistencygroup_id, 'cgsnapshot_id': cgsnapshot_id, 'group_id': group_id, 'replication_status': replication_status, 'refresh_az': refresh_az, 'backup_id': backup_id, 'multiattach': multiattach, 'availability_zones': availability_zones }
def _template_from_volume_type(self, vtype): specs = volume_types.get_volume_type_extra_specs(vtype['id']) if specs is None: return None return specs.get('storpool_template', None)
def __init__(self, volume, is_snapshot=False): volume_type_id = volume.get('volume_type_id') self.specs = volume_types.get_volume_type_extra_specs( volume_type_id) if volume_type_id else {} os400 = self.specs.get( 'drivers:os400', EXTRA_SPECS_DEFAULTS['os400'] ).strip().upper() self.type_thin = self.specs.get( 'drivers:thin_provision', '%s' % EXTRA_SPECS_DEFAULTS['thin'] ).upper() == 'True'.upper() self.type_replication = self.specs.get( 'replication_enabled', '<is> %s' % EXTRA_SPECS_DEFAULTS['replication_enabled'] ).upper() == strings.METADATA_IS_TRUE if volume.provider_location: provider_location = ast.literal_eval(volume.provider_location) self.ds_id = provider_location['vol_hex_id'] else: self.ds_id = None self.cinder_name = volume.display_name self.pool_lss_pair = {} self.is_snapshot = is_snapshot if self.is_snapshot: self.group = (Group(volume.group_snapshot, True) if volume.group_snapshot else None) self.size = volume.volume_size # ds8k supports at most 16 chars self.ds_name = ( "OS%s:%s" % ('snap', helper.filter_alnum(self.cinder_name)) )[:16] else: self.group = Group(volume.group) if volume.group else None self.size = volume.size self.ds_name = ( "OS%s:%s" % ('vol', helper.filter_alnum(self.cinder_name)) )[:16] self.replica_ds_name = ( "OS%s:%s" % ('Replica', helper.filter_alnum(self.cinder_name)) )[:16] self.replication_status = volume.replication_status self.replication_driver_data = ( json.loads(volume.replication_driver_data) if volume.replication_driver_data else {}) if self.replication_driver_data: # now only support one replication target. replication_target = sorted( self.replication_driver_data.values())[0] replica_id = replication_target['vol_hex_id'] self.pool_lss_pair = { 'source': (None, self.ds_id[0:2]), 'target': (None, replica_id[0:2]) } if os400: if os400 not in VALID_OS400_VOLUME_TYPES.keys(): raise restclient.APIException( data=(_("The OS400 volume type provided, %s, is not " "a valid volume type.") % os400)) self.type_os400 = os400 if os400 not in ['050', '099']: self.size = VALID_OS400_VOLUME_TYPES[os400] else: self.type_os400 = EXTRA_SPECS_DEFAULTS['os400'] self.data_type = self._create_datatype(self.type_os400) self.os_id = volume.id self.status = volume.status self.volume = volume
def execute(self, context, size, snapshot, image_id, source_volume, availability_zone, volume_type, metadata, key_manager, consistencygroup, cgsnapshot, group): utils.check_exclusive_options(snapshot=snapshot, imageRef=image_id, source_volume=source_volume) policy.enforce_action(context, ACTION) # TODO(harlowja): what guarantee is there that the snapshot or source # volume will remain available after we do this initial verification?? snapshot_id = self._extract_snapshot(snapshot) source_volid = self._extract_source_volume(source_volume) size = self._extract_size(size, source_volume, snapshot) consistencygroup_id = self._extract_consistencygroup(consistencygroup) cgsnapshot_id = self._extract_cgsnapshot(cgsnapshot) group_id = self._extract_group(group) image_meta = self._get_image_metadata(context, image_id, size) availability_zone, refresh_az = self._extract_availability_zone( availability_zone, snapshot, source_volume, group) # TODO(joel-coffman): This special handling of snapshots to ensure that # their volume type matches the source volume is too convoluted. We # should copy encryption metadata from the encrypted volume type to the # volume upon creation and propagate that information to each snapshot. # This strategy avoids any dependency upon the encrypted volume type. def_vol_type = volume_types.get_default_volume_type() if not volume_type and not source_volume and not snapshot: image_volume_type = self._get_image_volume_type(context, image_id) volume_type = (image_volume_type if image_volume_type else def_vol_type) volume_type_id = self._get_volume_type_id(volume_type, source_volume, snapshot) encryption_key_id = self._get_encryption_key_id( key_manager, context, volume_type_id, snapshot, source_volume, image_meta) specs = {} if volume_type_id: qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id) if qos_specs['qos_specs']: specs = qos_specs['qos_specs'].get('specs', {}) # Determine default replication status extra_specs = volume_types.get_volume_type_extra_specs( volume_type_id) if not specs: # to make sure we don't pass empty dict specs = None extra_specs = None if vol_utils.is_replicated_spec(extra_specs): replication_status = fields.ReplicationStatus.ENABLED else: replication_status = fields.ReplicationStatus.DISABLED return { 'size': size, 'snapshot_id': snapshot_id, 'source_volid': source_volid, 'availability_zone': availability_zone, 'volume_type': volume_type, 'volume_type_id': volume_type_id, 'encryption_key_id': encryption_key_id, 'qos_specs': specs, 'consistencygroup_id': consistencygroup_id, 'cgsnapshot_id': cgsnapshot_id, 'group_id': group_id, 'replication_status': replication_status, 'refresh_az': refresh_az }
def execute(self, context, size, snapshot, image_id, source_volume, availability_zone, volume_type, metadata, key_manager, consistencygroup, cgsnapshot, group, group_snapshot, backup, multiattach=False): utils.check_exclusive_options(snapshot=snapshot, imageRef=image_id, source_volume=source_volume, backup=backup) context.authorize(policy.CREATE_POLICY) # TODO(harlowja): what guarantee is there that the snapshot or source # volume will remain available after we do this initial verification?? snapshot_id = self._extract_snapshot(snapshot) source_volid = self._extract_source_volume(source_volume) backup_id = self._extract_backup(backup) size = self._extract_size(size, source_volume, snapshot, backup) consistencygroup_id = self._extract_consistencygroup(consistencygroup) cgsnapshot_id = self._extract_cgsnapshot(cgsnapshot) group_id = self._extract_group(group) image_meta = self._get_image_metadata(context, image_id, size) image_properties = image_meta.get('properties', {}) if image_meta else {} image_volume_type = image_properties.get( 'cinder_img_volume_type', None) if image_properties else None volume_type = self._get_volume_type(context, volume_type, source_volume, snapshot, image_volume_type) volume_type_id = volume_type.get('id') if volume_type else None availability_zones, refresh_az = self._extract_availability_zones( availability_zone, snapshot, source_volume, group, volume_type=volume_type) encryption_key_id = self._get_encryption_key_id( key_manager, context, volume_type_id, snapshot, source_volume, image_meta) # new key id that's been cloned already if volume_type_id: volume_type = objects.VolumeType.get_by_name_or_id( context, volume_type_id) extra_specs = volume_type.get('extra_specs', {}) # NOTE(tommylikehu): Although the parameter `multiattach` from # create volume API is deprecated now, we still need to consider # it when multiattach is not enabled in volume type. multiattach = (extra_specs.get('multiattach', '') == '<is> True' or multiattach) if multiattach and encryption_key_id: msg = _('Multiattach cannot be used with encrypted volumes.') raise exception.InvalidVolume(reason=msg) if multiattach: context.authorize(policy.MULTIATTACH_POLICY) specs = {} if volume_type_id: qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id) if qos_specs['qos_specs']: specs = qos_specs['qos_specs'].get('specs', {}) # Determine default replication status extra_specs = volume_types.get_volume_type_extra_specs( volume_type_id) if not specs: # to make sure we don't pass empty dict specs = None extra_specs = None if volume_utils.is_replicated_spec(extra_specs): replication_status = fields.ReplicationStatus.ENABLED else: replication_status = fields.ReplicationStatus.DISABLED return { 'size': size, 'snapshot_id': snapshot_id, 'source_volid': source_volid, 'volume_type': volume_type, 'volume_type_id': volume_type_id, 'encryption_key_id': encryption_key_id, 'qos_specs': specs, 'consistencygroup_id': consistencygroup_id, 'cgsnapshot_id': cgsnapshot_id, 'group_id': group_id, 'replication_status': replication_status, 'refresh_az': refresh_az, 'backup_id': backup_id, 'multiattach': multiattach, 'availability_zones': availability_zones }