Пример #1
0
    def disassociate_all(self, req, id):
        """Disassociate a qos specs from all volume types."""
        context = req.environ['cinder.context']
        authorize(context)

        LOG.debug("Disassociate qos_spec: %s from all." % id)

        try:
            qos_specs.get_qos_specs(context, id)
            qos_specs.disassociate_all(context, id)
            notifier_info = dict(id=id)
            notifier_api.notify(context, 'QoSSpecs',
                                'qos_specs.disassociate_all',
                                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.disassociate_all',
                                         notifier_err)
            raise webob.exc.HTTPNotFound(explanation=str(err))
        except exception.QoSSpecsDisassociateFailed as err:
            notifier_err = dict(id=id, error_message=str(err))
            self._notify_qos_specs_error(context,
                                         'qos_specs.disassociate_all',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(explanation=str(err))

        return webob.Response(status_int=202)
Пример #2
0
    def delete(self, req, id):
        """Deletes an existing qos specs."""
        context = req.environ['cinder.context']
        authorize(context)

        force = req.params.get('force', None)

        LOG.debug("Delete qos_spec: %(id)s, force: %(force)s" %
                  {'id': id, 'force': force})

        try:
            qos_specs.get_qos_specs(context, id)
            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)
Пример #3
0
    def get_qos_by_volume_type(volume_type):
        # We prefer the qos_specs association
        # and override any existing extra-specs settings
        # if present.
        if not volume_type:
            return {}

        qos_specs_id = volume_type.get('qos_specs_id')
        if not qos_specs_id:
            return {}

        qos = {}
        ctxt = context.get_admin_context()
        consumer = qos_specs.get_qos_specs(ctxt, qos_specs_id)['consumer']
        if consumer == 'front-end':
            return

        kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
        LOG.info('The QoS sepcs is: %s.', kvs)

        for k, v in kvs.items():
            if k not in constants.QOS_SPEC_KEYS:
                msg = _('Invalid QoS %s specification.') % k
                LOG.error(msg)
                raise exception.InvalidInput(reason=msg)

            if k != 'IOType' and int(v) <= 0:
                msg = _('QoS config is wrong. %s must > 0.') % k
                LOG.error(msg)
                raise exception.InvalidInput(reason=msg)

            qos[k.upper()] = v

        if 'IOTYPE' not in qos or qos['IOTYPE'] not in constants.QOS_IOTYPES:
            msg = _('IOType value must be in %(valid)s.') % {
                'valid': constants.QOS_IOTYPES
            }
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        if len(qos) < 2:
            msg = _('QoS policy must specify IOType and one of QoS specs.')
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        for upper_limit in constants.UPPER_LIMIT_KEYS:
            for lower_limit in constants.LOWER_LIMIT_KEYS:
                if upper_limit in qos and lower_limit in qos:
                    msg = (_('QoS policy upper_limit and lower_limit '
                             'conflict, QoS policy: %(qos_policy)s.') % {
                                 'qos_policy': qos
                             })
                    LOG.error(msg)
                    raise exception.InvalidInput(reason=msg)

        return qos
Пример #4
0
    def test_create(self):
        input = {"key1": "value1", "key2": "value2", "key3": "value3"}
        ref = qos_specs.create(self.ctxt, "FakeName", input)
        specs_obj = qos_specs.get_qos_specs(self.ctxt, ref["id"])
        specs_obj_dic = {
            "consumer": specs_obj["consumer"],
            "id": specs_obj["id"],
            "name": specs_obj["name"],
            "specs": specs_obj["specs"],
        }
        expected = {"consumer": "back-end", "id": ref["id"], "name": "FakeName", "specs": input}
        self.assertDictMatch(expected, specs_obj_dic)

        # qos specs must have unique name
        self.assertRaises(exception.QoSSpecsExists, qos_specs.create, self.ctxt, "FakeName", input)

        # consumer must be one of: front-end, back-end, both
        input["consumer"] = "fake"
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.create, self.ctxt, "QoSName", input)

        del input["consumer"]

        self.mock_object(db, "qos_specs_create", fake_db_qos_specs_create)
        # able to catch DBError
        self.assertRaises(exception.QoSSpecsCreateFailed, qos_specs.create, self.ctxt, "FailQoSName", input)
Пример #5
0
 def test_get_qos_specs(self):
     one_time_value = str(int(time.time()))
     specs = {"key1": one_time_value, "key2": "value2", "key3": "value3"}
     qos_id = self._create_qos_specs("Specs1", "both", specs)
     specs = qos_specs.get_qos_specs(self.ctxt, qos_id)
     self.assertEqual(one_time_value, specs["specs"]["key1"])
     self.assertRaises(exception.InvalidQoSSpecs, qos_specs.get_qos_specs, self.ctxt, None)
Пример #6
0
    def test_delete_keys(self):
        def fake_db_qos_delete_key(context, id, key):
            if key == "NotFound":
                raise exception.QoSSpecsKeyNotFound(specs_id=id, specs_key=key)
            else:
                pass

        value = {"foo": "Foo", "bar": "Bar", "zoo": "tiger"}
        name = "QoSName"
        consumer = "front-end"
        specs_id = self._create_qos_specs(name, consumer, value)
        qos_specs.delete_keys(self.ctxt, specs_id, ["foo", "bar"])

        del value["foo"]
        del value["bar"]
        expected = {"name": name, "id": specs_id, "consumer": consumer, "specs": value}
        specs = qos_specs.get_qos_specs(self.ctxt, specs_id)
        specs_dic = {"consumer": specs["consumer"], "id": specs["id"], "name": specs["name"], "specs": specs["specs"]}
        self.assertDictMatch(expected, specs_dic)

        self.mock_object(db, "qos_specs_item_delete", fake_db_qos_delete_key)
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.delete_keys, self.ctxt, None, [])
        self.assertRaises(exception.QoSSpecsNotFound, qos_specs.delete_keys, self.ctxt, "NotFound", [])
        self.assertRaises(exception.QoSSpecsKeyNotFound, qos_specs.delete_keys, self.ctxt, specs_id, ["NotFound"])
        self.assertRaises(
            exception.QoSSpecsKeyNotFound, qos_specs.delete_keys, self.ctxt, specs_id, ["foo", "bar", "NotFound"]
        )
