]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
First QoS versioned objects, ever
authorIhar Hrachyshka <ihrachys@redhat.com>
Tue, 30 Jun 2015 10:32:27 +0000 (13:32 +0300)
committerIhar Hrachyshka <ihrachys@redhat.com>
Thu, 2 Jul 2015 06:21:45 +0000 (09:21 +0300)
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

neutron/db/api.py
neutron/objects/__init__.py [new file with mode: 0644]
neutron/objects/base.py [new file with mode: 0644]
neutron/objects/qos/__init__.py [new file with mode: 0644]
neutron/objects/qos/policy.py [new file with mode: 0644]
neutron/objects/qos/rule.py [new file with mode: 0644]
requirements.txt

index 0b68bd3310ad508d9e4983e5ddc3fadae0d5acc4..b74f56e7b6407dde8a3d37af90018de025d4c073 100644 (file)
@@ -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()
diff --git a/neutron/objects/__init__.py b/neutron/objects/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/neutron/objects/base.py b/neutron/objects/base.py
new file mode 100644 (file)
index 0000000..b719869
--- /dev/null
@@ -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)
diff --git a/neutron/objects/qos/__init__.py b/neutron/objects/qos/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/neutron/objects/qos/policy.py b/neutron/objects/qos/policy.py
new file mode 100644 (file)
index 0000000..2352673
--- /dev/null
@@ -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()
+    }
diff --git a/neutron/objects/qos/rule.py b/neutron/objects/qos/rule.py
new file mode 100644 (file)
index 0000000..297fdda
--- /dev/null
@@ -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()
+    }
index 8d5041c38abac20df7bccff0766cae5d9cb6cfa8..2e7a8452ffec694e9d0be96fc391b01448dc3158 100644 (file)
@@ -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