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)
Example #2
0
    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)
Example #4
0
 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)
Example #5
0
    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)
Example #6
0
 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)
Example #7
0
    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)
Example #8
0
    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)
Example #9
0
    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}
Example #10
0
    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}
Example #11
0
    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}
Example #12
0
    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
Example #13
0
    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
Example #14
0
    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}
Example #15
0
    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))
Example #16
0
    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))
Example #17
0
    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}
Example #18
0
    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}
Example #19
0
    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}
Example #20
0
 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)
Example #21
0
    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)
Example #22
0
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<=':
Example #23
0
    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'))
Example #24
0
#    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()
Example #25
0
    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)
Example #27
0
    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