Пример #7
0
    def test_create(self):
        input = {'key1': 'value1',
                 'key2': 'value2',
                 'key3': 'value3'}
        ref = qos_specs.create(self.ctxt, 'FakeName', input)
        specs_obj = qos_specs.get_qos_specs(self.ctxt, ref['id'])
        specs_obj_dic = {'consumer': specs_obj['consumer'],
                         'id': specs_obj['id'],
                         'name': specs_obj['name'],
                         'specs': specs_obj['specs']}
        expected = {'consumer': 'back-end',
                    'id': ref['id'],
                    'name': 'FakeName',
                    'specs': input}
        self.assertDictEqual(expected,
                             specs_obj_dic)

        # qos specs must have unique name
        self.assertRaises(exception.QoSSpecsExists,
                          qos_specs.create, self.ctxt, 'FakeName', input)

        # consumer must be one of: front-end, back-end, both
        input['consumer'] = 'fake'
        self.assertRaises(exception.InvalidQoSSpecs,
                          qos_specs.create, self.ctxt, 'QoSName', input)

        del input['consumer']

        self.mock_object(db, 'qos_specs_create',
                         fake_db_qos_specs_create)
        # able to catch DBError
        self.assertRaises(exception.QoSSpecsCreateFailed,
                          qos_specs.create, self.ctxt, 'FailQoSName', input)
Пример #8
0
    def get_vdisk_params(self, config, state, type_id, volume_type=None,
                         volume_metadata=None):
        """Return the parameters for creating the vdisk.

        Takes volume type and defaults from config options into account.
        """
        opts = self.build_default_opts(config)
        ctxt = context.get_admin_context()
        if volume_type is None and type_id is not None:
            volume_type = volume_types.get_volume_type(ctxt, type_id)
        if volume_type:
            qos_specs_id = volume_type.get('qos_specs_id')
            specs = dict(volume_type).get('extra_specs')

            # NOTE(vhou): We prefer the qos_specs association
            # and over-ride any existing
            # extra-specs settings if present
            if qos_specs_id is not None:
                kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
                # Merge the qos_specs into extra_specs and qos_specs has higher
                # priority than extra_specs if they have different values for
                # the same key.
                specs.update(kvs)
            opts = self._get_opts_from_specs(opts, specs)
        if (opts['qos'] is None and config.storwize_svc_allow_tenant_qos
                and volume_metadata):
            qos = self._get_qos_from_volume_metadata(volume_metadata)
            if len(qos) != 0:
                opts['qos'] = qos

        self.check_vdisk_opts(state, opts)
        return opts
Пример #9
0
    def associations(self, req, id):
        """List all associations of given qos specs."""
        context = req.environ['cinder.context']
        context.authorize(policy.GET_ALL_POLICY)

        LOG.debug("Get associations for qos_spec id: %s", id)

        try:
            spec = qos_specs.get_qos_specs(context, id)

            associates = qos_specs.get_associations(context, id)
            notifier_info = dict(id=id, created_at=spec.created_at)
            rpc.get_notifier('QoSSpecs').info(context,
                                              'qos_specs.associations',
                                              notifier_info)
        except exception.QoSSpecsNotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.associations',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.CinderException as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.associations',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return self._view_builder.associations(req, associates)
Пример #10
0
def get_qos_by_volume_type(volume_type):
    qos = {}
    qos_specs_id = volume_type.get('qos_specs_id')

    # We prefer the qos_specs association
    # and override any existing extra-specs settings
    # if present.
    if qos_specs_id is not None:
        kvs = qos_specs.get_qos_specs(context.get_admin_context(),
                                      qos_specs_id)['specs']
    else:
        return qos

    LOG.info(_LI('The QoS sepcs is: %s.'), kvs)
    for key, value in kvs.items():
        if key in constants.HUAWEI_VALID_KEYS:
            if (key.upper() != 'IOTYPE') and (int(value) <= 0):
                err_msg = (_('Qos config is wrong. %(key)s'
                             ' must be set greater than 0.')
                           % {'key': key})
                LOG.error(err_msg)
                raise exception.VolumeBackendAPIException(data=err_msg)
            elif (key.upper() == 'IOTYPE') and (value not in ['0', '1', '2']):
                raise exception.InvalidInput(
                    reason=(_('Illegal value specified for IOTYPE: '
                              'set to either 0, 1, or 2.')))
            else:
                qos[key.upper()] = value

    return qos
Пример #11
0
    def test_create(self):
        input = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
        ref = qos_specs.create(self.ctxt, 'FakeName', input)
        specs_obj = qos_specs.get_qos_specs(self.ctxt, ref['id'])
        specs_obj_dic = {
            'consumer': specs_obj['consumer'],
            'id': specs_obj['id'],
            'name': specs_obj['name'],
            'specs': specs_obj['specs']
        }
        expected = {
            'consumer': 'back-end',
            'id': ref['id'],
            'name': 'FakeName',
            'specs': input
        }
        self.assertDictMatch(expected, specs_obj_dic)

        # qos specs must have unique name
        self.assertRaises(exception.QoSSpecsExists, qos_specs.create,
                          self.ctxt, 'FakeName', input)

        # consumer must be one of: front-end, back-end, both
        input['consumer'] = 'fake'
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.create,
                          self.ctxt, 'QoSName', input)

        del input['consumer']

        self.stubs.Set(db, 'qos_specs_create', fake_db_qos_specs_create)
        # able to catch DBError
        self.assertRaises(exception.QoSSpecsCreateFailed, qos_specs.create,
                          self.ctxt, 'FailQoSName', input)
Пример #12
0
    def disassociate_all(self, req, id):
        """Disassociate a qos specs from all volume types."""
        context = req.environ['cinder.context']
        context.authorize(policy.UPDATE_POLICY)

        LOG.debug("Disassociate qos_spec: %s from all.", id)

        try:
            spec = qos_specs.get_qos_specs(context, id)

            qos_specs.disassociate_all(context, id)
            notifier_info = dict(id=id,
                                 created_at=spec.created_at)
            rpc.get_notifier('QoSSpecs').info(context,
                                              'qos_specs.disassociate_all',
                                              notifier_info)
        except exception.QoSSpecsNotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.disassociate_all',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.QoSSpecsDisassociateFailed as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.disassociate_all',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return webob.Response(status_int=http_client.ACCEPTED)
