def _volume_upload_image(self, req, id, body): """Uploads the specified volume to image service.""" context = req.environ['cinder.context'] params = body['os-volume_upload_image'] req_version = req.api_version_request force = params.get('force', 'False') force = strutils.bool_from_string(force, strict=True) # Not found exception will be handled at the wsgi level volume = self.volume_api.get(context, id) context.authorize(policy.UPLOAD_IMAGE_POLICY) # check for valid disk-format disk_format = params.get("disk_format", "raw") image_metadata = {"container_format": params.get( "container_format", "bare"), "disk_format": disk_format, "name": params["image_name"]} if volume.encryption_key_id: # Clone volume encryption key: the current key cannot # be reused because it will be deleted when the volume is # deleted. # TODO(eharney): Currently, there is no mechanism to remove # these keys, because Glance will not delete the key from # Barbican when the image is deleted. encryption_key_id = self._key_manager.store( context, self._key_manager.get(context, volume.encryption_key_id)) image_metadata['cinder_encryption_key_id'] = encryption_key_id if req_version >= mv.get_api_version( mv.UPLOAD_IMAGE_PARAMS): image_metadata['visibility'] = params.get('visibility', 'private') image_metadata['protected'] = strutils.bool_from_string( params.get('protected', 'False'), strict=True) if image_metadata['visibility'] == 'public': context.authorize(policy.UPLOAD_PUBLIC_POLICY) try: response = self.volume_api.copy_volume_to_image(context, volume, image_metadata, force) except exception.InvalidVolume as error: raise webob.exc.HTTPBadRequest(explanation=error.msg) except ValueError as error: raise webob.exc.HTTPBadRequest(explanation=six.text_type(error)) except messaging.RemoteError as error: msg = "%(err_type)s: %(err_msg)s" % {'err_type': error.exc_type, 'err_msg': error.value} raise webob.exc.HTTPBadRequest(explanation=msg) except Exception as error: raise webob.exc.HTTPBadRequest(explanation=six.text_type(error)) return {'os-volume_upload_image': response}
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, action='migrate_live') block_migration = body["os-migrateLive"]["block_migration"] disk_over_commit = body["os-migrateLive"]["disk_over_commit"] host = body["os-migrateLive"]["host"] block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) try: instance = common.get_instance(self.compute_api, context, id) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.MigrationPreCheckError, exception.LiveMigrationWithOldNovaNotSafe) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'os-migrateLive', id)
def update_host(self, context, segment_uuid, id, host_data): """Update the host""" segment = objects.FailoverSegment.get_by_uuid(context, segment_uuid) host = objects.Host.get_by_uuid(context, id) if is_failover_segment_under_recovery(segment): msg = _("Host %s can't be updated as " "it is in-use to process notifications.") % host.uuid LOG.error(msg) raise exception.HostInUse(msg) if 'name' in host_data: self._is_valid_host_name(context, host_data.get('name')) if 'on_maintenance' in host_data: host_data['on_maintenance'] = strutils.bool_from_string( host_data['on_maintenance'], strict=True) if 'reserved' in host_data: host_data['reserved'] = strutils.bool_from_string( host_data['reserved'], strict=True) try: host.update(host_data) host.save() except Exception as e: with excutils.save_and_reraise_exception(): tb = traceback.format_exc() api_utils.notify_about_host_api(context, host, action=fields.EventNotificationAction.HOST_UPDATE, phase=fields.EventNotificationPhase.ERROR, exception=e, tb=tb) return host
def create_host(self, context, segment_uuid, host_data): """Create host""" segment = objects.FailoverSegment.get_by_uuid(context, segment_uuid) host = objects.Host(context=context) # Populate host object for create host.name = host_data.get('name') host.failover_segment_id = segment.uuid host.type = host_data.get('type') host.control_attributes = host_data.get('control_attributes') host.on_maintenance = strutils.bool_from_string( host_data.get('on_maintenance', False), strict=True) host.reserved = strutils.bool_from_string( host_data.get('reserved', False), strict=True) self._is_valid_host_name(context, host.name) try: host.create() except Exception as e: with excutils.save_and_reraise_exception(): tb = traceback.format_exc() api_utils.notify_about_host_api(context, host, action=fields.EventNotificationAction.HOST_CREATE, phase=fields.EventNotificationPhase.ERROR, exception=e, tb=tb) return host
def get_headers(req): kwargs = {} # TODO(vkmc) We should add a control here to make sure # that the headers/request combination is possible # e.g. we cannot have messages_post with grace if req._body.get('marker') is not None: kwargs['marker'] = req._body.get('marker') if req._body.get('limit') is not None: kwargs['limit'] = int(req._body.get('limit')) if req._body.get('detailed') is not None: kwargs['detailed'] = strutils.bool_from_string( req._body.get('detailed')) if req._body.get('echo') is not None: kwargs['echo'] = strutils.bool_from_string(req._body.get('echo')) if req._body.get('include_claimed') is not None: kwargs['include_claimed'] = strutils.bool_from_string( req._body.get('include_claimed')) if req._body.get('ttl') is not None: kwargs['ttl'] = int(req._body.get('ttl')) if req._body.get('grace') is not None: kwargs['grace'] = int(req._body.get('grace')) return kwargs
def _validate_type(self, attrib, value): if attrib.schema.type == attrib.schema.STRING: if not isinstance(value, six.string_types): LOG.warning(_LW("Attribute %(name)s is not of type " "%(att_type)s"), {'name': attrib.name, 'att_type': attrib.schema.STRING}) elif attrib.schema.type == attrib.schema.LIST: if (not isinstance(value, collections.Sequence) or isinstance(value, six.string_types)): LOG.warning(_LW("Attribute %(name)s is not of type " "%(att_type)s"), {'name': attrib.name, 'att_type': attrib.schema.LIST}) elif attrib.schema.type == attrib.schema.MAP: if not isinstance(value, collections.Mapping): LOG.warning(_LW("Attribute %(name)s is not of type " "%(att_type)s"), {'name': attrib.name, 'att_type': attrib.schema.MAP}) elif attrib.schema.type == attrib.schema.INTEGER: if not isinstance(value, int): LOG.warning(_LW("Attribute %(name)s is not of type " "%(att_type)s"), {'name': attrib.name, 'att_type': attrib.schema.INTEGER}) elif attrib.schema.type == attrib.schema.BOOLEAN: try: strutils.bool_from_string(value, strict=True) except ValueError: LOG.warning(_LW("Attribute %(name)s is not of type " "%(att_type)s"), {'name': attrib.name, 'att_type': attrib.schema.BOOLEAN})
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, 'migrateLive') try: block_migration = body["os-migrateLive"]["block_migration"] disk_over_commit = body["os-migrateLive"]["disk_over_commit"] host = body["os-migrateLive"]["host"] except (TypeError, KeyError): msg = _("host, block_migration and disk_over_commit must " "be specified for live migration.") raise exc.HTTPBadRequest(explanation=msg) try: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=six.text_type(err)) instance = common.get_instance(self.compute_api, context, id, want_objects=True) try: self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.InstanceNotRunning, exception.MigrationPreCheckError, exception.LiveMigrationWithOldNovaNotSafe) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceNotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'os-migrateLive', id) except Exception: if host is None: msg = _("Live migration of instance %s to another host " "failed") % id else: msg = _("Live migration of instance %(id)s to host %(host)s " "failed") % {'id': id, 'host': host} LOG.exception(msg) # Return messages from scheduler raise exc.HTTPInternalServerError(explanation=msg) return webob.Response(status_int=202)
def __init__(self, runtime): self._runtime = weakref.proxy(runtime) self._storage = runtime.storage self._undefined_resolver = RevertAll(self._runtime) self._defer_reverts = strutils.bool_from_string( self._runtime.options.get('defer_reverts', False)) self._resolve = not strutils.bool_from_string( self._runtime.options.get('never_resolve', False))
def evaluate_pool(pool): try: pool_attributes = pool.attributes.to_dict() except exceptions.RelationNotLoaded: pool_attributes = {} # Remove the "pool_id" attribute, that is used in # PoolIDAttributeFilter. If the item is not in the dict, it is # fine, we should just continue. pool_attributes.pop('pool_id', None) if pool_attributes == {}: # If we did not send any attribute to filter on, we should # not filter the pools based on an empty set, as this will # return no pools. return True # Check if the keys requested exist in this pool if not {key for key in six.iterkeys(pool_attributes)}.issuperset( zone_attributes): msg = "%(pool)s did not match list of requested attribute "\ "keys - removing from list. Requested: %(r_key)s. Pool:"\ "%(p_key)s" LOG.debug( msg, { 'pool': pool, 'r_key': zone_attributes, 'p_key': pool_attributes } ) # Missing required keys - remove from the list return False for key in six.iterkeys(zone_attributes): LOG.debug("Checking value of %s for %s", key, pool) pool_attr = bool_from_string(pool_attributes[key], default=pool_attributes[key]) zone_attr = bool_from_string(zone_attributes[key], default=zone_attributes[key]) if not pool_attr == zone_attr: LOG.debug( "%(pool)s did not match requested value of %(key)s. " "Requested: %(r_val)s. Pool: %(p_val)s", { 'pool': pool, 'key': key, 'r_val': zone_attr, 'p_val': pool_attr }) # Value didn't match - remove from the list return False # Pool matches list of attributes - keep return True
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] context.can(ms_policies.POLICY_ROOT % 'migrate_live') host = body["os-migrateLive"]["host"] block_migration = body["os-migrateLive"]["block_migration"] force = None async_ = api_version_request.is_supported(req, min_version='2.34') if api_version_request.is_supported(req, min_version='2.30'): force = self._get_force_param_for_live_migration(body, host) if api_version_request.is_supported(req, min_version='2.25'): if block_migration == 'auto': block_migration = None else: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = None else: disk_over_commit = body["os-migrateLive"]["disk_over_commit"] block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) instance = common.get_instance(self.compute_api, context, id) try: self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host, force, async_) except exception.InstanceUnknownCell as e: raise exc.HTTPNotFound(explanation=e.format_message()) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.MigrationPreCheckError) as ex: if async_: with excutils.save_and_reraise_exception(): LOG.error("Unexpected exception received from " "conductor during pre-live-migration checks " "'%(ex)s'", {'ex': ex}) else: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.ComputeHostNotFound as e: raise exc.HTTPBadRequest(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'os-migrateLive', id)
def _extract_edit_managed_records(self, ctxt, request): ctxt.edit_managed_records = False if 'edit_managed_records' in request.GET: value = request.GET.pop('edit_managed_records') ctxt.edit_managed_records = strutils.bool_from_string(value) elif request.headers.get('X-Designate-Edit-Managed-Records'): ctxt.edit_managed_records = \ strutils.bool_from_string( request.headers.get('X-Designate-Edit-Managed-Records'))
def _extract_all_projects(self, ctxt, request): ctxt.all_tenants = False if request.headers.get('X-Auth-All-Projects'): value = request.headers.get('X-Auth-All-Projects') ctxt.all_tenants = strutils.bool_from_string(value) for i in ('all_projects', 'all_tenants', ): if i in request.GET: value = request.GET.pop(i) ctxt.all_tenants = strutils.bool_from_string(value)
def index(self, req, segment_id): """Returns a list a hosts.""" context = req.environ['masakari.context'] authorize(context) try: filters = {} limit, marker = common.get_limit_and_marker(req) sort_keys, sort_dirs = common.get_sort_params(req.params) segment = objects.FailoverSegment.get_by_uuid(context, segment_id) filters['failover_segment_id'] = segment.uuid if 'name' in req.params: filters['name'] = req.params['name'] if 'type' in req.params: filters['type'] = req.params['type'] if 'control_attributes' in req.params: filters['control_attributes'] = req.params[ 'control_attributes'] if 'on_maintenance' in req.params: try: filters['on_maintenance'] = strutils.bool_from_string( req.params['on_maintenance'], strict=True) except ValueError as ex: msg = _("Invalid value for on_maintenance: " "%s") % encodeutils.exception_to_unicode(ex) raise exc.HTTPBadRequest(explanation=msg) if 'reserved' in req.params: try: filters['reserved'] = strutils.bool_from_string( req.params['reserved'], strict=True) except ValueError as ex: msg = _("Invalid value for reserved: " "%s") % encodeutils.exception_to_unicode(ex) raise exc.HTTPBadRequest(explanation=msg) hosts = self.api.get_all(context, filters=filters, sort_keys=sort_keys, sort_dirs=sort_dirs, limit=limit, marker=marker) except exception.MarkerNotFound as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.Invalid as e: raise exc.HTTPBadRequest(explanation=e.format_message()) except exception.FailoverSegmentNotFound as ex: raise exc.HTTPNotFound(explanation=ex.format_message()) return {'hosts': hosts}
def setUp(self): super(BaseTestCase, self).setUp() self.useFixture(fixtures.FakeLogger()) # If enabled, stdout and/or stderr is captured and will appear in # test results if that test fails. if strutils.bool_from_string(os.environ.get('OS_STDOUT_CAPTURE')): stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) if strutils.bool_from_string(os.environ.get('OS_STDERR_CAPTURE')): stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
def _migrate_live(self, req, id, body): """Permit admins to (live) migrate a server to a new host.""" context = req.environ["nova.context"] authorize(context, action='migrate_live') host = body["os-migrateLive"]["host"] block_migration = body["os-migrateLive"]["block_migration"] force = None if api_version_request.is_supported(req, min_version='2.30'): force = body["os-migrateLive"].get("force", False) force = strutils.bool_from_string(force, strict=True) if force is True and not host: message = _("Can't force to a non-provided destination") raise exc.HTTPBadRequest(explanation=message) if api_version_request.is_supported(req, min_version='2.25'): if block_migration == 'auto': block_migration = None else: block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = None else: disk_over_commit = body["os-migrateLive"]["disk_over_commit"] block_migration = strutils.bool_from_string(block_migration, strict=True) disk_over_commit = strutils.bool_from_string(disk_over_commit, strict=True) try: instance = common.get_instance(self.compute_api, context, id) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host, force) except exception.InstanceUnknownCell as e: raise exc.HTTPNotFound(explanation=e.format_message()) except (exception.NoValidHost, exception.ComputeServiceUnavailable, exception.InvalidHypervisorType, exception.InvalidCPUInfo, exception.UnableToMigrateToSelf, exception.DestinationHypervisorTooOld, exception.InvalidLocalStorage, exception.InvalidSharedStorage, exception.HypervisorUnavailable, exception.MigrationPreCheckError, exception.LiveMigrationWithOldNovaNotSupported) as ex: raise exc.HTTPBadRequest(explanation=ex.format_message()) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'os-migrateLive', id)
def get_replication_config(rep_device_list): """Gather necessary replication configuration info. :param rep_device_list: the replication device list from cinder.conf :returns: rep_config, replication configuration dict """ rep_config = {} if not rep_device_list: return None else: target = rep_device_list[0] try: rep_config['array'] = target['target_device_id'] rep_config['srp'] = target['remote_pool'] rep_config['rdf_group_label'] = target['rdf_group_label'] rep_config['portgroup'] = target['remote_port_group'] except KeyError as ke: error_message = (_("Failed to retrieve all necessary SRDF " "information. Error received: %(ke)s.") % {'ke': six.text_type(ke)}) LOG.exception(error_message) raise exception.VolumeBackendAPIException( message=error_message) allow_extend = target.get('allow_extend', 'false') if strutils.bool_from_string(allow_extend): rep_config['allow_extend'] = True else: rep_config['allow_extend'] = False rep_mode = target.get('mode', '') if rep_mode.lower() in ['async', 'asynchronous']: rep_config['mode'] = REP_ASYNC elif rep_mode.lower() == 'metro': rep_config['mode'] = REP_METRO metro_bias = target.get('metro_use_bias', 'false') if strutils.bool_from_string(metro_bias): rep_config[METROBIAS] = True else: rep_config[METROBIAS] = False allow_delete_metro = target.get('allow_delete_metro', 'false') if strutils.bool_from_string(allow_delete_metro): rep_config['allow_delete_metro'] = True else: rep_config['allow_delete_metro'] = False else: rep_config['mode'] = REP_SYNC return rep_config
def create(self, req, body): """Create a new backup.""" LOG.debug('Creating new backup %s', body) context = req.environ['cinder.context'] req_version = req.api_version_request backup = body['backup'] container = backup.get('container', None) volume_id = backup['volume_id'] self.validate_name_and_description(backup, check_length=False) name = backup.get('name', None) description = backup.get('description', None) incremental = strutils.bool_from_string(backup.get( 'incremental', False), strict=True) force = strutils.bool_from_string(backup.get( 'force', False), strict=True) snapshot_id = backup.get('snapshot_id', None) metadata = backup.get('metadata', None) if req_version.matches( mv.BACKUP_METADATA) else None if req_version.matches(mv.BACKUP_AZ): availability_zone = backup.get('availability_zone', None) else: availability_zone = None az_text = ' in az %s' % availability_zone if availability_zone else '' LOG.info("Creating backup of volume %(volume_id)s in container" " %(container)s%(az)s", {'volume_id': volume_id, 'container': container, 'az': az_text}, context=context) try: new_backup = self.backup_api.create(context, name, description, volume_id, container, incremental, availability_zone, force, snapshot_id, metadata) except (exception.InvalidVolume, exception.InvalidSnapshot, exception.InvalidVolumeMetadata, exception.InvalidVolumeMetadataSize) as error: raise exc.HTTPBadRequest(explanation=error.msg) # Other not found exceptions will be handled at the wsgi level except exception.ServiceNotFound as error: raise exc.HTTPServiceUnavailable(explanation=error.msg) retval = self._view_builder.summary(req, dict(new_backup)) return retval
def _validate(self, bdm_dict): """Basic data format validations.""" dict_fields = set(key for key, _ in six.iteritems(bdm_dict)) # Check that there are no bogus fields if not (dict_fields <= (self._fields | self._db_only_fields)): raise exception.InvalidBDMFormat( details=_("Some fields are invalid.")) if bdm_dict.get('no_device'): return # Check that all required fields are there if (self._required_fields and not ((dict_fields & self._required_fields) == self._required_fields)): raise exception.InvalidBDMFormat( details=_("Some required fields are missing")) if 'delete_on_termination' in bdm_dict: bdm_dict['delete_on_termination'] = strutils.bool_from_string( bdm_dict['delete_on_termination']) if bdm_dict.get('device_name') is not None: validate_device_name(bdm_dict['device_name']) validate_and_default_volume_size(bdm_dict) if bdm_dict.get('boot_index'): try: bdm_dict['boot_index'] = int(bdm_dict['boot_index']) except ValueError: raise exception.InvalidBDMFormat( details=_("Boot index is invalid."))
def validate_public_share_policy(context, api_params, api='create'): """Validates if policy allows is_public parameter to be set to True. :arg api_params - A dictionary of values that may contain 'is_public' :returns api_params with 'is_public' item sanitized if present :raises exception.InvalidParameterValue if is_public is set but is Invalid exception.NotAuthorized if is_public is True but policy prevents it """ if 'is_public' not in api_params: return api_params policies = { 'create': 'create_public_share', 'update': 'set_public_share', } policy_to_check = policies[api] try: api_params['is_public'] = strutils.bool_from_string( api_params['is_public'], strict=True) except ValueError as e: raise exception.InvalidParameterValue(six.text_type(e)) public_shares_allowed = policy.check_policy( context, 'share', policy_to_check, do_raise=False) if api_params['is_public'] and not public_shares_allowed: message = _("User is not authorized to set 'is_public' to True in the " "request.") raise exception.NotAuthorized(message=message) return api_params
def _add_disk_config(self, context, images): for image in images: metadata = image['metadata'] if INTERNAL_DISK_CONFIG in metadata: raw_value = metadata[INTERNAL_DISK_CONFIG] value = strutils.bool_from_string(raw_value) image[API_DISK_CONFIG] = disk_config_to_api(value)
def bmc_reset(self, task, http_method, warm=True): """Reset BMC with IPMI command 'bmc reset (warm|cold)'. :param task: a TaskManager instance. :param http_method: the HTTP method used on the request. :param warm: boolean parameter to decide on warm or cold reset. :raises: IPMIFailure on an error from ipmitool. :raises: MissingParameterValue if a required parameter is missing. :raises: InvalidParameterValue when an invalid value is specified """ node_uuid = task.node.uuid warm = strutils.bool_from_string(warm) if warm: warm_param = 'warm' else: warm_param = 'cold' LOG.debug('Doing %(warm)s BMC reset on node %(node)s', {'warm': warm_param, 'node': node_uuid}) driver_info = _parse_driver_info(task.node) cmd = 'bmc reset %s' % warm_param try: out, err = _exec_ipmitool(driver_info, cmd) LOG.debug('bmc reset returned stdout: %(stdout)s, stderr:' ' %(stderr)s', {'stdout': out, 'stderr': err}) except (exception.PasswordFileFailedToCreate, processutils.ProcessExecutionError) as e: LOG.exception(_LE('IPMI "bmc reset" failed for node %(node_id)s ' 'with error: %(error)s.'), {'node_id': node_uuid, 'error': e}) raise exception.IPMIFailure(cmd=cmd)
def delete(self, req, id, body): """Delete a consistency group.""" LOG.debug('delete called for member %s', id) context = req.environ['cinder.context'] force = False if body: if not self.is_valid_body(body, 'consistencygroup'): msg = _("Missing required element 'consistencygroup' in " "request body.") raise exc.HTTPBadRequest(explanation=msg) cg_body = body['consistencygroup'] try: force = strutils.bool_from_string(cg_body.get('force', False), strict=True) except ValueError: msg = _("Invalid value '%s' for force.") % force raise exc.HTTPBadRequest(explanation=msg) LOG.info(_LI('Delete consistency group with id: %s'), id) try: group = self.consistencygroup_api.get(context, id) self.consistencygroup_api.delete(context, group, force) # Not found exception will be handled at the wsgi level except exception.InvalidConsistencyGroup as error: raise exc.HTTPBadRequest(explanation=error.msg) return webob.Response(status_int=202)
def sync_instances(self, req, body): """Tell all cells to sync instance info.""" context = req.environ['nova.context'] authorize(context) authorize(context, action="sync_instances") project_id = body.pop('project_id', None) deleted = body.pop('deleted', False) updated_since = body.pop('updated_since', None) if body: msg = _("Only 'updated_since', 'project_id' and 'deleted' are " "understood.") raise exc.HTTPBadRequest(explanation=msg) if isinstance(deleted, six.string_types): try: deleted = strutils.bool_from_string(deleted, strict=True) except ValueError as err: raise exc.HTTPBadRequest(explanation=six.text_type(err)) if updated_since: try: timeutils.parse_isotime(updated_since) except ValueError: msg = _('Invalid changes-since value') raise exc.HTTPBadRequest(explanation=msg) self.cells_rpcapi.sync_instances(context, project_id=project_id, updated_since=updated_since, deleted=deleted)
def _set_bootable(self, req, id, body): """Update bootable status of a volume.""" context = req.environ['storage.context'] try: volume = self.volume_api.get(context, id) except exception.VolumeNotFound as error: raise webob.exc.HTTPNotFound(explanation=error.msg) try: bootable = body['os-set_bootable']['bootable'] except KeyError: msg = _("Must specify bootable in request.") raise webob.exc.HTTPBadRequest(explanation=msg) try: bootable = strutils.bool_from_string(bootable, strict=True) except ValueError as error: err_msg = encodeutils.exception_to_unicode(error) msg = _("Invalid value for 'bootable': '%s'") % err_msg raise webob.exc.HTTPBadRequest(explanation=msg) update_dict = {'bootable': bootable} self.volume_api.update(context, volume, update_dict) return webob.Response(status_int=200)
def confirmation_prompt(self): print(self._objects_map.get_count_table()) raw_val = input( _("There are %(count)d objects set for deletion. " "Continue? [y/N]") % dict(count=len(self._objects_map))) return strutils.bool_from_string(raw_val)
def password(self): if self._validate_string(self.args.os_password): return self.args.os_password verify_pass = ( strutils.bool_from_string(cliutils.env("OS_VERIFY_PASSWORD")) ) return self._prompt_password(verify_pass)
def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) environ_enabled = (lambda var_name: strutils.bool_from_string(os.environ.get(var_name))) if environ_enabled('OS_STDOUT_CAPTURE'): stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) if environ_enabled('OS_STDERR_CAPTURE'): stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) self.start = timeutils.utcnow()
def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() test_timeout = os.environ.get("OS_TEST_TIMEOUT", 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) environ_enabled = lambda var_name: strutils.bool_from_string(os.environ.get(var_name)) if environ_enabled("OS_STDOUT_CAPTURE"): stdout = self.useFixture(fixtures.StringStream("stdout")).stream self.useFixture(fixtures.MonkeyPatch("sys.stdout", stdout)) if environ_enabled("OS_STDERR_CAPTURE"): stderr = self.useFixture(fixtures.StringStream("stderr")).stream self.useFixture(fixtures.MonkeyPatch("sys.stderr", stderr)) if environ_enabled("OS_LOG_CAPTURE"): log_format = "%(levelname)s [%(name)s] %(message)s" if environ_enabled("OS_DEBUG"): level = logging.DEBUG else: level = logging.INFO self.useFixture(fixtures.LoggerFixture(nuke_handlers=False, format=log_format, level=level))
def _cloud_create(cs, args, cloud_type=None): try: params = _extract_dict(args.params) except Exception: raise exceptions.CommandError("Unable to convert params to dict: %s" % params) enabled = strutils.bool_from_string(args.enabled) capabilities = _extract_list(args.capabilities) if not params: raise exceptions.CommandError("Connection parameters can't be empty.") kwargs = {'name': args.name, 'driver': args.driver, 'type': cloud_type, 'capabilities': capabilities, 'enabled': enabled, 'params': params} cloud = cs.clouds.create(**kwargs) info = dict() info.update(cloud._info) info['params'] = _dict_to_string(info['params']) info['capabilities'] = _list_to_string(info['capabilities']) if info['type'] == 'destination': info['properties'] = _extract_props(info['properties']) utils.print_dict(info)
def _migrate_volume(self, req, id, body): """Migrate a volume to the specified host.""" context = req.environ['cinder.context'] self.authorize(context, 'migrate_volume') try: volume = self._get(context, id) except exception.NotFound: raise exc.HTTPNotFound() params = body['os-migrate_volume'] try: host = params['host'] except KeyError: raise exc.HTTPBadRequest(explanation=_("Must specify 'host'")) force_host_copy = params.get('force_host_copy', False) if isinstance(force_host_copy, basestring): try: force_host_copy = strutils.bool_from_string(force_host_copy, strict=True) except ValueError: raise exc.HTTPBadRequest( explanation=_("Bad value for 'force_host_copy'")) elif not isinstance(force_host_copy, bool): raise exc.HTTPBadRequest( explanation=_("'force_host_copy' not string or bool")) self.volume_api.migrate_volume(context, volume, host, force_host_copy) return webob.Response(status_int=202)
def get_all(self, context, search_opts=None, sort_key='created_at', sort_dir='desc'): policy.check_policy(context, 'share', 'get_all') if search_opts is None: search_opts = {} LOG.debug("Searching for shares by: %s", six.text_type(search_opts)) # Prepare filters filters = {} if 'metadata' in search_opts: filters['metadata'] = search_opts.pop('metadata') if not isinstance(filters['metadata'], dict): msg = _("Wrong metadata filter provided: " "%s.") % six.text_type(filters['metadata']) raise exception.InvalidInput(reason=msg) if 'extra_specs' in search_opts: # Verify policy for extra-specs access extensions.extension_authorizer('share', 'types_extra_specs')(context) filters['extra_specs'] = search_opts.pop('extra_specs') if not isinstance(filters['extra_specs'], dict): msg = _("Wrong extra specs filter provided: " "%s.") % six.text_type(filters['extra_specs']) raise exception.InvalidInput(reason=msg) if not (isinstance(sort_key, six.string_types) and sort_key): msg = _("Wrong sort_key filter provided: " "'%s'.") % six.text_type(sort_key) raise exception.InvalidInput(reason=msg) if not (isinstance(sort_dir, six.string_types) and sort_dir): msg = _("Wrong sort_dir filter provided: " "'%s'.") % six.text_type(sort_dir) raise exception.InvalidInput(reason=msg) is_public = search_opts.pop('is_public', False) is_public = strutils.bool_from_string(is_public, strict=True) # Get filtered list of shares if 'share_server_id' in search_opts: # NOTE(vponomaryov): this is project_id independent policy.check_policy(context, 'share', 'list_by_share_server_id') shares = self.db.share_get_all_by_share_server( context, search_opts.pop('share_server_id'), filters=filters, sort_key=sort_key, sort_dir=sort_dir) elif (context.is_admin and 'all_tenants' in search_opts): shares = self.db.share_get_all(context, filters=filters, sort_key=sort_key, sort_dir=sort_dir) else: shares = self.db.share_get_all_by_project( context, project_id=context.project_id, filters=filters, is_public=is_public, sort_key=sort_key, sort_dir=sort_dir) # NOTE(vponomaryov): we do not need 'all_tenants' opt anymore search_opts.pop('all_tenants', None) if search_opts: results = [] for s in shares: # values in search_opts can be only strings if all(s.get(k, None) == v for k, v in search_opts.items()): results.append(s) shares = results return shares
def create(self, context, share_proto, size, name, description, snapshot=None, availability_zone=None, metadata=None, share_network_id=None, share_type=None, is_public=False): """Create new share.""" policy.check_policy(context, 'share', 'create') self._check_metadata_properties(context, metadata) if snapshot is not None: if snapshot['status'] != 'available': msg = _("status must be 'available'") raise exception.InvalidShareSnapshot(reason=msg) if not size: size = snapshot['size'] snapshot_id = snapshot['id'] else: snapshot_id = None def as_int(s): try: return int(s) except (ValueError, TypeError): return s # tolerate size as stringified int size = as_int(size) if not isinstance(size, int) or size <= 0: msg = (_("Share size '%s' must be an integer and greater than 0") % size) raise exception.InvalidInput(reason=msg) if snapshot and size < snapshot['size']: msg = (_("Share size '%s' must be equal or greater " "than snapshot size") % size) raise exception.InvalidInput(reason=msg) if snapshot is None: share_type_id = share_type['id'] if share_type else None else: source_share = self.db.share_get(context, snapshot['share_id']) if share_type is None: share_type_id = source_share['share_type_id'] if share_type_id is not None: share_type = share_types.get_share_type( context, share_type_id) else: share_type_id = share_type['id'] if share_type_id != source_share['share_type_id']: msg = _("Invalid share type specified: the requested " "share type must match the type of the source " "share. If a share type is not specified when " "requesting a new share from a snapshot, the " "share type of the source share will be applied " "to the new share.") raise exception.InvalidInput(reason=msg) supported_share_protocols = (proto.upper() for proto in CONF.enabled_share_protocols) if not (share_proto and share_proto.upper() in supported_share_protocols): msg = (_("Invalid share protocol provided: %(provided)s. " "It is either disabled or unsupported. Available " "protocols: %(supported)s") % dict(provided=share_proto, supported=CONF.enabled_share_protocols)) raise exception.InvalidInput(reason=msg) try: reservations = QUOTAS.reserve(context, shares=1, gigabytes=size) except exception.OverQuota as e: overs = e.kwargs['overs'] usages = e.kwargs['usages'] quotas = e.kwargs['quotas'] def _consumed(name): return (usages[name]['reserved'] + usages[name]['in_use']) if 'gigabytes' in overs: LOG.warn( _LW("Quota exceeded for %(s_pid)s, tried to create " "%(s_size)sG share (%(d_consumed)dG of " "%(d_quota)dG already consumed)"), { 's_pid': context.project_id, 's_size': size, 'd_consumed': _consumed('gigabytes'), 'd_quota': quotas['gigabytes'] }) raise exception.ShareSizeExceedsAvailableQuota() elif 'shares' in overs: LOG.warn( _LW("Quota exceeded for %(s_pid)s, tried to create " "share (%(d_consumed)d shares " "already consumed)"), { 's_pid': context.project_id, 'd_consumed': _consumed('shares') }) raise exception.ShareLimitExceeded(allowed=quotas['shares']) if availability_zone is None: availability_zone = CONF.storage_availability_zone try: is_public = strutils.bool_from_string(is_public, strict=True) except ValueError as e: raise exception.InvalidParameterValue(e.message) options = { 'size': size, 'user_id': context.user_id, 'project_id': context.project_id, 'snapshot_id': snapshot_id, 'share_network_id': share_network_id, 'availability_zone': availability_zone, 'metadata': metadata, 'status': "creating", 'scheduled_at': timeutils.utcnow(), 'display_name': name, 'display_description': description, 'share_proto': share_proto, 'share_type_id': share_type_id, 'is_public': is_public, } try: share = self.db.share_create(context, options) QUOTAS.commit(context, reservations) except Exception: with excutils.save_and_reraise_exception(): try: self.db.share_delete(context, share['id']) finally: QUOTAS.rollback(context, reservations) request_spec = { 'share_properties': options, 'share_proto': share_proto, 'share_id': share['id'], 'snapshot_id': snapshot_id, 'share_type': share_type, } filter_properties = {} if (snapshot and not CONF.use_scheduler_creating_share_from_snapshot): # Shares from snapshots with restriction - source host only. # It is common situation for different types of backends. host = snapshot['share']['host'] share = self.db.share_update(context, share['id'], {'host': host}) self.share_rpcapi.create_share( context, share, host, request_spec=request_spec, filter_properties=filter_properties, snapshot_id=snapshot_id, ) else: # Shares from scratch and from snapshots when source host is not # the only allowed, it is possible, for example, in multibackend # installation with Generic drivers only. self.scheduler_rpcapi.create_share( context, CONF.share_topic, share['id'], snapshot_id, request_spec=request_spec, filter_properties=filter_properties, ) return share
def update(self, req, id, body): """Update Quota for a particular tenant This works for hierarchical and non-hierarchical projects. For hierarchical projects only immediate parent admin or the CLOUD admin are able to perform an update. :param req: request :param id: target project id that needs to be updated :param body: key, value pair that that will be applied to the resources if the update succeeds """ context = req.environ['cinder.context'] authorize_update(context) self.validate_string_length(id, 'quota_set_name', min_length=1, max_length=255) self.assert_valid_body(body, 'quota_set') # Get the optional argument 'skip_validation' from body, # if skip_validation is False, then validate existing resource. skip_flag = body.get('skip_validation', True) if not utils.is_valid_boolstr(skip_flag): msg = _("Invalid value '%s' for skip_validation.") % skip_flag raise exception.InvalidParameterValue(err=msg) skip_flag = strutils.bool_from_string(skip_flag) target_project_id = id bad_keys = [] # NOTE(ankit): Pass #1 - In this loop for body['quota_set'].items(), # we figure out if we have any bad keys. for key, value in body['quota_set'].items(): if (key not in QUOTAS and key not in NON_QUOTA_KEYS): bad_keys.append(key) continue if len(bad_keys) > 0: msg = _("Bad key(s) in quota set: %s") % ",".join(bad_keys) raise webob.exc.HTTPBadRequest(explanation=msg) # Saving off this value since we need to use it multiple times use_nested_quotas = QUOTAS.using_nested_quotas() if use_nested_quotas: # Get the parent_id of the target project to verify whether we are # dealing with hierarchical namespace or non-hierarchical namespace target_project = quota_utils.get_project_hierarchy( context, target_project_id, parents_as_ids=True) parent_id = target_project.parent_id if parent_id: # Get the children of the project which the token is scoped to # in order to know if the target_project is in its hierarchy. context_project = quota_utils.get_project_hierarchy( context, context.project_id, subtree_as_ids=True) self._authorize_update_or_delete(context_project, target_project.id, parent_id) # NOTE(ankit): Pass #2 - In this loop for body['quota_set'].keys(), # we validate the quota limits to ensure that we can bail out if # any of the items in the set is bad. Meanwhile we validate value # to ensure that the value can't be lower than number of existing # resources. quota_values = QUOTAS.get_project_quotas(context, target_project_id, defaults=False) valid_quotas = {} reservations = [] for key in body['quota_set'].keys(): if key in NON_QUOTA_KEYS: continue value = self.validate_integer(body['quota_set'][key], key, min_value=-1, max_value=db.MAX_INT) # Can't skip the validation of nested quotas since it could mess up # hierarchy if parent limit is less than childrens' current usage if not skip_flag or use_nested_quotas: self._validate_existing_resource(key, value, quota_values) if use_nested_quotas: try: reservations += self._update_nested_quota_allocated( context, target_project, quota_values, key, value) except exception.OverQuota as e: if reservations: db.reservation_rollback(context, reservations) raise webob.exc.HTTPBadRequest(explanation=e.message) valid_quotas[key] = value # NOTE(ankit): Pass #3 - At this point we know that all the keys and # values are valid and we can iterate and update them all in one shot # without having to worry about rolling back etc as we have done # the validation up front in the 2 loops above. for key, value in valid_quotas.items(): try: db.quota_update(context, target_project_id, key, value) except exception.ProjectQuotaNotFound: db.quota_create(context, target_project_id, key, value) except exception.AdminRequired: raise webob.exc.HTTPForbidden() if reservations: db.reservation_commit(context, reservations) return {'quota_set': self._get_quotas(context, target_project_id)}
def prepare_ramdisk(self, task, ramdisk_params): """Prepares the boot of Ironic ramdisk using PXE. This method prepares the boot of the deploy or rescue kernel/ramdisk after reading relevant information from the node's driver_info and instance_info. :param task: a task from TaskManager. :param ramdisk_params: the parameters to be passed to the ramdisk. pxe driver passes these parameters as kernel command-line arguments. :param mode: Label indicating a deploy or rescue operation being carried out on the node. Supported values are 'deploy' and 'rescue'. Defaults to 'deploy', indicating deploy operation is being carried out. :returns: None :raises: MissingParameterValue, if some information is missing in node's driver_info or instance_info. :raises: InvalidParameterValue, if some information provided is invalid. :raises: IronicException, if some power or set boot boot device operation failed on the node. """ node = task.node mode = deploy_utils.rescue_or_deploy_mode(node) ipxe_enabled = CONF.pxe.ipxe_enabled if ipxe_enabled: # NOTE(mjturek): At this point, the ipxe boot script should # already exist as it is created at startup time. However, we # call the boot script create method here to assert its # existence and handle the unlikely case that it wasn't created # or was deleted. pxe_utils.create_ipxe_boot_script() dhcp_opts = pxe_utils.dhcp_options_for_instance( task, ipxe_enabled=ipxe_enabled) provider = dhcp_factory.DHCPFactory() provider.update_dhcp(task, dhcp_opts) pxe_info = pxe_utils.get_image_info(node, mode=mode) # NODE: Try to validate and fetch instance images only # if we are in DEPLOYING state. if node.provision_state == states.DEPLOYING: pxe_info.update(pxe_utils.get_instance_image_info(task)) boot_mode_utils.sync_boot_mode(task) pxe_options = pxe_utils.build_pxe_config_options( task, pxe_info, ipxe_enabled=ipxe_enabled) pxe_options.update(ramdisk_params) pxe_config_template = deploy_utils.get_pxe_config_template(node) pxe_utils.create_pxe_config(task, pxe_options, pxe_config_template, ipxe_enabled=CONF.pxe.ipxe_enabled) persistent = False value = node.driver_info.get('force_persistent_boot_device', 'Default') if value in {'Always', 'Default', 'Never'}: if value == 'Always': persistent = True else: persistent = strutils.bool_from_string(value, False) manager_utils.node_set_boot_device(task, boot_devices.PXE, persistent=persistent) if CONF.pxe.ipxe_enabled and CONF.pxe.ipxe_use_swift: kernel_label = '%s_kernel' % mode ramdisk_label = '%s_ramdisk' % mode pxe_info.pop(kernel_label, None) pxe_info.pop(ramdisk_label, None) if pxe_info: pxe_utils.cache_ramdisk_kernel(task, pxe_info, ipxe_enabled=CONF.pxe.ipxe_enabled)
def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() # Create default notifier self.notifier = fake_notifier.get_fake_notifier() # Mock rpc get notifier with fake notifier method that joins all # notifications with the default notifier p = mock.patch('miper.rpc.get_notifier', side_effect=self._get_joined_notifier) p.start() # Import miper objects for test cases objects.register_all() # Unit tests do not need to use lazy gettext i18n.enable_lazy(False) test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) environ_enabled = (lambda var_name: strutils.bool_from_string( os.environ.get(var_name))) if environ_enabled('OS_STDOUT_CAPTURE'): stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) if environ_enabled('OS_STDERR_CAPTURE'): stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) self.useFixture(log_fixture.get_logging_handle_error_fixture()) self.useFixture(miper_fixtures.StandardLogging()) rpc.add_extra_exmods("miper.tests.unit") self.addCleanup(rpc.clear_extra_exmods) self.addCleanup(rpc.cleanup) self.messaging_conf = messaging_conffixture.ConfFixture(CONF) self.messaging_conf.transport_driver = 'fake' self.messaging_conf.response_timeout = 15 self.useFixture(self.messaging_conf) rpc.init(CONF) conf_fixture.set_defaults(CONF) CONF([], default_config_files=[]) # NOTE(vish): We need a better method for creating fixtures for tests # now that we have some required db setup for the system # to work properly. self.start = timeutils.utcnow() CONF.set_default('connection', 'sqlite://', 'database') CONF.set_default('sqlite_synchronous', False, 'database') global _DB_CACHE if not _DB_CACHE: _DB_CACHE = Database(sqla_api, migration, sql_connection=CONF.database.connection, sqlite_db=CONF.database.sqlite_db, sqlite_clean_db=CONF.sqlite_clean_db) self.useFixture(_DB_CACHE) # emulate some of the mox stuff, we can't use the metaclass # because it screws with our generators mox_fixture = self.useFixture(moxstubout.MoxStubout()) self.mox = mox_fixture.mox self.stubs = mox_fixture.stubs self.addCleanup(CONF.reset) self.addCleanup(self._common_cleanup) self.injected = [] self._services = [] fake_notifier.stub_notifier(self.stubs) self.override_config('fatal_exception_format_errors', True) # This will be cleaned up by the NestedTempfile fixture lock_path = self.useFixture(fixtures.TempDir()).path self.fixture = self.useFixture(config_fixture.Config(lockutils.CONF)) self.fixture.config(lock_path=lock_path, group='oslo_concurrency') lockutils.set_defaults(lock_path) self.override_config('policy_file', os.path.join( os.path.abspath( os.path.join( os.path.dirname(__file__), '..', )), 'miper/tests/unit/policy.json'), group='oslo_policy') self._disable_osprofiler()
def _is_magnum_auto_healer_running(self): auto_healing = self.cluster.labels.get("auto_healing_enabled") auto_healing_enabled = strutils.bool_from_string(auto_healing) controller = self.cluster.labels.get("auto_healing_controller") return (auto_healing_enabled and controller == "magnum-auto-healer")
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None, swap=0, rxtx_factor=1.0, is_public=True, description=None): """Creates flavors.""" if not flavorid: flavorid = uuidutils.generate_uuid() kwargs = { 'memory_mb': memory, 'vcpus': vcpus, 'root_gb': root_gb, 'ephemeral_gb': ephemeral_gb, 'swap': swap, 'rxtx_factor': rxtx_factor, 'description': description } if isinstance(name, str): name = name.strip() # NOTE(vish): Internally, flavorid is stored as a string but it comes # in through json as an integer, so we convert it here. flavorid = str(flavorid) # NOTE(wangbo): validate attributes of the creating flavor. # ram and vcpus should be positive ( > 0) integers. # disk, ephemeral and swap should be non-negative ( >= 0) integers. flavor_attributes = { 'memory_mb': ('ram', 1), 'vcpus': ('vcpus', 1), 'root_gb': ('disk', 0), 'ephemeral_gb': ('ephemeral', 0), 'swap': ('swap', 0) } for key, value in flavor_attributes.items(): kwargs[key] = utils.validate_integer(kwargs[key], value[0], value[1], db_const.MAX_INT) # rxtx_factor should be a positive float try: kwargs['rxtx_factor'] = float(kwargs['rxtx_factor']) if (kwargs['rxtx_factor'] <= 0 or kwargs['rxtx_factor'] > db_const.SQL_SP_FLOAT_MAX): raise ValueError() except ValueError: msg = _("'rxtx_factor' argument must be a float between 0 and %g") raise exception.InvalidInput(reason=msg % db_const.SQL_SP_FLOAT_MAX) kwargs['name'] = name kwargs['flavorid'] = flavorid # ensure is_public attribute is boolean try: kwargs['is_public'] = strutils.bool_from_string(is_public, strict=True) except ValueError: raise exception.InvalidInput(reason=_("is_public must be a boolean")) flavor = objects.Flavor(context=context.get_admin_context(), **kwargs) flavor.create() return flavor
def test_bool_bool_from_string(self): self.assertTrue(strutils.bool_from_string(True)) self.assertFalse(strutils.bool_from_string(False))
def test_bool_bool_from_string_no_text(self, mock_text): self.assertTrue(strutils.bool_from_string(True)) self.assertFalse(strutils.bool_from_string(False)) self.assertEqual(0, mock_text.call_count)
def test_bool_bool_from_string_default(self): self.assertTrue(strutils.bool_from_string('', default=True)) self.assertFalse(strutils.bool_from_string('wibble', default=False))
def _test_bool_from_string(self, c): self.assertTrue(strutils.bool_from_string(c('true'))) self.assertTrue(strutils.bool_from_string(c('TRUE'))) self.assertTrue(strutils.bool_from_string(c('on'))) self.assertTrue(strutils.bool_from_string(c('On'))) self.assertTrue(strutils.bool_from_string(c('yes'))) self.assertTrue(strutils.bool_from_string(c('YES'))) self.assertTrue(strutils.bool_from_string(c('yEs'))) self.assertTrue(strutils.bool_from_string(c('1'))) self.assertTrue(strutils.bool_from_string(c('T'))) self.assertTrue(strutils.bool_from_string(c('t'))) self.assertTrue(strutils.bool_from_string(c('Y'))) self.assertTrue(strutils.bool_from_string(c('y'))) self.assertFalse(strutils.bool_from_string(c('false'))) self.assertFalse(strutils.bool_from_string(c('FALSE'))) self.assertFalse(strutils.bool_from_string(c('off'))) self.assertFalse(strutils.bool_from_string(c('OFF'))) self.assertFalse(strutils.bool_from_string(c('no'))) self.assertFalse(strutils.bool_from_string(c('0'))) self.assertFalse(strutils.bool_from_string(c('42'))) self.assertFalse(strutils.bool_from_string(c( 'This should not be True'))) self.assertFalse(strutils.bool_from_string(c('F'))) self.assertFalse(strutils.bool_from_string(c('f'))) self.assertFalse(strutils.bool_from_string(c('N'))) self.assertFalse(strutils.bool_from_string(c('n'))) # Whitespace should be stripped self.assertTrue(strutils.bool_from_string(c(' 1 '))) self.assertTrue(strutils.bool_from_string(c(' true '))) self.assertFalse(strutils.bool_from_string(c(' 0 '))) self.assertFalse(strutils.bool_from_string(c(' false ')))
def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() # Create default notifier self.notifier = fake_notifier.get_fake_notifier() # Mock rpc get notifier with fake notifier method that joins all # notifications with the default notifier p = mock.patch('cinder.rpc.get_notifier', side_effect=self._get_joined_notifier) p.start() # Unit tests do not need to use lazy gettext i18n.enable_lazy(False) test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) environ_enabled = (lambda var_name: strutils.bool_from_string( os.environ.get(var_name))) if environ_enabled('OS_STDOUT_CAPTURE'): stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) if environ_enabled('OS_STDERR_CAPTURE'): stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) if environ_enabled('OS_LOG_CAPTURE'): log_format = '%(levelname)s [%(name)s] %(message)s' if environ_enabled('OS_DEBUG'): level = logging.DEBUG else: level = logging.INFO self.useFixture( fixtures.LoggerFixture(nuke_handlers=False, format=log_format, level=level)) rpc.add_extra_exmods("cinder.tests.unit") self.addCleanup(rpc.clear_extra_exmods) self.addCleanup(rpc.cleanup) self.messaging_conf = messaging_conffixture.ConfFixture(CONF) self.messaging_conf.transport_driver = 'fake' self.messaging_conf.response_timeout = 15 self.useFixture(self.messaging_conf) rpc.init(CONF) conf_fixture.set_defaults(CONF) CONF([], default_config_files=[]) # NOTE(vish): We need a better method for creating fixtures for tests # now that we have some required db setup for the system # to work properly. self.start = timeutils.utcnow() CONF.set_default('connection', 'sqlite://', 'database') CONF.set_default('sqlite_synchronous', False, 'database') global _DB_CACHE if not _DB_CACHE: _DB_CACHE = Database(sqla_api, migration, sql_connection=CONF.database.connection, sqlite_db=CONF.database.sqlite_db, sqlite_clean_db=CONF.sqlite_clean_db) self.useFixture(_DB_CACHE) # NOTE(danms): Make sure to reset us back to non-remote objects # for each test to avoid interactions. Also, backup the object # registry. objects_base.CinderObject.indirection_api = None self._base_test_obj_backup = copy.copy( objects_base.CinderObjectRegistry._registry._obj_classes) self.addCleanup(self._restore_obj_registry) # emulate some of the mox stuff, we can't use the metaclass # because it screws with our generators mox_fixture = self.useFixture(moxstubout.MoxStubout()) self.mox = mox_fixture.mox self.stubs = mox_fixture.stubs self.addCleanup(CONF.reset) self.addCleanup(self._common_cleanup) self.injected = [] self._services = [] fake_notifier.stub_notifier(self.stubs) self.override_config('fatal_exception_format_errors', True) # This will be cleaned up by the NestedTempfile fixture lock_path = self.useFixture(fixtures.TempDir()).path self.fixture = self.useFixture(config_fixture.Config(lockutils.CONF)) self.fixture.config(lock_path=lock_path, group='oslo_concurrency') lockutils.set_defaults(lock_path) self.override_config('policy_file', os.path.join( os.path.abspath( os.path.join( os.path.dirname(__file__), '..', )), 'cinder/tests/unit/policy.json'), group='oslo_policy') self._disable_osprofiler() # NOTE(geguileo): This is required because common get_by_id method in # cinder.db.sqlalchemy.api caches get methods and if we use a mocked # get method in one test it would carry on to the next test. So we # clear out the cache. sqla_api._GET_METHODS = {}
def get_base_parser(self, argv): parser = NovaClientArgumentParser( prog='nova', description=__doc__.strip(), epilog='See "nova help COMMAND" ' 'for help on a specific command.', add_help=False, formatter_class=OpenStackHelpFormatter, ) # Global arguments parser.add_argument( '-h', '--help', action='store_true', help=argparse.SUPPRESS, ) parser.add_argument('--version', action='version', version=novaclient.__version__) parser.add_argument('--debug', default=False, action='store_true', help=_("Print debugging output.")) parser.add_argument( '--os-cache', default=strutils.bool_from_string( utils.env('OS_CACHE', default=False), True), action='store_true', help=_("Use the auth token cache. Defaults to False if " "env[OS_CACHE] is not set.")) parser.add_argument('--timings', default=False, action='store_true', help=_("Print call timing info.")) parser.add_argument('--os-region-name', metavar='<region-name>', default=utils.env('OS_REGION_NAME', 'NOVA_REGION_NAME'), help=_('Defaults to env[OS_REGION_NAME].')) parser.add_argument('--service-type', metavar='<service-type>', help=_('Defaults to compute for most actions.')) parser.add_argument('--service-name', metavar='<service-name>', default=utils.env('NOVA_SERVICE_NAME'), help=_('Defaults to env[NOVA_SERVICE_NAME].')) parser.add_argument('--os-endpoint-type', metavar='<endpoint-type>', dest='endpoint_type', default=utils.env( 'NOVA_ENDPOINT_TYPE', default=utils.env( 'OS_ENDPOINT_TYPE', default=DEFAULT_NOVA_ENDPOINT_TYPE)), help=_('Defaults to env[NOVA_ENDPOINT_TYPE], ' 'env[OS_ENDPOINT_TYPE] or ') + DEFAULT_NOVA_ENDPOINT_TYPE + '.') parser.add_argument( '--os-compute-api-version', metavar='<compute-api-ver>', default=utils.env('OS_COMPUTE_API_VERSION', default=DEFAULT_OS_COMPUTE_API_VERSION), help=_('Accepts X, X.Y (where X is major and Y is minor part) or ' '"X.latest", defaults to env[OS_COMPUTE_API_VERSION].')) parser.add_argument( '--os-endpoint-override', metavar='<bypass-url>', dest='endpoint_override', default=utils.env('OS_ENDPOINT_OVERRIDE', 'NOVACLIENT_ENDPOINT_OVERRIDE', 'NOVACLIENT_BYPASS_URL'), help=_("Use this API endpoint instead of the Service Catalog. " "Defaults to env[OS_ENDPOINT_OVERRIDE].")) parser.set_defaults(func=self.do_help) parser.set_defaults(command='') if osprofiler_profiler: parser.add_argument('--profile', metavar='HMAC_KEY', default=utils.env('OS_PROFILE'), help='HMAC key to use for encrypting context ' 'data for performance profiling of operation. ' 'This key should be the value of the HMAC key ' 'configured for the OSprofiler middleware in ' 'nova; it is specified in the Nova ' 'configuration file at "/etc/nova/nova.conf". ' 'Without the key, profiling will not be ' 'triggered even if OSprofiler is enabled on ' 'the server side.') self._append_global_identity_args(parser, argv) return parser
def coerce(obj, attr, value): return strutils.bool_from_string(value)
def test_int_bool_from_string(self): self.assertTrue(strutils.bool_from_string(1)) self.assertFalse(strutils.bool_from_string(-1)) self.assertFalse(strutils.bool_from_string(0)) self.assertFalse(strutils.bool_from_string(2))
def get_base_parser(self): parser = NovaClientArgumentParser( prog='nova', description=__doc__.strip(), epilog='See "nova help COMMAND" ' 'for help on a specific command.', add_help=False, formatter_class=OpenStackHelpFormatter, ) # Global arguments parser.add_argument( '-h', '--help', action='store_true', help=argparse.SUPPRESS, ) parser.add_argument('--version', action='version', version=novaclient.__version__) parser.add_argument('--debug', default=False, action='store_true', help=_("Print debugging output")) parser.add_argument( '--os-cache', default=strutils.bool_from_string( cliutils.env('OS_CACHE', default=False), True), action='store_true', help=_("Use the auth token cache. Defaults to False if " "env[OS_CACHE] is not set.")) parser.add_argument('--timings', default=False, action='store_true', help=_("Print call timing info")) parser.add_argument('--os-auth-token', default=cliutils.env('OS_AUTH_TOKEN'), help='Defaults to env[OS_AUTH_TOKEN]') parser.add_argument('--os_username', help=argparse.SUPPRESS) parser.add_argument('--os_password', help=argparse.SUPPRESS) parser.add_argument('--os-tenant-name', metavar='<auth-tenant-name>', default=cliutils.env('OS_TENANT_NAME', 'NOVA_PROJECT_ID'), help=_('Defaults to env[OS_TENANT_NAME].')) parser.add_argument('--os_tenant_name', help=argparse.SUPPRESS) parser.add_argument('--os-tenant-id', metavar='<auth-tenant-id>', default=cliutils.env('OS_TENANT_ID'), help=_('Defaults to env[OS_TENANT_ID].')) parser.add_argument('--os_auth_url', help=argparse.SUPPRESS) parser.add_argument('--os-region-name', metavar='<region-name>', default=cliutils.env('OS_REGION_NAME', 'NOVA_REGION_NAME'), help=_('Defaults to env[OS_REGION_NAME].')) parser.add_argument('--os_region_name', help=argparse.SUPPRESS) parser.add_argument('--os-auth-system', metavar='<auth-system>', default=cliutils.env('OS_AUTH_SYSTEM'), help='Defaults to env[OS_AUTH_SYSTEM].') parser.add_argument('--os_auth_system', help=argparse.SUPPRESS) parser.add_argument('--service-type', metavar='<service-type>', help=_('Defaults to compute for most actions')) parser.add_argument('--service_type', help=argparse.SUPPRESS) parser.add_argument('--service-name', metavar='<service-name>', default=cliutils.env('NOVA_SERVICE_NAME'), help=_('Defaults to env[NOVA_SERVICE_NAME]')) parser.add_argument('--service_name', help=argparse.SUPPRESS) parser.add_argument( '--volume-service-name', metavar='<volume-service-name>', default=cliutils.env('NOVA_VOLUME_SERVICE_NAME'), help=_('Defaults to env[NOVA_VOLUME_SERVICE_NAME]')) parser.add_argument('--volume_service_name', help=argparse.SUPPRESS) parser.add_argument('--os-endpoint-type', metavar='<endpoint-type>', dest='endpoint_type', default=cliutils.env( 'NOVA_ENDPOINT_TYPE', default=cliutils.env( 'OS_ENDPOINT_TYPE', default=DEFAULT_NOVA_ENDPOINT_TYPE)), help=_('Defaults to env[NOVA_ENDPOINT_TYPE], ' 'env[OS_ENDPOINT_TYPE] or ') + DEFAULT_NOVA_ENDPOINT_TYPE + '.') parser.add_argument('--endpoint-type', help=argparse.SUPPRESS) # NOTE(dtroyer): We can't add --endpoint_type here due to argparse # thinking usage-list --end is ambiguous; but it # works fine with only --endpoint-type present # Go figure. I'm leaving this here for doc purposes. # parser.add_argument('--endpoint_type', # help=argparse.SUPPRESS) parser.add_argument('--os-compute-api-version', metavar='<compute-api-ver>', default=cliutils.env( 'OS_COMPUTE_API_VERSION', default=DEFAULT_OS_COMPUTE_API_VERSION), help=_('Accepts 1.1 or 3, ' 'defaults to env[OS_COMPUTE_API_VERSION].')) parser.add_argument('--os_compute_api_version', help=argparse.SUPPRESS) parser.add_argument( '--bypass-url', metavar='<bypass-url>', dest='bypass_url', default=cliutils.env('NOVACLIENT_BYPASS_URL'), help="Use this API endpoint instead of the Service Catalog. " "Defaults to env[NOVACLIENT_BYPASS_URL]") parser.add_argument('--bypass_url', help=argparse.SUPPRESS) # The auth-system-plugins might require some extra options novaclient.auth_plugin.load_auth_system_opts(parser) self._append_global_identity_args(parser) return parser
def create(name, memory, vcpus, root_gb, ephemeral_gb=0, flavorid=None, swap=0, rxtx_factor=1.0, is_public=True): """Creates flavors.""" if not flavorid: flavorid = uuid.uuid4() kwargs = { 'memory_mb': memory, 'vcpus': vcpus, 'root_gb': root_gb, 'ephemeral_gb': ephemeral_gb, 'swap': swap, 'rxtx_factor': rxtx_factor, } if isinstance(name, six.string_types): name = name.strip() # ensure name do not exceed 255 characters utils.check_string_length(name, 'name', min_length=1, max_length=255) # ensure name does not contain any special characters valid_name = VALID_NAME_REGEX.search(name) if not valid_name: msg = _("Flavor names can only contain printable characters " "and horizontal spaces.") raise exception.InvalidInput(reason=msg) # NOTE(vish): Internally, flavorid is stored as a string but it comes # in through json as an integer, so we convert it here. flavorid = six.text_type(flavorid) # ensure leading/trailing whitespaces not present. if flavorid.strip() != flavorid: msg = _("id cannot contain leading and/or trailing whitespace(s)") raise exception.InvalidInput(reason=msg) # ensure flavor id does not exceed 255 characters utils.check_string_length(flavorid, 'id', min_length=1, max_length=255) # ensure flavor id does not contain any special characters valid_flavor_id = VALID_ID_REGEX.search(flavorid) if not valid_flavor_id: msg = _("Flavor id can only contain letters from A-Z (both cases), " "periods, dashes, underscores and spaces.") raise exception.InvalidInput(reason=msg) # NOTE(wangbo): validate attributes of the creating flavor. # ram and vcpus should be positive ( > 0) integers. # disk, ephemeral and swap should be non-negative ( >= 0) integers. flavor_attributes = { 'memory_mb': ('ram', 1), 'vcpus': ('vcpus', 1), 'root_gb': ('disk', 0), 'ephemeral_gb': ('ephemeral', 0), 'swap': ('swap', 0) } for key, value in flavor_attributes.items(): kwargs[key] = utils.validate_integer(kwargs[key], value[0], value[1], db.MAX_INT) # rxtx_factor should be a positive float try: kwargs['rxtx_factor'] = float(kwargs['rxtx_factor']) if (kwargs['rxtx_factor'] <= 0 or kwargs['rxtx_factor'] > SQL_SP_FLOAT_MAX): raise ValueError() except ValueError: msg = (_("'rxtx_factor' argument must be a float between 0 and %g") % SQL_SP_FLOAT_MAX) raise exception.InvalidInput(reason=msg) kwargs['name'] = name kwargs['flavorid'] = flavorid # ensure is_public attribute is boolean try: kwargs['is_public'] = strutils.bool_from_string(is_public, strict=True) except ValueError: raise exception.InvalidInput(reason=_("is_public must be a boolean")) flavor = objects.Flavor(context=context.get_admin_context(), **kwargs) flavor.create() return flavor
def _poll_health_status(self, k8s_api): """Poll health status of API and nodes for given cluster Design Policy: 1. How to calculate the overall health status? Any node (including API and minion nodes) is not OK, then the overall health status is UNHEALTHY 2. The data structure of health_status_reason As an attribute of the cluster, the health_status_reason have to use the field type from oslo.versionedobjects/blob/master/oslo_versionedobjects/fields.py 3. How to get the health_status and health_status_reason? 3.1 Call /healthz to get the API health status 3.2 Call list_node (using API /api/v1/nodes) to get the nodes health status :param k8s_api: The api client to the cluster :return: Tumple including status and reason. Example: ( ClusterHealthStatus.HEALTHY, { 'api': 'ok', 'k8scluster-ydz7cfbxqqu3-node-0.Ready': False, 'k8scluster-ydz7cfbxqqu3-node-1.Ready': True, 'k8scluster-ydz7cfbxqqu3-node-2.Ready': True, } ) """ health_status = m_fields.ClusterHealthStatus.UNHEALTHY health_status_reason = {} api_status = None try: api_status = k8s_api.get_healthz() for node in k8s_api.list_node()['items']: node_key = node['metadata']['name'] + ".Ready" ready = False for condition in node['status']['conditions']: if condition['type'] == 'Ready': ready = strutils.bool_from_string(condition['status']) break health_status_reason[node_key] = ready if (api_status == 'ok' and all(n for n in health_status_reason.values())): health_status = m_fields.ClusterHealthStatus.HEALTHY health_status_reason['api'] = api_status except Exception as exp_api: if not api_status: api_status = (getattr(exp_api, 'body', None) or getattr(exp_api, 'message', None)) if api_status is not None: health_status_reason['api'] = api_status return health_status, health_status_reason
def update(self, req, id, body): """Perform service update Starting with microversion 2.53, the service uuid is passed in on the path of the request to uniquely identify the service record on which to perform a given update, which is defined in the body of the request. """ service_id = id # Validate that the service ID is a UUID. if not uuidutils.is_uuid_like(service_id): msg = _('Invalid uuid %s') % service_id raise webob.exc.HTTPBadRequest(explanation=msg) # Validate the request context against the policy. context = req.environ['nova.context'] context.can(services_policies.BASE_POLICY_NAME) # Get the service by uuid. try: service = self.host_api.service_get_by_id(context, service_id) # At this point the context is targeted to the cell that the # service was found in so we don't need to do any explicit cell # targeting below. except exception.ServiceNotFound as e: raise webob.exc.HTTPNotFound(explanation=e.format_message()) # Return 400 if service.binary is not nova-compute. # Before the earlier PUT handlers were made cells-aware, you could # technically disable a nova-scheduler service, although that doesn't # really do anything within Nova and is just confusing. Now trying to # do that will fail as a nova-scheduler service won't have a host # mapping so you'll get a 404. In this new microversion, we close that # old gap and make sure you can only enable/disable and set forced_down # on nova-compute services since those are the only ones that make # sense to update for those operations. if service.binary != 'nova-compute': msg = (_('Updating a %(binary)s service is not supported. Only ' 'nova-compute services can be updated.') % { 'binary': service.binary }) raise webob.exc.HTTPBadRequest(explanation=msg) # Now determine the update to perform based on the body. We are # intentionally not using _perform_action or the other old-style # action functions. if 'status' in body: # This is a status update for either enabled or disabled. if body['status'] == 'enabled': # Fail if 'disabled_reason' was requested when enabling the # service since those two combined don't make sense. if body.get('disabled_reason'): msg = _("Specifying 'disabled_reason' with status " "'enabled' is invalid.") raise webob.exc.HTTPBadRequest(explanation=msg) service.disabled = False service.disabled_reason = None elif body['status'] == 'disabled': service.disabled = True # The disabled reason is optional. service.disabled_reason = body.get('disabled_reason') # This is intentionally not an elif, i.e. it's in addition to the # status update. if 'forced_down' in body: service.forced_down = strutils.bool_from_string( body['forced_down'], strict=True) # Check to see if anything was actually updated since the schema does # not define any required fields. if not service.obj_what_changed(): msg = _("No updates were requested. Fields 'status' or " "'forced_down' should be specified.") raise webob.exc.HTTPBadRequest(explanation=msg) # Now save our updates to the service record in the database. service.save() # Return the full service record details. additional_fields = ['forced_down'] return { 'service': self._get_service_detail(service, additional_fields, req) }
def get_base_parser(self): parser = ZunClientArgumentParser( prog='zun', description=__doc__.strip(), epilog='See "zun help COMMAND" ' 'for help on a specific command.', add_help=False, formatter_class=OpenStackHelpFormatter, ) # Global arguments parser.add_argument('-h', '--help', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--version', action='version', version=version.version_info.version_string()) parser.add_argument('--debug', default=False, action='store_true', help="Print debugging output.") parser.add_argument('--os-cache', default=strutils.bool_from_string( cliutils.env('OS_CACHE', default=False)), action='store_true', help="Use the auth token cache. Defaults to False " "if env[OS_CACHE] is not set.") parser.add_argument('--os-region-name', metavar='<region-name>', default=os.environ.get('OS_REGION_NAME'), help='Region name. Default=env[OS_REGION_NAME].') # TODO(mattf) - add get_timings support to Client # parser.add_argument('--timings', # default=False, # action='store_true', # help="Print call timing info") # TODO(mattf) - use timeout # parser.add_argument('--timeout', # default=600, # metavar='<seconds>', # type=positive_non_zero_float, # help="Set HTTP call timeout (in seconds)") parser.add_argument('--os-project-id', metavar='<auth-project-id>', default=cliutils.env('OS_PROJECT_ID', default=None), help='Defaults to env[OS_PROJECT_ID].') parser.add_argument('--os-project-name', metavar='<auth-project-name>', default=cliutils.env('OS_PROJECT_NAME', default=None), help='Defaults to env[OS_PROJECT_NAME].') parser.add_argument('--os-user-domain-id', metavar='<auth-user-domain-id>', default=cliutils.env('OS_USER_DOMAIN_ID'), help='Defaults to env[OS_USER_DOMAIN_ID].') parser.add_argument('--os-user-domain-name', metavar='<auth-user-domain-name>', default=cliutils.env('OS_USER_DOMAIN_NAME'), help='Defaults to env[OS_USER_DOMAIN_NAME].') parser.add_argument('--os-project-domain-id', metavar='<auth-project-domain-id>', default=cliutils.env('OS_PROJECT_DOMAIN_ID'), help='Defaults to env[OS_PROJECT_DOMAIN_ID].') parser.add_argument('--os-project-domain-name', metavar='<auth-project-domain-name>', default=cliutils.env('OS_PROJECT_DOMAIN_NAME'), help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') parser.add_argument('--service-type', metavar='<service-type>', help='Defaults to container for all ' 'actions.') parser.add_argument('--service_type', help=argparse.SUPPRESS) parser.add_argument('--endpoint-type', metavar='<endpoint-type>', default=cliutils.env( 'OS_ENDPOINT_TYPE', default=DEFAULT_ENDPOINT_TYPE), help='Defaults to env[OS_ENDPOINT_TYPE] or ' + DEFAULT_ENDPOINT_TYPE + '.') # NOTE(dtroyer): We can't add --endpoint_type here due to argparse # thinking usage-list --end is ambiguous; but it # works fine with only --endpoint-type present # Go figure. I'm leaving this here for doc purposes. # parser.add_argument('--endpoint_type', # help=argparse.SUPPRESS) parser.add_argument('--zun-api-version', metavar='<zun-api-ver>', default=cliutils.env('ZUN_API_VERSION', default=DEFAULT_API_VERSION), help='Accepts X, X.Y (where X is major, Y is minor' ' part) or "X.latest", defaults to' ' env[ZUN_API_VERSION].') parser.add_argument('--zun_api_version', help=argparse.SUPPRESS) parser.add_argument('--os-cacert', metavar='<ca-certificate>', default=cliutils.env('OS_CACERT', default=None), help='Specify a CA bundle file to use in ' 'verifying a TLS (https) server certificate. ' 'Defaults to env[OS_CACERT].') parser.add_argument('--os-cert', metavar='<ca-certificate>', default=cliutils.env('OS_CERT', default=None), help='Specify a client certificate file (for ' 'client auth). ' 'Defaults to env[OS_CERT].') parser.add_argument('--os-key', metavar='<ca-certificate>', default=cliutils.env('OS_KEY', default=None), help='Specify a client certificate key file (for ' 'client auth). ' 'Defaults to env[OS_KEY].') parser.add_argument('--bypass-url', metavar='<bypass-url>', default=cliutils.env('BYPASS_URL', default=None), dest='bypass_url', help="Use this API endpoint instead of the " "Service Catalog.") parser.add_argument('--bypass_url', help=argparse.SUPPRESS) parser.add_argument('--insecure', default=cliutils.env('ZUNCLIENT_INSECURE', default=False), action='store_true', help="Do not verify https connections") if profiler: parser.add_argument('--profile', metavar='HMAC_KEY', default=cliutils.env('OS_PROFILE', default=None), help='HMAC key to use for encrypting context ' 'data for performance profiling of ' 'operation. This key should be the ' 'value of the HMAC key configured for ' 'the OSprofiler middleware in zun; it ' 'is specified in the Zun configuration ' 'file at "/etc/zun/zun.conf". Without ' 'the key, profiling functions will not ' 'be triggered even if OSprofiler is ' 'enabled on the server side.') # The auth-system-plugins might require some extra options auth.load_auth_system_opts(parser) return parser
def _get_opts_from_specs(self, opts, specs): qos = {} for k, value in specs.iteritems(): # Get the scope, if using scope format key_split = k.split(':') if len(key_split) == 1: scope = None key = key_split[0] else: scope = key_split[0] key = key_split[1] # We generally do not look at capabilities in the driver, but # protocol is a special case where the user asks for a given # protocol and we want both the scheduler and the driver to act # on the value. if ((not scope or scope == 'capabilities') and key == 'storage_protocol'): scope = None key = 'protocol' words = value.split() if not (words and len(words) == 2 and words[0] == '<in>'): LOG.error(_LE('Protocol must be specified as ' '\'<in> iSCSI\' or \'<in> FC\'.')) del words[0] value = words[0] # We generally do not look at capabilities in the driver, but # replication is a special case where the user asks for # a volume to be replicated, and we want both the scheduler and # the driver to act on the value. if ((not scope or scope == 'capabilities') and key == 'replication'): scope = None key = 'replication' words = value.split() if not (words and len(words) == 2 and words[0] == '<is>'): LOG.error(_LE('Replication must be specified as ' '\'<is> True\' or \'<is> False\'.')) del words[0] value = words[0] # Add the QoS. if scope and scope == 'qos': if key in self.svc_qos_keys.keys(): try: type_fn = self.svc_qos_keys[key]['type'] value = type_fn(value) qos[key] = value except ValueError: continue # Any keys that the driver should look at should have the # 'drivers' scope. if scope and scope != 'drivers': continue if key in opts: this_type = type(opts[key]).__name__ if this_type == 'int': value = int(value) elif this_type == 'bool': value = strutils.bool_from_string(value) opts[key] = value if len(qos) != 0: opts['qos'] = qos return opts
def create(self, context, name=None, description=None, share_type_ids=None, source_share_group_snapshot_id=None, share_network_id=None, share_group_type_id=None): """Create new share group.""" share_group_snapshot = None original_share_group = None # NOTE(gouthamr): share_server_id is inherited from the # parent share group if a share group snapshot is specified, # else, it will be set in the share manager. share_server_id = None if source_share_group_snapshot_id: share_group_snapshot = self.db.share_group_snapshot_get( context, source_share_group_snapshot_id) if share_group_snapshot['status'] != constants.STATUS_AVAILABLE: msg = (_("Share group snapshot status must be %s.") % constants.STATUS_AVAILABLE) raise exception.InvalidShareGroupSnapshot(reason=msg) original_share_group = self.db.share_group_get( context, share_group_snapshot['share_group_id']) share_type_ids = [ s['share_type_id'] for s in original_share_group['share_types'] ] share_network_id = original_share_group['share_network_id'] share_server_id = original_share_group['share_server_id'] # Get share_type_objects share_type_objects = [] driver_handles_share_servers = None for share_type_id in (share_type_ids or []): try: share_type_object = share_types.get_share_type( context, share_type_id) except exception.ShareTypeNotFound: msg = _("Share type with id %s could not be found.") raise exception.InvalidInput(msg % share_type_id) share_type_objects.append(share_type_object) extra_specs = share_type_object.get('extra_specs') if extra_specs: share_type_handle_ss = strutils.bool_from_string( extra_specs.get( constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS)) if driver_handles_share_servers is None: driver_handles_share_servers = share_type_handle_ss elif not driver_handles_share_servers == share_type_handle_ss: # NOTE(ameade): if the share types have conflicting values # for driver_handles_share_servers then raise bad request msg = _("The specified share_types cannot have " "conflicting values for the " "driver_handles_share_servers extra spec.") raise exception.InvalidInput(reason=msg) if (not share_type_handle_ss) and share_network_id: msg = _("When using a share types with the " "driver_handles_share_servers extra spec as " "False, a share_network_id must not be provided.") raise exception.InvalidInput(reason=msg) try: if share_network_id: self.db.share_network_get(context, share_network_id) except exception.ShareNetworkNotFound: msg = _("The specified share network does not exist.") raise exception.InvalidInput(reason=msg) if (driver_handles_share_servers and not (source_share_group_snapshot_id or share_network_id)): msg = _("When using a share type with the " "driver_handles_share_servers extra spec as " "True, a share_network_id must be provided.") raise exception.InvalidInput(reason=msg) try: share_group_type = self.db.share_group_type_get( context, share_group_type_id) except exception.ShareGroupTypeNotFound: msg = _("The specified share group type %s does not exist.") raise exception.InvalidInput(reason=msg % share_group_type_id) supported_share_types = set( [x['share_type_id'] for x in share_group_type['share_types']]) if not set(share_type_ids or []) <= supported_share_types: msg = _("The specified share types must be a subset of the share " "types supported by the share group type.") raise exception.InvalidInput(reason=msg) options = { 'share_group_type_id': share_group_type_id, 'source_share_group_snapshot_id': source_share_group_snapshot_id, 'share_network_id': share_network_id, 'share_server_id': share_server_id, 'name': name, 'description': description, 'user_id': context.user_id, 'project_id': context.project_id, 'status': constants.STATUS_CREATING, 'share_types': share_type_ids or supported_share_types } if original_share_group: options['host'] = original_share_group['host'] share_group = self.db.share_group_create(context, options) try: if share_group_snapshot: members = self.db.share_group_snapshot_members_get_all( context, source_share_group_snapshot_id) for member in members: share = self.db.share_get(context, member['share_id']) share_type = share_types.get_share_type( context, share['share_type_id']) member['share_instance'] = self.db.share_instance_get( context, member['share_instance_id'], with_share_data=True) self.share_api.create(context, member['share_proto'], member['size'], None, None, share_group_id=share_group['id'], share_group_snapshot_member=member, share_type=share_type, share_network_id=share_network_id) except Exception: with excutils.save_and_reraise_exception(): self.db.share_group_destroy(context.elevated(), share_group['id']) request_spec = {'share_group_id': share_group['id']} request_spec.update(options) request_spec['share_types'] = share_type_objects request_spec['resource_type'] = share_group_type if share_group_snapshot and original_share_group: self.share_rpcapi.create_share_group(context, share_group, original_share_group['host']) else: self.scheduler_rpcapi.create_share_group( context, share_group_id=share_group['id'], request_spec=request_spec, filter_properties={}) return share_group
def validate(value): try: return strutils.bool_from_string(value, strict=True) except ValueError as e: # raise Invalid to return 400 (BadRequest) in the API raise exception.Invalid(e)
def password(self): if self._validate_string(self.args.os_password): return self.args.os_password verify_pass = (strutils.bool_from_string( cliutils.env("OS_VERIFY_PASSWORD"))) return self._prompt_password(verify_pass)
def to_schema_type(self, value): try: return strutils.bool_from_string(str(value), strict=True) except ValueError: msg = _("The value '%s' is not a valid Boolean") % value raise exc.ESchema(message=msg)
def _extract_dns_hide_counts(self, ctxt, request): ctxt.hide_counts = False value = request.headers.get('OpenStack-DNS-Hide-Counts') if value: ctxt.hide_counts = strutils.bool_from_string(value)
def bool_from_env(key, strict=False, default=False): value = os.environ.get(key) return strutils.bool_from_string(value, strict=strict, default=default)
def coerce(self, obj, attr, value): return strutils.bool_from_string(value, strict=True, default=self._default)
def _volume_upload_image(self, req, id, body): """Uploads the specified volume to image service.""" context = req.environ['cinder.context'] params = body['os-volume_upload_image'] req_version = req.api_version_request if not params.get("image_name"): msg = _("No image_name was specified in request.") raise webob.exc.HTTPBadRequest(explanation=msg) force = params.get('force', 'False') try: force = strutils.bool_from_string(force, strict=True) except ValueError as error: err_msg = encodeutils.exception_to_unicode(error) msg = _("Invalid value for 'force': '%s'") % err_msg raise webob.exc.HTTPBadRequest(explanation=msg) # Not found exception will be handled at the wsgi level volume = self.volume_api.get(context, id) context.authorize(policy.UPLOAD_IMAGE_POLICY) # check for valid disk-format disk_format = params.get("disk_format", "raw") if not image_utils.validate_disk_format(disk_format): msg = _("Invalid disk-format '%(disk_format)s' is specified. " "Allowed disk-formats are %(allowed_disk_formats)s.") % { "disk_format": disk_format, "allowed_disk_formats": ", ".join( image_utils.VALID_DISK_FORMATS) } raise webob.exc.HTTPBadRequest(explanation=msg) image_metadata = { "container_format": params.get("container_format", "bare"), "disk_format": disk_format, "name": params["image_name"] } if volume.encryption_key_id: # Clone volume encryption key: the current key cannot # be reused because it will be deleted when the volume is # deleted. # TODO(eharney): Currently, there is no mechanism to remove # these keys, because Glance will not delete the key from # Barbican when the image is deleted. encryption_key_id = self._key_manager.store( context, self._key_manager.get(context, volume.encryption_key_id)) image_metadata['cinder_encryption_key_id'] = encryption_key_id if req_version >= mv.get_api_version(mv.UPLOAD_IMAGE_PARAMS): image_metadata['visibility'] = params.get('visibility', 'private') image_metadata['protected'] = params.get('protected', 'False') if image_metadata['visibility'] == 'public': context.authorize(policy.UPLOAD_PUBLIC_POLICY) image_metadata['protected'] = (utils.get_bool_param( 'protected', image_metadata)) try: response = self.volume_api.copy_volume_to_image( context, volume, image_metadata, force) except exception.InvalidVolume as error: raise webob.exc.HTTPBadRequest(explanation=error.msg) except ValueError as error: raise webob.exc.HTTPBadRequest(explanation=six.text_type(error)) except messaging.RemoteError as error: msg = "%(err_type)s: %(err_msg)s" % { 'err_type': error.exc_type, 'err_msg': error.value } raise webob.exc.HTTPBadRequest(explanation=msg) except Exception as error: raise webob.exc.HTTPBadRequest(explanation=six.text_type(error)) return {'os-volume_upload_image': response}
def test_other_bool_from_string(self): self.assertFalse(strutils.bool_from_string(None)) self.assertFalse(strutils.bool_from_string(mock.Mock()))