neutron/neutron/objects/qos/rule.py

158 lines
5.0 KiB
Python

# Copyright 2015 Huawei Technologies India Pvt Ltd, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# 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 abc
from oslo_versionedobjects import base as obj_base
from oslo_versionedobjects import fields as obj_fields
import six
from neutron.db import api as db_api
from neutron.db.qos import models as qos_db_model
from neutron.extensions import qos as qos_extension
from neutron.objects import base
@six.add_metaclass(abc.ABCMeta)
class QosRule(base.NeutronObject):
base_db_model = qos_db_model.QosRule
fields = {
'id': obj_fields.UUIDField(),
'type': obj_fields.StringField(),
'qos_policy_id': obj_fields.UUIDField()
}
fields_no_update = ['id', 'tenant_id', 'qos_policy_id']
# each rule subclass should redefine it
rule_type = None
_core_fields = list(fields.keys())
_common_fields = ['id']
@classmethod
def _is_common_field(cls, field):
return field in cls._common_fields
@classmethod
def _is_core_field(cls, field):
return field in cls._core_fields
@classmethod
def _is_addn_field(cls, field):
return not cls._is_core_field(field) or cls._is_common_field(field)
@staticmethod
def _filter_fields(fields, func):
return {
key: val for key, val in fields.items()
if func(key)
}
def _get_changed_core_fields(self):
fields = self.obj_get_changes()
return self._filter_fields(fields, self._is_core_field)
def _get_changed_addn_fields(self):
fields = self.obj_get_changes()
return self._filter_fields(fields, self._is_addn_field)
def _copy_common_fields(self, from_, to_):
for field in self._common_fields:
to_[field] = from_[field]
@classmethod
def get_objects(cls, context, **kwargs):
# TODO(QoS): support searching for subtype fields
db_objs = db_api.get_objects(context, cls.base_db_model, **kwargs)
return [cls.get_by_id(context, db_obj['id']) for db_obj in db_objs]
@classmethod
def get_by_id(cls, context, id):
obj = super(QosRule, cls).get_by_id(context, id)
if obj:
# the object above does not contain fields from base QosRule yet,
# so fetch it and mix its fields into the object
base_db_obj = db_api.get_object(context, cls.base_db_model, id)
for field in cls._core_fields:
setattr(obj, field, base_db_obj[field])
obj.obj_reset_changes()
return obj
# TODO(QoS): create and update are not transactional safe
def create(self):
# TODO(QoS): enforce that type field value is bound to specific class
self.type = self.rule_type
# create base qos_rule
core_fields = self._get_changed_core_fields()
base_db_obj = db_api.create_object(
self._context, self.base_db_model, core_fields)
# create type specific qos_..._rule
addn_fields = self._get_changed_addn_fields()
self._copy_common_fields(core_fields, addn_fields)
addn_db_obj = db_api.create_object(
self._context, self.db_model, addn_fields)
# merge two db objects into single neutron one
self.from_db_object(base_db_obj, addn_db_obj)
def update(self):
updated_db_objs = []
# TODO(QoS): enforce that type field cannot be changed
# update base qos_rule, if needed
core_fields = self._get_changed_core_fields()
if core_fields:
base_db_obj = db_api.update_object(
self._context, self.base_db_model, self.id, core_fields)
updated_db_objs.append(base_db_obj)
addn_fields = self._get_changed_addn_fields()
if addn_fields:
addn_db_obj = db_api.update_object(
self._context, self.db_model, self.id, addn_fields)
updated_db_objs.append(addn_db_obj)
# update neutron object with values from both database objects
self.from_db_object(*updated_db_objs)
# delete is the same, additional rule object cleanup is done thru cascading
@classmethod
def get_rules_by_policy(cls, context, policy_id):
return cls.get_objects(context, qos_policy_id=policy_id)
@obj_base.VersionedObjectRegistry.register
class QosBandwidthLimitRule(QosRule):
db_model = qos_db_model.QosBandwidthLimitRule
rule_type = qos_extension.RULE_TYPE_BANDWIDTH_LIMIT
fields = {
'max_kbps': obj_fields.IntegerField(nullable=True),
'max_burst_kbps': obj_fields.IntegerField(nullable=True)
}