Пример #13
0
    def test_update(self):
        def fake_db_update(context, specs_id, values):
            raise db_exc.DBError()

        input = {'key1': 'value1', 'consumer': 'WrongPlace'}
        # consumer must be one of: front-end, back-end, both
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.update,
                          self.ctxt, 'fake_id', input)

        input['consumer'] = 'front-end'
        # qos specs must exists
        self.assertRaises(exception.QoSSpecsNotFound, qos_specs.update,
                          self.ctxt, 'fake_id', input)

        specs_id = self._create_qos_specs('Name', input)
        qos_specs.update(self.ctxt, specs_id, {
            'key1': 'newvalue1',
            'key2': 'value2'
        })
        specs = qos_specs.get_qos_specs(self.ctxt, specs_id)
        self.assertEqual(specs['specs']['key1'], 'newvalue1')
        self.assertEqual(specs['specs']['key2'], 'value2')

        self.stubs.Set(db, 'qos_specs_update', fake_db_update)
        self.assertRaises(exception.QoSSpecsUpdateFailed, qos_specs.update,
                          self.ctxt, 'fake_id', input)
Пример #14
0
    def test_create(self):
        input = {'key1': 'value1',
                 'key2': 'value2',
                 'key3': 'value3'}
        ref = qos_specs.create(self.ctxt, 'FakeName', input)
        specs = qos_specs.get_qos_specs(self.ctxt, ref['id'])
        expected = (dict(consumer='back-end'))
        expected.update(dict(id=ref['id']))
        expected.update(dict(name='FakeName'))
        del input['consumer']
        expected.update(dict(specs=input))
        self.assertDictMatch(expected, specs)

        self.stubs.Set(db, 'qos_specs_create',
                       fake_db_qos_specs_create)

        # qos specs must have unique name
        self.assertRaises(exception.QoSSpecsExists,
                          qos_specs.create, self.ctxt, 'DupQoSName', input)

        input.update({'consumer': 'FakeConsumer'})
        # consumer must be one of: front-end, back-end, both
        self.assertRaises(exception.InvalidQoSSpecs,
                          qos_specs.create, self.ctxt, 'QoSName', input)

        del input['consumer']
        # able to catch DBError
        self.assertRaises(exception.QoSSpecsCreateFailed,
                          qos_specs.create, self.ctxt, 'FailQoSName', input)
Пример #15
0
    def _get_qos_by_volume_type(self, ctxt, type_id):
        """Get the properties which can be QoS or file system related."""

        update_qos_group_params = {}
        update_file_system_params = {}

        volume_type = volume_types.get_volume_type(ctxt, type_id)
        qos_specs_id = volume_type.get('qos_specs_id')
        extra_specs = volume_type.get('extra_specs')

        if qos_specs_id is not None:
            specs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']

            # Override extra specs with specs
            # Hence specs will prefer QoS than extra specs
            extra_specs.update(specs)

        for key, value in extra_specs.items():
            if ':' in key:
                fields = key.split(':')
                key = fields[1]

            if key in self.configuration.cb_update_qos_group:
                update_qos_group_params[key] = value

            elif key in self.configuration.cb_update_file_system:
                update_file_system_params[key] = value

        return update_qos_group_params, update_file_system_params
Пример #16
0
    def test_create(self):
        input = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
        ref = qos_specs.create(self.ctxt, 'FakeName', input)
        specs = qos_specs.get_qos_specs(self.ctxt, ref['id'])
        expected = (dict(consumer='back-end'))
        expected.update(dict(id=ref['id']))
        expected.update(dict(name='FakeName'))
        del input['consumer']
        expected.update(dict(specs=input))
        self.assertDictMatch(specs, expected)

        self.stubs.Set(db, 'qos_specs_create', fake_db_qos_specs_create)

        # qos specs must have unique name
        self.assertRaises(exception.QoSSpecsExists, qos_specs.create,
                          self.ctxt, 'DupQoSName', input)

        input.update({'consumer': 'FakeConsumer'})
        # consumer must be one of: front-end, back-end, both
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.create,
                          self.ctxt, 'QoSName', input)

        del input['consumer']
        # able to catch DBError
        self.assertRaises(exception.QoSSpecsCreateFailed, qos_specs.create,
                          self.ctxt, 'FailQoSName', input)
Пример #17
0
    def _get_qos_by_volume_type(self, ctxt, type_id):
        """Get the properties which can be QoS or file system related."""

        update_qos_group_params = {}
        update_file_system_params = {}

        volume_type = volume_types.get_volume_type(ctxt, type_id)
        qos_specs_id = volume_type.get('qos_specs_id')
        extra_specs = volume_type.get('extra_specs')

        if qos_specs_id is not None:
            specs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']

            # Override extra specs with specs
            # Hence specs will prefer QoS than extra specs
            extra_specs.update(specs)

        for key, value in extra_specs.items():
            if ':' in key:
                fields = key.split(':')
                key = fields[1]

            if key in self.configuration.cb_update_qos_group:
                update_qos_group_params[key] = value

            elif key in self.configuration.cb_update_file_system:
                update_file_system_params[key] = value

        return update_qos_group_params, update_file_system_params
Пример #18
0
    def test_update(self):
        def fake_db_update(context, specs_id, values):
            raise db_exc.DBError()

        qos = {'consumer': 'back-end',
               'specs': {'key1': 'value1'}}

        # qos specs must exists
        self.assertRaises(exception.QoSSpecsNotFound,
                          qos_specs.update, self.ctxt, 'fake_id', qos['specs'])

        specs_id = self._create_qos_specs('Name',
                                          qos['consumer'],
                                          qos['specs'])

        qos_specs.update(self.ctxt, specs_id,
                         {'key1': 'newvalue1', 'key2': 'value2'})

        specs = qos_specs.get_qos_specs(self.ctxt, specs_id)
        self.assertEqual('newvalue1', specs['specs']['key1'])
        self.assertEqual('value2', specs['specs']['key2'])

        # consumer must be one of: front-end, back-end, both
        self.assertRaises(exception.InvalidQoSSpecs,
                          qos_specs.update, self.ctxt, specs_id,
                          {'consumer': 'not-real'})

        self.mock_object(db, 'qos_specs_update', fake_db_update)
        self.assertRaises(exception.QoSSpecsUpdateFailed,
                          qos_specs.update, self.ctxt, specs_id, {'key':
                                                                  'new_key'})
Пример #19
0
    def get_qos_by_volume_type(volume_type):
        # We prefer the qos_specs association
        # and override any existing extra-specs settings
        # if present.
        if not volume_type:
            return {}

        qos_specs_id = volume_type.get('qos_specs_id')
        if not qos_specs_id:
            return {}

        qos = {}
        ctxt = context.get_admin_context()
        kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
        LOG.info(_LI('The QoS sepcs is: %s.'), kvs)
        for k, v in kvs.items():
            if k not in constants.HUAWEI_VALID_KEYS:
                continue

            if k.upper() != 'IOTYPE' and int(v) <= 0:
                msg = _('QoS config is wrong. %s must > 0.') % k
                LOG.error(msg)
                raise exception.InvalidInput(reason=msg)
            elif k.upper() == 'IOTYPE' and v not in ['0', '1', '2']:
                msg = _('Illegal value specified for IOTYPE: 0, 1, or 2.')
                LOG.error(msg)
                raise exception.InvalidInput(reason=msg)
            else:
                qos[k.upper()] = v

        return qos
