def delete(self, req, id): """Deletes an existing qos specs.""" context = req.environ['cinder.context'] authorize(context) force = req.params.get('force', None) #convert string to bool type in strict manner force = strutils.bool_from_string(force) LOG.debug("Delete qos_spec: %(id)s, force: %(force)s" % { 'id': id, 'force': force }) try: qos_specs.delete(context, id, force) notifier_info = dict(id=id) notifier_api.notify(context, 'QoSSpecs', 'qos_specs.delete', notifier_api.INFO, notifier_info) except exception.QoSSpecsNotFound as err: notifier_err = dict(id=id, error_message=str(err)) self._notify_qos_specs_error(context, 'qos_specs.delete', notifier_err) raise webob.exc.HTTPNotFound(explanation=str(err)) except exception.QoSSpecsInUse as err: notifier_err = dict(id=id, error_message=str(err)) self._notify_qos_specs_error(context, 'qos_specs.delete', notifier_err) if force: msg = _('Failed to disassociate qos specs.') raise webob.exc.HTTPInternalServerError(explanation=msg) msg = _('Qos specs still in use.') raise webob.exc.HTTPBadRequest(explanation=msg) return webob.Response(status_int=202)
def _volume_readonly_update(self, req, id, body): """Update volume readonly flag.""" context = req.environ['cinder.context'] try: volume = self.volume_api.get(context, id) except exception.VolumeNotFound as error: raise webob.exc.HTTPNotFound(explanation=error.msg) try: readonly_flag = body['os-update_readonly_flag']['readonly'] except KeyError: msg = _("Must specify readonly in request.") raise webob.exc.HTTPBadRequest(explanation=msg) if isinstance(readonly_flag, basestring): try: readonly_flag = strutils.bool_from_string(readonly_flag, strict=True) except ValueError: msg = _("Bad value for 'readonly'") raise webob.exc.HTTPBadRequest(explanation=msg) elif not isinstance(readonly_flag, bool): msg = _("'readonly' not string or bool") raise webob.exc.HTTPBadRequest(explanation=msg) self.volume_api.update_readonly_flag(context, volume, readonly_flag) return webob.Response(status_int=202)
def _set_bootable(self, req, id, body): """Update bootable status of a volume.""" context = req.environ['cinder.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) if isinstance(bootable, basestring): try: bootable = strutils.bool_from_string(bootable, strict=True) except ValueError: msg = _("Bad value for 'bootable'") raise webob.exc.HTTPBadRequest(explanation=msg) elif not isinstance(bootable, bool): msg = _("'bootable' not string or bool") 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 _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 delete(self, req, id): """Deletes an existing qos specs.""" context = req.environ["cinder.context"] authorize(context) force = req.params.get("force", None) # convert string to bool type in strict manner force = strutils.bool_from_string(force) LOG.debug("Delete qos_spec: %(id)s, force: %(force)s" % {"id": id, "force": force}) try: qos_specs.delete(context, id, force) notifier_info = dict(id=id) notifier_api.notify(context, "QoSSpecs", "qos_specs.delete", notifier_api.INFO, notifier_info) except exception.QoSSpecsNotFound as err: notifier_err = dict(id=id, error_message=str(err)) self._notify_qos_specs_error(context, "qos_specs.delete", notifier_err) raise webob.exc.HTTPNotFound(explanation=str(err)) except exception.QoSSpecsInUse as err: notifier_err = dict(id=id, error_message=str(err)) self._notify_qos_specs_error(context, "qos_specs.delete", notifier_err) if force: msg = _("Failed to disassociate qos specs.") raise webob.exc.HTTPInternalServerError(explanation=msg) msg = _("Qos specs still in use.") raise webob.exc.HTTPBadRequest(explanation=msg) return webob.Response(status_int=202)
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 _volume_readonly_update(self, req, id, body): """Update volume readonly flag.""" context = req.environ['cinder.context'] try: volume = self.volume_api.get(context, id) except exception.VolumeNotFound as error: raise webob.exc.HTTPNotFound(explanation=error.msg) try: readonly_flag = body['os-update_readonly_flag']['readonly'] except KeyError: msg = _("Must specify readonly in request.") raise webob.exc.HTTPBadRequest(explanation=msg) if isinstance(readonly_flag, basestring): try: readonly_flag = strutils.bool_from_string(readonly_flag, strict=True) except ValueError: msg = _("Bad value for 'readonly'") raise webob.exc.HTTPBadRequest(explanation=msg) elif not isinstance(readonly_flag, bool): msg = _("'readonly' not string or bool") raise webob.exc.HTTPBadRequest(explanation=msg) self.volume_api.update_readonly_flag(context, volume, readonly_flag) return webob.Response(status_int=202)
def _set_bootable(self, req, id, body): """Update bootable status of a volume.""" context = req.environ['cinder.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) if isinstance(bootable, basestring): try: bootable = strutils.bool_from_string(bootable, strict=True) except ValueError: msg = _("Bad value for 'bootable'") raise webob.exc.HTTPBadRequest(explanation=msg) elif not isinstance(bootable, bool): msg = _("'bootable' not string or bool") 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 create(self, req, body): """Creates a new snapshot.""" kwargs = {} context = req.environ['cinder.context'] if not self.is_valid_body(body, 'snapshot'): raise exc.HTTPUnprocessableEntity() snapshot = body['snapshot'] kwargs['metadata'] = snapshot.get('metadata', None) volume_id = snapshot['volume_id'] volume = self.volume_api.get(context, volume_id) force = snapshot.get('force', False) msg = _("Create snapshot from volume %s") LOG.audit(msg, volume_id, context=context) if not utils.is_valid_boolstr(force): msg = _("Invalid value '%s' for force. ") % force raise exception.InvalidParameterValue(err=msg) if strutils.bool_from_string(force): new_snapshot = self.volume_api.create_snapshot_force( context, volume, snapshot.get('display_name'), snapshot.get('display_description'), **kwargs) else: new_snapshot = self.volume_api.create_snapshot( context, volume, snapshot.get('display_name'), snapshot.get('display_description'), **kwargs) retval = _translate_snapshot_detail_view(context, new_snapshot) return {'snapshot': retval}
def create(self, req, body): """Creates a new snapshot.""" kwargs = {} context = req.environ['cinder.context'] if not self.is_valid_body(body, 'snapshot'): msg = (_("Missing required element '%s' in request body") % 'snapshot') raise exc.HTTPBadRequest(explanation=msg) snapshot = body['snapshot'] kwargs['metadata'] = snapshot.get('metadata', None) try: volume_id = snapshot['volume_id'] except KeyError: msg = _("'volume_id' must be specified") raise exc.HTTPBadRequest(explanation=msg) try: volume = self.volume_api.get(context, volume_id) except exception.NotFound: msg = _("Volume could not be found") raise exc.HTTPNotFound(explanation=msg) force = snapshot.get('force', False) msg = _("Create snapshot from volume %s") LOG.info(msg, volume_id, context=context) # NOTE(thingee): v2 API allows name instead of display_name if 'name' in snapshot: snapshot['display_name'] = snapshot.get('name') del snapshot['name'] if not utils.is_valid_boolstr(force): msg = _("Invalid value '%s' for force. ") % force raise exception.InvalidParameterValue(err=msg) if strutils.bool_from_string(force): new_snapshot = self.volume_api.create_snapshot_force( context, volume, snapshot.get('display_name'), snapshot.get('description'), **kwargs) else: new_snapshot = self.volume_api.create_snapshot( context, volume, snapshot.get('display_name'), snapshot.get('description'), **kwargs) req.cache_db_snapshot(new_snapshot) retval = _translate_snapshot_detail_view(context, new_snapshot) return {'snapshot': retval}
def create(self, req, body): """Creates a new snapshot.""" kwargs = {} context = req.environ['cinder.context'] if not self.is_valid_body(body, 'snapshot'): msg = (_("Missing required element '%s' in request body") % 'snapshot') raise exc.HTTPBadRequest(explanation=msg) snapshot = body['snapshot'] kwargs['metadata'] = snapshot.get('metadata', None) try: volume_id = snapshot['volume_id'] except KeyError: msg = _("'volume_id' must be specified") raise exc.HTTPBadRequest(explanation=msg) try: volume = self.volume_api.get(context, volume_id) except exception.NotFound: msg = _("Volume could not be found") raise exc.HTTPNotFound(explanation=msg) force = snapshot.get('force', False) msg = _("Create snapshot from volume %s") LOG.info(msg, volume_id, context=context) # NOTE(thingee): v2 API allows name instead of display_name if 'name' in snapshot: snapshot['display_name'] = snapshot.get('name') del snapshot['name'] if not utils.is_valid_boolstr(force): msg = _("Invalid value '%s' for force. ") % force raise exception.InvalidParameterValue(err=msg) if strutils.bool_from_string(force): new_snapshot = self.volume_api.create_snapshot_force( context, volume, snapshot.get('display_name'), snapshot.get('description'), **kwargs) else: new_snapshot = self.volume_api.create_snapshot( context, volume, snapshot.get('display_name'), snapshot.get('description'), **kwargs) retval = _translate_snapshot_detail_view(context, new_snapshot) return {'snapshot': retval}
def get_vdisk_params(self, config, state, type_id, volume_type=None): """Return the parameters for creating the vdisk. Takes volume type and defaults from config options into account. """ opts = self.build_default_opts(config) if volume_type is None and type_id is not None: ctxt = context.get_admin_context() volume_type = volume_types.get_volume_type(ctxt, type_id) if volume_type: specs = dict(volume_type).get('extra_specs') 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( _('Protocol must be specified as ' '\'<in> iSCSI\' or \'<in> FC\'.')) del words[0] value = words[0] # 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 self.check_vdisk_opts(state, opts) return opts
def get_vdisk_params(self, config, state, type_id, volume_type=None): """Return the parameters for creating the vdisk. Takes volume type and defaults from config options into account. """ opts = self.build_default_opts(config) if volume_type is None and type_id is not None: ctxt = context.get_admin_context() volume_type = volume_types.get_volume_type(ctxt, type_id) if volume_type: specs = dict(volume_type).get('extra_specs') 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(_('Protocol must be specified as ' '\'<in> iSCSI\' or \'<in> FC\'.')) del words[0] value = words[0] # 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 self.check_vdisk_opts(state, opts) return opts
def create(self, req, body): """Creates a new snapshot.""" kwargs = {} context = req.environ['cinder.context'] if not self.is_valid_body(body, 'snapshot'): raise exc.HTTPUnprocessableEntity() snapshot = body['snapshot'] kwargs['metadata'] = snapshot.get('metadata', None) try: volume_id = snapshot['volume_id'] except KeyError: msg = _("'volume_id' must be specified") raise exc.HTTPBadRequest(explanation=msg) try: volume = self.volume_api.get(context, volume_id) except exception.NotFound: raise exc.HTTPNotFound() force = snapshot.get('force', False) msg = _("Create snapshot from volume %s") LOG.info(msg, volume_id, context=context) if not utils.is_valid_boolstr(force): msg = _("Invalid value '%s' for force. ") % force raise exception.InvalidParameterValue(err=msg) if strutils.bool_from_string(force): new_snapshot = self.volume_api.create_snapshot_force( context, volume, snapshot.get('display_name'), snapshot.get('display_description'), **kwargs) else: new_snapshot = self.volume_api.create_snapshot( context, volume, snapshot.get('display_name'), snapshot.get('display_description'), **kwargs) req.cache_db_snapshot(new_snapshot) retval = _translate_snapshot_detail_view(context, new_snapshot) return {'snapshot': retval}
def show(self, req, id): context = req.environ['cinder.context'] authorize_show(context) params = req.params if not hasattr(params, '__call__') and 'usage' in params: usage = strutils.bool_from_string(params['usage']) else: usage = False try: sqlalchemy_api.authorize_project_context(context, id) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() return self._format_quota_set(id, self._get_quotas(context, id, usage))
def show(self, req, id): context = req.environ['cinder.context'] authorize_show(context) params = req.params if not hasattr(params, '__call__') and 'usage' in params: usage = strutils.bool_from_string(params['usage']) else: usage = False try: sqlalchemy_api.authorize_project_context(context, id) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() return self._format_quota_set(id, self._get_quotas(context, id, usage))
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'] 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) if isinstance(force, basestring): try: force = strutils.bool_from_string(force, strict=False) except ValueError: msg = _("Bad value for 'force' parameter.") raise webob.exc.HTTPBadRequest(explanation=msg) elif not isinstance(force, bool): msg = _("'force' is not string or bool.") raise webob.exc.HTTPBadRequest(explanation=msg) try: volume = self.volume_api.get(context, id) except exception.VolumeNotFound as error: raise webob.exc.HTTPNotFound(explanation=error.msg) authorize(context, "upload_image") image_metadata = { "container_format": params.get("container_format", "bare"), "disk_format": params.get("disk_format", "raw"), "name": params["image_name"] } 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=unicode(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=unicode(error)) return {'os-volume_upload_image': response}
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'] 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) if isinstance(force, basestring): try: force = strutils.bool_from_string(force, strict=False) except ValueError: msg = _("Bad value for 'force' parameter.") raise webob.exc.HTTPBadRequest(explanation=msg) elif not isinstance(force, bool): msg = _("'force' is not string or bool.") raise webob.exc.HTTPBadRequest(explanation=msg) try: volume = self.volume_api.get(context, id) except exception.VolumeNotFound as error: raise webob.exc.HTTPNotFound(explanation=error.msg) authorize(context, "upload_image") image_metadata = {"container_format": params.get("container_format", "bare"), "disk_format": params.get("disk_format", "raw"), "name": params["image_name"]} 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=unicode(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=unicode(error)) return {'os-volume_upload_image': response}
def create(self, req, body): """Creates a new snapshot.""" kwargs = {} context = req.environ['cinder.context'] if not self.is_valid_body(body, 'snapshot'): raise exc.HTTPBadRequest() snapshot = body['snapshot'] kwargs['metadata'] = snapshot.get('metadata', None) volume_id = snapshot['volume_id'] volume = self.volume_api.get(context, volume_id) force = snapshot.get('force', False) msg = _("Create snapshot from volume %s") LOG.audit(msg, volume_id, context=context) # NOTE(thingee): v2 API allows name instead of display_name if 'name' in snapshot: snapshot['display_name'] = snapshot.get('name') del snapshot['name'] if not utils.is_valid_boolstr(force): msg = _("Invalid value '%s' for force. ") % force raise exception.InvalidParameterValue(err=msg) if strutils.bool_from_string(force): new_snapshot = self.volume_api.create_snapshot_force( context, volume, snapshot.get('display_name'), snapshot.get('description'), **kwargs) else: new_snapshot = self.volume_api.create_snapshot( context, volume, snapshot.get('display_name'), snapshot.get('description'), **kwargs) retval = _translate_snapshot_detail_view(context, new_snapshot) return {'snapshot': retval}
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"] host = params["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("Bad value for 'force_host_copy'") elif not isinstance(force_host_copy, bool): raise exc.HTTPBadRequest("'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 delete(self, req, id): """Deletes an existing qos specs.""" context = req.environ['cinder.context'] authorize(context) force = req.params.get('force', None) #convert string to bool type in strict manner force = strutils.bool_from_string(force) LOG.debug("Delete qos_spec: %(id)s, force: %(force)s" % {'id': id, 'force': force}) try: qos_specs.delete(context, id, force) notifier_info = dict(id=id) rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.delete', notifier_info) except exception.QoSSpecsNotFound as err: notifier_err = dict(id=id, error_message=err) self._notify_qos_specs_error(context, 'qos_specs.delete', notifier_err) raise webob.exc.HTTPNotFound(explanation=six.text_type(err)) except exception.QoSSpecsInUse as err: notifier_err = dict(id=id, error_message=err) self._notify_qos_specs_error(context, 'qos_specs.delete', notifier_err) if force: msg = _('Failed to disassociate qos specs.') raise webob.exc.HTTPInternalServerError(explanation=msg) msg = _('Qos specs still in use.') raise webob.exc.HTTPBadRequest(explanation=msg) return webob.Response(status_int=202)
from cinder.openstack.common import strutils # 1. The following operations are supported: # =, s==, s!=, s>=, s>, s<=, s<, <in>, <is>, <or>, ==, !=, >=, <= # 2. Note that <or> is handled in a different way below. # 3. If the first word in the extra_specs is not one of the operators, # it is ignored. _op_methods = { '=': lambda x, y: float(x) >= float(y), '<in>': lambda x, y: y in x, '<is>': lambda x, y: (strutils.bool_from_string(x) is strutils.bool_from_string(y)), '==': lambda x, y: float(x) == float(y), '!=': lambda x, y: float(x) != float(y), '>=': lambda x, y: float(x) >= float(y), '<=': lambda x, y: float(x) <= float(y), 's==': operator.eq, 's!=': operator.ne, 's<': operator.lt, 's<=':
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)) rpc.add_extra_exmods("cinder.tests") 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 self.mox = mox.Mox() self.stubs = stubout.StubOutForTesting() self.addCleanup(CONF.reset) self.addCleanup(self.mox.UnsetStubs) self.addCleanup(self.stubs.UnsetAll) self.addCleanup(self.stubs.SmartUnsetAll) self.addCleanup(self.mox.VerifyAll) self.addCleanup(self._common_cleanup) self.injected = [] self._services = [] fake_notifier.stub_notifier(self.stubs) CONF.set_override('fatal_exception_format_errors', True) # This will be cleaned up by the NestedTempfile fixture CONF.set_override('lock_path', tempfile.mkdtemp()) CONF.set_override('policy_file', os.path.join( os.path.abspath( os.path.join( os.path.dirname(__file__), '..', ) ), 'cinder/tests/policy.json'))
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import operator from cinder.openstack.common import strutils # 1. The following operations are supported: # =, s==, s!=, s>=, s>, s<=, s<, <in>, <is>, <or>, ==, !=, >=, <= # 2. Note that <or> is handled in a different way below. # 3. If the first word in the extra_specs is not one of the operators, # it is ignored. _op_methods = {'=': lambda x, y: float(x) >= float(y), '<in>': lambda x, y: y in x, '<is>': lambda x, y: (strutils.bool_from_string(x) is strutils.bool_from_string(y)), '==': lambda x, y: float(x) == float(y), '!=': lambda x, y: float(x) != float(y), '>=': lambda x, y: float(x) >= float(y), '<=': lambda x, y: float(x) <= float(y), 's==': operator.eq, 's!=': operator.ne, 's<': operator.lt, 's<=': operator.le, 's>': operator.gt, 's>=': operator.ge} def match(value, req): words = req.split()
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( _('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( _('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 _get_replication_hosts(self, context, request_spec, filter_properties): """Find hosts for the volume and its copy if replicaiton is specified. Here we use a greedy algorithm and choose the host with the best score after weighing plus its partner, rather than finding an optimal pair (pair with the total best score after weighing). It is possible for a host to be partnered with itself if that is allowed by its capabilities. Note: When checking the case where we use the same host for both copies, we should take size into account twice, but we don't. """ def _host_has_replication_caps(capabilities): required = ['replication_unit_id', 'replication_partners', 'replication_rpo_range', 'replication_single_control'] reqs_satisfied = True for req in required: if req not in capabilities: reqs_satisfied = False return reqs_satisfied specs = request_spec['volume_type']['extra_specs'] same_az = specs.pop('replica_same_az', None) if same_az: same_az = strutils.bool_from_string(same_az) replica_backend_name = specs.pop('replica_volume_backend_name', None) target_rpo = specs.pop('replication_target_rpo', None) weighed_hosts1 = self._get_weighted_candidates(context, request_spec, filter_properties) # NOTE(avishay): We now override volume_backend_name with # replica_volume_backend_name, otherwise we won't find other hosts specs.pop('volume_backend_name', None) if replica_backend_name: specs['volume_backend_name'] = replica_backend_name weighed_hosts2 = self._get_weighted_candidates(context, request_spec, filter_properties) for host1 in weighed_hosts1: caps1 = host1.obj.capabilities if not _host_has_replication_caps(caps1): continue partners1 = caps1['replication_partners'] if target_rpo is not None: target_rpo = int(target_rpo) rpo_range = caps1['replication_rpo_range'] if target_rpo < rpo_range[0] or target_rpo > rpo_range[1]: continue for host2 in weighed_hosts2: if same_az is not None: op = operator.ne if same_az else operator.eq if op(host1.obj.service['availability_zone'], host2.obj.service['availability_zone']): continue caps2 = host2.obj.capabilities if caps2['replication_unit_id'] not in partners1: continue partners2 = caps2['replication_partners'] if caps1['replication_unit_id'] not in partners2: continue return (host1, host2) return (None, None)
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(_('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(_('Replication must be specified as ' '\'<is> True\' or \'<is> False\'.')) del words[0] value = words[0] # Add the QoS. if scope and scope == 'qos': type_fn = self.svc_qos_keys[key] try: value = type_fn(value) qos[self.svc_qos_param_dict[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