First QoS versioned objects, ever
Well, first versioned objects in the tree. Binding to networks and ports is not implemented. No tests. Checked manually. blueprint quantum-qos-api Co-Authored-By: vikram.choudhary <vikram.choudhary@huawei.com> Change-Id: I9b6cacfda4f40230d746222bed5b6c490be63743
This commit is contained in:
parent
d7e60d59a3
commit
e90b28662e
|
@ -19,9 +19,12 @@ import six
|
|||
from oslo_config import cfg
|
||||
from oslo_db import exception as os_db_exception
|
||||
from oslo_db.sqlalchemy import session
|
||||
from oslo_utils import uuidutils
|
||||
from sqlalchemy import exc
|
||||
from sqlalchemy import orm
|
||||
|
||||
from neutron.db import common_db_mixin
|
||||
|
||||
|
||||
_FACADE = None
|
||||
|
||||
|
@ -85,3 +88,39 @@ class convert_db_exception_to_retry(object):
|
|||
except self.to_catch as e:
|
||||
raise os_db_exception.RetryRequest(e)
|
||||
return wrapper
|
||||
|
||||
|
||||
# Common database operation implementations
|
||||
def get_object(context, model, id):
|
||||
with context.session.begin(subtransactions=True):
|
||||
return (common_db_mixin.model_query(context, model)
|
||||
.filter_by(id=id)
|
||||
.one())
|
||||
|
||||
|
||||
def get_objects(context, model):
|
||||
with context.session.begin(subtransactions=True):
|
||||
return common_db_mixin.model_query(context, model).all()
|
||||
|
||||
|
||||
def create_object(context, model, values):
|
||||
with context.session.begin(subtransactions=True):
|
||||
if 'id' not in values:
|
||||
values['id'] = uuidutils.generate_uuid()
|
||||
db_obj = model(**values)
|
||||
context.session.add(db_obj)
|
||||
return db_obj.__dict__
|
||||
|
||||
|
||||
def update_object(context, model, id, values):
|
||||
with context.session.begin(subtransactions=True):
|
||||
db_obj = get_object(context, model, id)
|
||||
db_obj.update(values)
|
||||
db_obj.save(session=context.session)
|
||||
return db_obj.__dict__
|
||||
|
||||
|
||||
def delete_object(context, model, id):
|
||||
with context.session.begin(subtransactions=True):
|
||||
db_obj = get_object(context, model, id)
|
||||
db_obj.delete()
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# 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
|
||||
import six
|
||||
|
||||
from neutron.db import api as db_api
|
||||
|
||||
|
||||
# TODO(QoS): revisit dict compatibility and how we can isolate dict behavior
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class NeutronObject(obj_base.VersionedObject,
|
||||
obj_base.VersionedObjectDictCompat):
|
||||
|
||||
# should be overridden for all persistent objects
|
||||
db_model = None
|
||||
|
||||
def from_db_object(self, *objs):
|
||||
for field in self.fields:
|
||||
for db_obj in objs:
|
||||
if field in db_obj:
|
||||
setattr(self, field, db_obj[field])
|
||||
break
|
||||
self.obj_reset_changes()
|
||||
|
||||
@classmethod
|
||||
def get_by_id(cls, context, id):
|
||||
db_obj = db_api.get_object(context, cls.db_model, id)
|
||||
return cls(context, **db_obj)
|
||||
|
||||
@classmethod
|
||||
def get_objects(cls, context):
|
||||
db_objs = db_api.get_objects(context, cls.db_model)
|
||||
objs = [cls(context, **db_obj) for db_obj in db_objs]
|
||||
return objs
|
||||
|
||||
def create(self):
|
||||
fields = self.obj_get_changes()
|
||||
db_obj = db_api.create_object(self._context, self.db_model, fields)
|
||||
self.from_db_object(db_obj)
|
||||
|
||||
def update(self):
|
||||
updates = self.obj_get_changes()
|
||||
db_obj = db_api.update_object(self._context, self.db_model,
|
||||
self.id, updates)
|
||||
self.from_db_object(self, db_obj)
|
||||
|
||||
def delete(self):
|
||||
db_api.delete_object(self._context, self.db_model, self.id)
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2015 Red Hat, 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.
|
||||
|
||||
from oslo_versionedobjects import base as obj_base
|
||||
from oslo_versionedobjects import fields as obj_fields
|
||||
|
||||
from neutron.db.qos import models as qos_db_model
|
||||
from neutron.objects import base
|
||||
|
||||
|
||||
# TODO(QoS): add rule lists to object fields
|
||||
# TODO(QoS): implement something for binding networks and ports with policies
|
||||
|
||||
|
||||
@obj_base.VersionedObjectRegistry.register
|
||||
class QosPolicy(base.NeutronObject):
|
||||
|
||||
db_model = qos_db_model.QosPolicy
|
||||
|
||||
fields = {
|
||||
'id': obj_fields.UUIDField(),
|
||||
'tenant_id': obj_fields.UUIDField(),
|
||||
'name': obj_fields.StringField(),
|
||||
'description': obj_fields.StringField(),
|
||||
'shared': obj_fields.BooleanField()
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
# 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.objects import base
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class QosRule(base.NeutronObject):
|
||||
|
||||
base_db_model = qos_db_model.QosRule
|
||||
|
||||
fields = {
|
||||
'id': obj_fields.UUIDField(),
|
||||
'tenant_id': obj_fields.UUIDField(),
|
||||
'type': obj_fields.StringField(),
|
||||
'qos_policy_id': obj_fields.UUIDField()
|
||||
}
|
||||
|
||||
_core_fields = list(fields.keys())
|
||||
|
||||
@classmethod
|
||||
def _is_core_field(cls, field):
|
||||
return field in cls._core_fields
|
||||
|
||||
@staticmethod
|
||||
def _filter_fields(fields, func):
|
||||
return {
|
||||
key: val for key, val in fields.items()
|
||||
if func(key)
|
||||
}
|
||||
|
||||
# TODO(QoS): reimplement get_by_id to merge both core and addn fields
|
||||
|
||||
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, lambda key: not self._is_core_field(key))
|
||||
|
||||
# TODO(QoS): create and update are not transactional safe
|
||||
def create(self):
|
||||
|
||||
# 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()
|
||||
addn_fields['qos_rule_id'] = base_db_obj.id
|
||||
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(self._context, self, base_db_obj, addn_db_obj)
|
||||
|
||||
def update(self):
|
||||
updated_db_objs = []
|
||||
|
||||
# update base qos_rule, if needed
|
||||
core_fields = self._get_changed_core_fields()
|
||||
if core_fields:
|
||||
base_db_obj = db_api.create_object(
|
||||
self._context, self.base_db_model, 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.base_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(self._context, self, *updated_db_objs)
|
||||
|
||||
# delete is the same, additional rule object cleanup is done thru cascading
|
||||
|
||||
|
||||
@obj_base.VersionedObjectRegistry.register
|
||||
class QosBandwidthLimitRule(QosRule):
|
||||
|
||||
db_model = qos_db_model.QosBandwidthLimitRule
|
||||
|
||||
fields = {
|
||||
'max_kbps': obj_fields.IntegerField(),
|
||||
'max_burst_kbps': obj_fields.IntegerField()
|
||||
}
|
|
@ -35,6 +35,7 @@ oslo.rootwrap>=2.0.0 # Apache-2.0
|
|||
oslo.serialization>=1.4.0 # Apache-2.0
|
||||
oslo.service>=0.1.0 # Apache-2.0
|
||||
oslo.utils>=1.6.0 # Apache-2.0
|
||||
oslo.versionedobjects>=0.3.0,!=0.5.0
|
||||
|
||||
python-novaclient>=2.22.0
|
||||
|
||||
|
|
Loading…
Reference in New Issue