Пример #20
0
    def delete_keys(self, req, id, body):
        """Deletes specified keys in qos specs."""
        context = req.environ['cinder.context']
        context.authorize(policy.DELETE_POLICY)

        if not (body and 'keys' in body
                and isinstance(body.get('keys'), list)):
            raise webob.exc.HTTPBadRequest()

        keys = body['keys']
        LOG.debug("Delete_key spec: %(id)s, keys: %(keys)s", {
            'id': id,
            'keys': keys
        })

        try:
            qos_specs.delete_keys(context, id, keys)
            spec = qos_specs.get_qos_specs(context, id)
            notifier_info = dict(id=id,
                                 created_at=spec.created_at,
                                 updated_at=spec.updated_at)
            rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.delete_keys',
                                              notifier_info)
        except exception.NotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.delete_keys',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise

        return webob.Response(status_int=http_client.ACCEPTED)
Пример #21
0
    def associations(self, req, id):
        """List all associations of given qos specs."""
        context = req.environ['cinder.context']
        context.authorize(policy.GET_ALL_POLICY)

        LOG.debug("Get associations for qos_spec id: %s", id)

        try:
            spec = qos_specs.get_qos_specs(context, id)

            associates = qos_specs.get_associations(context, id)
            notifier_info = dict(id=id,
                                 created_at=spec.created_at)
            rpc.get_notifier('QoSSpecs').info(context,
                                              'qos_specs.associations',
                                              notifier_info)
        except exception.QoSSpecsNotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.associations',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.CinderException as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.associations',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return self._view_builder.associations(req, associates)
Пример #22
0
def get_qos_by_volume_type(volume_type):
    qos = {}
    qos_specs_id = volume_type.get('qos_specs_id')

    # We prefer the qos_specs association
    # and override any existing extra-specs settings
    # if present.
    if qos_specs_id is not None:
        kvs = qos_specs.get_qos_specs(context.get_admin_context(),
                                      qos_specs_id)['specs']
    else:
        return qos

    LOG.info(_LI('The QoS sepcs is: %s.'), kvs)
    for key, value in kvs.items():
        if key in constants.HUAWEI_VALID_KEYS:
            if (key.upper() != 'IOTYPE') and (int(value) <= 0):
                err_msg = (_('Qos config is wrong. %(key)s'
                             ' must be set greater than 0.')
                           % {'key': key})
                LOG.error(err_msg)
                raise exception.VolumeBackendAPIException(data=err_msg)
            elif (key.upper() == 'IOTYPE') and (value not in ['0', '1', '2']):
                raise exception.InvalidInput(
                    reason=(_('Illegal value specified for IOTYPE: '
                              'set to either 0, 1, or 2.')))
            else:
                qos[key.upper()] = value

    return qos
Пример #23
0
    def update(self, req, id, body=None):
        context = req.environ['cinder.context']
        context.authorize(policy.UPDATE_POLICY)

        specs = body['qos_specs']
        try:
            spec = qos_specs.get_qos_specs(context, id)

            qos_specs.update(context, id, specs)
            notifier_info = dict(id=id,
                                 created_at=spec.created_at,
                                 updated_at=timeutils.utcnow(),
                                 specs=specs)
            rpc.get_notifier('QoSSpecs').info(context,
                                              'qos_specs.update',
                                              notifier_info)
        except (exception.QoSSpecsNotFound, exception.InvalidQoSSpecs) as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.update',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.QoSSpecsUpdateFailed as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.update',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return body
Пример #24
0
    def delete_keys(self, req, id, body):
        """Deletes specified keys in qos specs."""
        context = req.environ['cinder.context']
        context.authorize(policy.DELETE_POLICY)

        keys = body['keys']
        LOG.debug("Delete_key spec: %(id)s, keys: %(keys)s",
                  {'id': id, 'keys': keys})

        try:
            qos_specs.delete_keys(context, id, keys)
            spec = qos_specs.get_qos_specs(context, id)
            notifier_info = dict(id=id,
                                 created_at=spec.created_at,
                                 updated_at=spec.updated_at)
            rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.delete_keys',
                                              notifier_info)
        except exception.NotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.delete_keys',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise

        return webob.Response(status_int=http_client.ACCEPTED)
Пример #25
0
    def get_vdisk_params(self, config, state, type_id, volume_type=None,
                         volume_metadata=None):
        """Return the parameters for creating the vdisk.

        Takes volume type and defaults from config options into account.
        """
        opts = self.build_default_opts(config)
        ctxt = context.get_admin_context()
        if volume_type is None and type_id is not None:
            volume_type = volume_types.get_volume_type(ctxt, type_id)
        if volume_type:
            qos_specs_id = volume_type.get('qos_specs_id')
            specs = dict(volume_type).get('extra_specs')

            # NOTE(vhou): We prefer the qos_specs association
            # and over-ride any existing
            # extra-specs settings if present
            if qos_specs_id is not None:
                kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
                # Merge the qos_specs into extra_specs and qos_specs has higher
                # priority than extra_specs if they have different values for
                # the same key.
                specs.update(kvs)
            opts = self._get_opts_from_specs(opts, specs)
        if (opts['qos'] is None and config.storwize_svc_allow_tenant_qos
                and volume_metadata):
            qos = self._get_qos_from_volume_metadata(volume_metadata)
            if len(qos) != 0:
                opts['qos'] = qos

        self.check_vdisk_opts(state, opts)
        return opts
Пример #26
0
    def disassociate_all(self, req, id):
        """Disassociate a qos specs from all volume types."""
        context = req.environ['cinder.context']
        context.authorize(policy.UPDATE_POLICY)

        LOG.debug("Disassociate qos_spec: %s from all.", id)

        try:
            spec = qos_specs.get_qos_specs(context, id)

            qos_specs.disassociate_all(context, id)
            notifier_info = dict(id=id, created_at=spec.created_at)
            rpc.get_notifier('QoSSpecs').info(context,
                                              'qos_specs.disassociate_all',
                                              notifier_info)
        except exception.QoSSpecsNotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.disassociate_all',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.QoSSpecsDisassociateFailed as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.disassociate_all',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return webob.Response(status_int=http_client.ACCEPTED)
Пример #27
0
    def test_update(self):
        def fake_db_update(context, specs_id, values):
            raise db_exc.DBError()

        qos = {'consumer': 'back-end', 'specs': {'key1': 'value1'}}

        # qos specs must exists
        self.assertRaises(exception.QoSSpecsNotFound, qos_specs.update,
                          self.ctxt, 'fake_id', qos)

        specs_id = self._create_qos_specs('Name', qos['consumer'],
                                          qos['specs'])

        qos_specs.update(self.ctxt, specs_id, {
            'key1': 'newvalue1',
            'key2': 'value2'
        })

        specs = qos_specs.get_qos_specs(self.ctxt, specs_id)
        self.assertEqual('newvalue1', specs['specs']['key1'])
        self.assertEqual('value2', specs['specs']['key2'])

        # consumer must be one of: front-end, back-end, both
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.update,
                          self.ctxt, specs_id, {'consumer': 'not-real'})

        self.stubs.Set(db, 'qos_specs_update', fake_db_update)
        self.assertRaises(exception.QoSSpecsUpdateFailed, qos_specs.update,
                          self.ctxt, specs_id, {'key': 'new_key'})
Пример #28
0
    def test_update(self):
        def fake_db_update(context, specs_id, values):
            raise db_exc.DBError()

        input = {'key1': 'value1',
                 'consumer': 'WrongPlace'}
        # consumer must be one of: front-end, back-end, both
        self.assertRaises(exception.InvalidQoSSpecs,
                          qos_specs.update, self.ctxt, 'fake_id', input)

        input['consumer'] = 'front-end'
        # qos specs must exists
        self.assertRaises(exception.QoSSpecsNotFound,
                          qos_specs.update, self.ctxt, 'fake_id', input)

        specs_id = self._create_qos_specs('Name', input)
        qos_specs.update(self.ctxt, specs_id,
                         {'key1': 'newvalue1',
                          'key2': 'value2'})
        specs = qos_specs.get_qos_specs(self.ctxt, specs_id)
        self.assertEqual('newvalue1', specs['specs']['key1'])
        self.assertEqual('value2', specs['specs']['key2'])

        self.stubs.Set(db, 'qos_specs_update', fake_db_update)
        self.assertRaises(exception.QoSSpecsUpdateFailed,
                          qos_specs.update, self.ctxt, 'fake_id', input)
Пример #29
0
    def update(self, req, id, body=None):
        context = req.environ['cinder.context']
        context.authorize(policy.UPDATE_POLICY)
        self.assert_valid_body(body, 'qos_specs')
        specs = body['qos_specs']
        try:
            spec = qos_specs.get_qos_specs(context, id)

            qos_specs.update(context, id, specs)
            notifier_info = dict(id=id,
                                 created_at=spec.created_at,
                                 updated_at=timeutils.utcnow(),
                                 specs=specs)
            rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.update',
                                              notifier_info)
        except (exception.QoSSpecsNotFound, exception.InvalidQoSSpecs) as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.update',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.QoSSpecsUpdateFailed as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.update',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return body
Пример #30
0
 def test_get_qos_specs(self):
     one_time_value = str(int(time.time()))
     specs = {'key1': one_time_value, 'key2': 'value2', 'key3': 'value3'}
     qos_id = self._create_qos_specs('Specs1', 'both', specs)
     specs = qos_specs.get_qos_specs(self.ctxt, qos_id)
     self.assertEqual(one_time_value, specs['specs']['key1'])
     self.assertRaises(exception.InvalidQoSSpecs, qos_specs.get_qos_specs,
                       self.ctxt, None)
Пример #31
0
    def show(self, req, id):
        """Return a single qos spec item."""
        context = req.environ['cinder.context']
        authorize(context)

        # Not found exception will be handled at the wsgi level
        spec = qos_specs.get_qos_specs(context, id)

        return self._view_builder.detail(req, spec)
Пример #32
0
    def get_qos_by_volume_type(volume_type):
        # We prefer the qos_specs association
        # and override any existing extra-specs settings
        # if present.
        if not volume_type:
            return {}

        qos_specs_id = volume_type.get('qos_specs_id')
        if not qos_specs_id:
            return {}

        qos = {}
        io_type_flag = None
        ctxt = context.get_admin_context()
        kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
        LOG.info(_LI('The QoS sepcs is: %s.'), kvs)
        for k, v in kvs.items():
            if k not in constants.HUAWEI_VALID_KEYS:
                continue
            if k != 'IOType' and int(v) <= 0:
                msg = _('QoS config is wrong. %s must > 0.') % k
                LOG.error(msg)
                raise exception.InvalidInput(reason=msg)
            if k == 'IOType':
                if v not in ['0', '1', '2']:
                    msg = _('Illegal value specified for IOTYPE: 0, 1, or 2.')
                    LOG.error(msg)
                    raise exception.InvalidInput(reason=msg)
                io_type_flag = 1
                qos[k.upper()] = v
            else:
                qos[k.upper()] = v

        if not io_type_flag:
            msg = (_('QoS policy must specify for IOTYPE: 0, 1, or 2, '
                     'QoS policy: %(qos_policy)s ') % {'qos_policy': qos})
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        # QoS policy must specify for IOTYPE and another qos_specs.
        if len(qos) < 2:
            msg = (_('QoS policy must specify for IOTYPE and another '
                     'qos_specs, QoS policy: %(qos_policy)s.')
                   % {'qos_policy': qos})
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        for upper_limit in constants.UPPER_LIMIT_KEYS:
            for lower_limit in constants.LOWER_LIMIT_KEYS:
                if upper_limit in qos and lower_limit in qos:
                    msg = (_('QoS policy upper_limit and lower_limit '
                             'conflict, QoS policy: %(qos_policy)s.')
                           % {'qos_policy': qos})
                    LOG.error(msg)
                    raise exception.InvalidInput(reason=msg)

        return qos
Пример #33
0
    def test_get_qos_specs(self):
        one_time_value = str(int(time.time()))
        input = {'key1': one_time_value, 'key2': 'value2', 'key3': 'value3'}
        id = self._create_qos_specs('Specs1', input)
        specs = qos_specs.get_qos_specs(self.ctxt, id)
        self.assertEquals(specs['Specs1']['key1'], one_time_value)

        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.get_qos_specs,
                          self.ctxt, None)
Пример #34
0
    def disassociate(self, req, id):
        """Disassociate a qos specs from a volume type."""
        context = req.environ['cinder.context']
        authorize(context)

        type_id = req.params.get('vol_type_id', None)

        if not type_id:
            msg = _('Volume Type id must not be None.')
            notifier_err = dict(id=id, error_message=msg)
            self._notify_qos_specs_error(context,
                                         'qos_specs.delete',
                                         notifier_err)
            raise webob.exc.HTTPBadRequest(explanation=msg)
        LOG.debug("Disassociate qos_spec: %(id)s from type: %(type_id)s" %
                  {'id': id, 'type_id': type_id})

        try:
            qos_specs.get_qos_specs(context, id)
            qos_specs.disassociate_qos_specs(context, id, type_id)
            notifier_info = dict(id=id, type_id=type_id)
            notifier_api.notify(context, 'QoSSpecs',
                                'qos_specs.disassociate',
                                notifier_api.INFO, notifier_info)
        except exception.VolumeTypeNotFound as err:
            notifier_err = dict(id=id, error_message=str(err))
            self._notify_qos_specs_error(context,
                                         'qos_specs.disassociate',
                                         notifier_err)
            raise webob.exc.HTTPNotFound(explanation=str(err))
        except exception.QoSSpecsNotFound as err:
            notifier_err = dict(id=id, error_message=str(err))
            self._notify_qos_specs_error(context,
                                         'qos_specs.disassociate',
                                         notifier_err)
            raise webob.exc.HTTPNotFound(explanation=str(err))
        except exception.QoSSpecsDisassociateFailed as err:
            notifier_err = dict(id=id, error_message=str(err))
            self._notify_qos_specs_error(context,
                                         'qos_specs.disassociate',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(explanation=str(err))

        return webob.Response(status_int=202)
Пример #35
0
 def test_get_qos_specs(self):
     one_time_value = str(int(time.time()))
     specs = {'key1': one_time_value,
              'key2': 'value2',
              'key3': 'value3'}
     qos_id = self._create_qos_specs('Specs1', 'both', specs)
     specs = qos_specs.get_qos_specs(self.ctxt, qos_id)
     self.assertEqual(one_time_value, specs['specs']['key1'])
     self.assertRaises(exception.InvalidQoSSpecs,
                       qos_specs.get_qos_specs, self.ctxt, None)
    def _retrieve_qos_info(self, ctxt, type_id):
        qosspec = {}
        volume_type = volume_types.get_volume_type(ctxt, type_id)
        qos_specs_id = volume_type.get('qos_specs_id')
        voltype = volume_type.get('extra_specs')

        if qos_specs_id is not None:
            qosspec = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']

        return voltype, qosspec
Пример #37
0
    def test_get_qos_specs(self):
        one_time_value = str(int(time.time()))
        input = {'key1': one_time_value,
                 'key2': 'value2',
                 'key3': 'value3'}
        id = self._create_qos_specs('Specs1', input)
        specs = qos_specs.get_qos_specs(self.ctxt, id)
        self.assertEquals(specs['Specs1']['key1'], one_time_value)

        self.assertRaises(exception.InvalidQoSSpecs,
                          qos_specs.get_qos_specs, self.ctxt, None)
Пример #38
0
    def show(self, req, id):
        """Return a single qos spec item."""
        context = req.environ['cinder.context']
        authorize(context)

        try:
            spec = qos_specs.get_qos_specs(context, id)
        except exception.NotFound:
            raise webob.exc.HTTPNotFound()

        return spec
    def show(self, req, id):
        """Return a single qos spec item."""
        context = req.environ['cinder.context']
        authorize(context)

        try:
            spec = qos_specs.get_qos_specs(context, id)
        except exception.QoSSpecsNotFound as err:
            raise webob.exc.HTTPNotFound(explanation=str(err))

        return self._view_builder.detail(req, spec)
Пример #40
0
    def show(self, req, id):
        """Return a single qos spec item."""
        context = req.environ["cinder.context"]
        authorize(context)

        try:
            spec = qos_specs.get_qos_specs(context, id)
        except exception.QoSSpecsNotFound as err:
            raise webob.exc.HTTPNotFound(explanation=str(err))

        return self._view_builder.detail(req, spec)
Пример #41
0
def get_backend_qos_spec_from_volume_type(volume_type):
    qos_specs_id = volume_type.get('qos_specs_id')
    if qos_specs_id is None:
        return None
    ctxt = context.get_admin_context()
    qos_spec = qos_specs.get_qos_specs(ctxt, qos_specs_id)
    if qos_spec is None:
        return None
    consumer = qos_spec['consumer']
    # Front end QoS specs are handled by libvirt and we ignore them here.
    if consumer not in BACKEND_QOS_CONSUMERS:
        return None
    return qos_spec['specs']
Пример #42
0
    def associate(self, req, id):
        """Associate a qos specs with a volume type."""
        context = req.environ['cinder.context']
        context.authorize(policy.UPDATE_POLICY)

        type_id = req.params.get('vol_type_id', None)

        if not type_id:
            msg = _('Volume Type id must not be None.')
            notifier_err = dict(id=id, error_message=msg)
            self._notify_qos_specs_error(context,
                                         'qos_specs.delete',
                                         notifier_err)
            raise webob.exc.HTTPBadRequest(explanation=msg)
        LOG.debug("Associate qos_spec: %(id)s with type: %(type_id)s",
                  {'id': id, 'type_id': type_id})

        try:
            spec = qos_specs.get_qos_specs(context, id)

            qos_specs.associate_qos_with_type(context, id, type_id)
            notifier_info = dict(id=id, type_id=type_id,
                                 created_at=spec.created_at)
            rpc.get_notifier('QoSSpecs').info(context,
                                              'qos_specs.associate',
                                              notifier_info)
        except exception.NotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.associate',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.InvalidVolumeType as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.associate',
                                         notifier_err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.associate',
                                         notifier_err)
            raise webob.exc.HTTPBadRequest(explanation=six.text_type(err))
        except exception.QoSSpecsAssociateFailed as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context,
                                         'qos_specs.associate',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return webob.Response(status_int=http_client.ACCEPTED)
Пример #43
0
def get_backend_qos_spec_from_volume_type(volume_type):
    qos_specs_id = volume_type.get('qos_specs_id')
    if qos_specs_id is None:
        return None
    ctxt = context.get_admin_context()
    qos_spec = qos_specs.get_qos_specs(ctxt, qos_specs_id)
    if qos_spec is None:
        return None
    consumer = qos_spec['consumer']
    # Front end QoS specs are handled by libvirt and we ignore them here.
    if consumer not in BACKEND_QOS_CONSUMERS:
        return None
    spec_key_values = qos_spec['specs']
    return spec_key_values
Пример #44
0
def _get_qos_specs(qos_specs_id):
    ctxt = context.get_admin_context()
    specs = qos_specs.get_qos_specs(ctxt, qos_specs_id)
    if specs is None:
        return {}

    if specs.get('consumer') == 'front-end':
        return {}

    kvs = specs.get('specs', {})
    LOG.info('The QoS specs is: %s.', kvs)

    qos = {'IOTYPE': kvs.pop('IOType', None)}

    if qos['IOTYPE'] not in constants.QOS_IOTYPES:
        msg = _('IOType must be in %(types)s.') % {
            'types': constants.QOS_IOTYPES
        }
        LOG.error(msg)
        raise exception.InvalidInput(reason=msg)

    for k, v in kvs.items():
        if k not in constants.QOS_SPEC_KEYS:
            msg = _('QoS key %s is not valid.') % k
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        if int(v) <= 0:
            msg = _('QoS value for %s must > 0.') % k
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        qos[k.upper()] = v

    if len(qos) < 2:
        msg = _('QoS policy must specify both IOType and one another '
                'qos spec, got policy: %s.') % qos
        LOG.error(msg)
        raise exception.InvalidInput(reason=msg)

    qos_keys = set(qos.keys())
    if (qos_keys & set(constants.UPPER_LIMIT_KEYS)
            and qos_keys & set(constants.LOWER_LIMIT_KEYS)):
        msg = _('QoS policy upper limit and lower limit '
                'conflict, QoS policy: %s.') % qos
        LOG.error(msg)
        raise exception.InvalidInput(reason=msg)

    return qos
Пример #45
0
 def _get_volumetype_qos(self, volume):
     qos = {}
     ctxt = context.get_admin_context()
     type_id = volume['volume_type_id']
     if type_id:
         volume_type = volume_types.get_volume_type(ctxt, type_id)
         qos_specs_id = volume_type.get('qos_specs_id')
         if qos_specs_id is not None:
             specs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
         else:
             specs = {}
         for key, value in specs.items():
             if key in self.scaleio_qos_keys:
                 qos[key] = value
     return qos
Пример #46
0
    def associate(self, req, id):
        """Associate a qos specs with a volume type."""
        context = req.environ['cinder.context']
        context.authorize(policy.UPDATE_POLICY)

        type_id = req.params.get('vol_type_id', None)

        if not type_id:
            msg = _('Volume Type id must not be None.')
            notifier_err = dict(id=id, error_message=msg)
            self._notify_qos_specs_error(context, 'qos_specs.delete',
                                         notifier_err)
            raise webob.exc.HTTPBadRequest(explanation=msg)
        LOG.debug("Associate qos_spec: %(id)s with type: %(type_id)s", {
            'id': id,
            'type_id': type_id
        })

        try:
            spec = qos_specs.get_qos_specs(context, id)

            qos_specs.associate_qos_with_type(context, id, type_id)
            notifier_info = dict(id=id,
                                 type_id=type_id,
                                 created_at=spec.created_at)
            rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.associate',
                                              notifier_info)
        except exception.NotFound as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.associate',
                                         notifier_err)
            # Not found exception will be handled at the wsgi level
            raise
        except exception.InvalidVolumeType as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.associate',
                                         notifier_err)
            self._notify_qos_specs_error(context, 'qos_specs.associate',
                                         notifier_err)
            raise webob.exc.HTTPBadRequest(explanation=six.text_type(err))
        except exception.QoSSpecsAssociateFailed as err:
            notifier_err = dict(id=id, error_message=err)
            self._notify_qos_specs_error(context, 'qos_specs.associate',
                                         notifier_err)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return webob.Response(status_int=http_client.ACCEPTED)
Пример #47
0
 def _set_qos_by_volume_type(self, type_id):
     valid_presets = self.fio_qos_dict.keys()
     volume_type = volume_types.get_volume_type(ctxt=None, id=type_id)
     qos_specs_id = volume_type.get('qos_specs_id')
     specs = volume_type.get('extra_specs')
     if qos_specs_id is not None:
         kvs = qos_specs.get_qos_specs(ctxt=None, id=qos_specs_id)['specs']
     else:
         kvs = specs
     for key, value in kvs.iteritems():
         if ':' in key:
             fields = key.split(':')
             key = fields[1]
         if 'fio-qos' in key:
             if value in valid_presets:
                 return self.fio_qos_dict[value]
Пример #48
0
 def _set_qos_by_volume_type(self, type_id):
     valid_presets = self.fio_qos_dict.keys()
     volume_type = volume_types.get_volume_type(ctxt=None, id=type_id)
     qos_specs_id = volume_type.get("qos_specs_id")
     specs = volume_type.get("extra_specs")
     if qos_specs_id is not None:
         kvs = qos_specs.get_qos_specs(ctxt=None, id=qos_specs_id)["specs"]
     else:
         kvs = specs
     for key, value in kvs.iteritems():
         if ":" in key:
             fields = key.split(":")
             key = fields[1]
         if "fio-qos" in key:
             if value in valid_presets:
                 return self.fio_qos_dict[value]
Пример #49
0
    def _get_policies_for_resource(self, resource):
        """Get extra_specs and qos_specs of a volume_type.

        This fetches the scoped keys from the volume type. Anything set from
         qos_specs will override key/values set from extra_specs.
        """
        type_id = resource.get('volume_type_id', None)
        # Handle case of volume with no type.  We still want the
        # specified defaults from above
        if type_id:
            ctxt = context.get_admin_context()
            volume_type = volume_types.get_volume_type(ctxt, type_id)
            specs = volume_type.get('extra_specs')
        else:
            volume_type = None
            specs = {}

        # Set defaults:
        policies = {k.lstrip('DF:'): str(v['default']) for (k, v)
                    in self._init_vendor_properties()[0].items()}

        if volume_type:
            # Populate updated value
            for key, value in specs.items():
                if ':' in key:
                    fields = key.split(':')
                    key = fields[1]
                    policies[key] = value

            qos_specs_id = volume_type.get('qos_specs_id')
            if qos_specs_id is not None:
                qos_kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
                if qos_kvs:
                    policies.update(qos_kvs)
        # Cast everything except booleans int that can be cast
        for k, v in policies.items():
            # Handle String Boolean case
            if v == 'True' or v == 'False':
                policies[k] = policies[k] == 'True'
                continue
            # Int cast
            try:
                policies[k] = int(v)
            except ValueError:
                pass
        return policies
def _get_policies_for_resource(driver, resource):
    """Get extra_specs and qos_specs of a volume_type.

    This fetches the scoped keys from the volume type. Anything set from
     qos_specs will override key/values set from extra_specs.
    """
    volume_type = driver._get_volume_type_obj(resource)
    # Handle case of volume with no type.  We still want the
    # specified defaults from above
    if volume_type:
        specs = volume_type.get('extra_specs')
    else:
        specs = {}

    # Set defaults:
    policies = {
        k.lstrip('DF:'): str(v['default'])
        for (k, v) in driver._init_vendor_properties()[0].items()
    }

    if volume_type:
        # Populate updated value
        for key, value in specs.items():
            if ':' in key:
                fields = key.split(':')
                key = fields[1]
                policies[key] = value

        qos_specs_id = volume_type.get('qos_specs_id')
        if qos_specs_id is not None:
            ctxt = context.get_admin_context()
            qos_kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
            if qos_kvs:
                policies.update(qos_kvs)
    # Cast everything except booleans int that can be cast
    for k, v in policies.items():
        # Handle String Boolean case
        if v == 'True' or v == 'False':
            policies[k] = policies[k] == 'True'
            continue
        # Int cast
        try:
            policies[k] = int(v)
        except ValueError:
            pass
    return policies
Пример #51
0
    def test_delete_keys(self):
        def fake_db_qos_delete_key(context, id, key):
            if key == 'NotFound':
                raise exception.QoSSpecsKeyNotFound(specs_id=id, specs_key=key)
            else:
                pass

        def fake_qos_specs_get(context, id):
            if id == 'NotFound':
                raise exception.QoSSpecsNotFound(specs_id=id)
            else:
                pass

        value = {'foo': 'Foo', 'bar': 'Bar', 'zoo': 'tiger'}
        name = 'QoSName'
        consumer = 'front-end'
        specs_id = self._create_qos_specs(name, consumer, value)
        qos_specs.delete_keys(self.ctxt, specs_id, ['foo', 'bar'])

        del value['foo']
        del value['bar']
        expected = {
            'name': name,
            'id': specs_id,
            'consumer': consumer,
            'specs': value
        }
        specs = qos_specs.get_qos_specs(self.ctxt, specs_id)
        specs_dic = {
            'consumer': specs['consumer'],
            'id': specs['id'],
            'name': specs['name'],
            'specs': specs['specs']
        }
        self.assertDictMatch(expected, specs_dic)

        self.stubs.Set(db, 'qos_specs_item_delete', fake_db_qos_delete_key)
        self.assertRaises(exception.InvalidQoSSpecs, qos_specs.delete_keys,
                          self.ctxt, None, [])
        self.assertRaises(exception.QoSSpecsNotFound, qos_specs.delete_keys,
                          self.ctxt, 'NotFound', [])
        self.assertRaises(exception.QoSSpecsKeyNotFound, qos_specs.delete_keys,
                          self.ctxt, specs_id, ['NotFound'])
        self.assertRaises(exception.QoSSpecsKeyNotFound, qos_specs.delete_keys,
                          self.ctxt, specs_id, ['foo', 'bar', 'NotFound'])
Пример #52
0
    def _get_qos_by_volume_type(self, ctxt, type_id):
        qos = {}

        # NOTE(bardia): we only honor qos_specs
        if type_id:
            volume_type = volume_types.get_volume_type(ctxt, type_id)
            qos_specs_id = volume_type.get('qos_specs_id')

            if qos_specs_id is not None:
                kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
                qos['uuid'] = qos_specs_id
            else:
                kvs = {}

            for key, value in kvs.items():
                if key in self.COHO_QOS_KEYS:
                    qos[key] = int(value)
        return qos
Пример #53
0
 def _set_qos_by_volume_type(self, type_id):
     valid_presets = self.fio_qos_dict.keys()
     volume_type = volume_types.get_volume_type(ctxt=None,
                                                id=type_id)
     qos_specs_id = volume_type.get('qos_specs_id')
     specs = volume_type.get('extra_specs')
     if qos_specs_id is not None:
         kvs = qos_specs.get_qos_specs(ctxt=None,
                                       id=qos_specs_id)['specs']
     else:
         kvs = specs
     for key, value in kvs.iteritems():
         if ':' in key:
             fields = key.split(':')
             key = fields[1]
         if 'fio-qos' in key:
             if value in valid_presets:
                 return self.fio_qos_dict[value]
Пример #54
0
    def _get_qos_by_volume_type(self, ctxt, type_id):
        qos = {}

        # NOTE(bardia): we only honor qos_specs
        if type_id:
            volume_type = volume_types.get_volume_type(ctxt, type_id)
            qos_specs_id = volume_type.get('qos_specs_id')

            if qos_specs_id is not None:
                kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
                qos['uuid'] = qos_specs_id
            else:
                kvs = {}

            for key, value in kvs.items():
                if key in self.COHO_QOS_KEYS:
                    qos[key] = int(value)
        return qos
Пример #55
0
def _get_qos_specs(qos_specs_id, client):
    ctxt = context.get_admin_context()
    specs = qos_specs.get_qos_specs(ctxt, qos_specs_id)
    if specs is None:
        return {}

    if specs.get('consumer') == 'front-end':
        return {}

    kvs = specs.get('specs', {})
    LOG.info('The QoS specs is: %s.', kvs)

    qos = dict()
    for k, v in kvs.items():
        if k not in constants.QOS_KEYS + constants.QOS_SCHEDULER_KEYS:
            msg = _('QoS key %s is not valid.') % k
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

        if k in constants.QOS_KEYS:
            if int(v) <= 0:
                msg = _('QoS value for %s must > 0.') % k
                LOG.error(msg)
                raise exception.InvalidInput(reason=msg)

            qos[k] = int(v.encode("utf-8"))
        elif k in constants.QOS_SCHEDULER_KEYS:
            qos[k] = v.strip()

    for item in constants.QOS_MUST_SET:
        if qos.get(item) is None:
            msg = _('maxIOPS and maxMBPS must be set for QoS: %s') % qos
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

    if qos.get(constants.QOS_SCHEDULER_KEYS[0]):
        if client.get_fsm_version() >= constants.QOS_SUPPORT_SCHEDULE_VERSION:
            qos = _check_and_convert_qos(qos, client)
        else:
            msg = _('FusionStorage Version is not suitable for QoS: %s') % qos
            LOG.error(msg)
            raise exception.InvalidInput(reason=msg)

    return qos