diff --git a/neutron/db/metering/metering_db.py b/neutron/db/metering/metering_db.py index 57a514a7640..3d475ff2a00 100644 --- a/neutron/db/metering/metering_db.py +++ b/neutron/db/metering/metering_db.py @@ -15,7 +15,6 @@ import netaddr from oslo_db import exception as db_exc from oslo_utils import uuidutils -from sqlalchemy import orm from neutron.api.rpc.agentnotifiers import metering_rpc_agent_api from neutron.common import constants @@ -27,6 +26,8 @@ from neutron.db import l3_dvr_db from neutron.db.models import l3 as l3_models from neutron.db.models import metering as metering_models from neutron.extensions import metering +from neutron.objects import base as base_obj +from neutron.objects import metering as metering_objs class MeteringDbMixin(metering.MeteringPluginBase, @@ -47,50 +48,39 @@ class MeteringDbMixin(metering.MeteringPluginBase, def create_metering_label(self, context, metering_label): m = metering_label['metering_label'] - with db_api.context_manager.writer.using(context): - metering_db = metering_models.MeteringLabel( - id=uuidutils.generate_uuid(), - description=m['description'], - tenant_id=m['tenant_id'], - name=m['name'], - shared=m['shared']) - context.session.add(metering_db) + metering_obj = metering_objs.MeteringLabel( + context, id=uuidutils.generate_uuid(), + description=m['description'], project_id=m['tenant_id'], + name=m['name'], shared=m['shared']) + metering_obj.create() + return self._make_metering_label_dict(metering_obj) - return self._make_metering_label_dict(metering_db) + def _get_metering_label(self, context, label_id): + metering_label = metering_objs.MeteringLabel.get_object(context, + id=label_id) + if not metering_label: + raise metering.MeteringLabelNotFound(label_id=label_id) + return metering_label def delete_metering_label(self, context, label_id): - with db_api.context_manager.writer.using(context): - try: - label = model_query.get_by_id(context, - metering_models.MeteringLabel, - label_id) - except orm.exc.NoResultFound: - raise metering.MeteringLabelNotFound(label_id=label_id) - - context.session.delete(label) - - def get_metering_label(self, context, label_id, fields=None): - try: - metering_label = model_query.get_by_id( - context, metering_models.MeteringLabel, label_id) - except orm.exc.NoResultFound: + deleted = metering_objs.MeteringLabel.delete_objects( + context, id=label_id) + if not deleted: raise metering.MeteringLabelNotFound(label_id=label_id) - return self._make_metering_label_dict(metering_label, fields) + def get_metering_label(self, context, label_id, fields=None): + return self._make_metering_label_dict( + self._get_metering_label(context, label_id), fields) def get_metering_labels(self, context, filters=None, fields=None, sorts=None, limit=None, marker=None, page_reverse=False): - marker_obj = self._get_marker_obj(context, 'metering_labels', limit, - marker) - return model_query.get_collection(context, - metering_models.MeteringLabel, - self._make_metering_label_dict, - filters=filters, fields=fields, - sorts=sorts, - limit=limit, - marker_obj=marker_obj, - page_reverse=page_reverse) + filters = filters or {} + pager = base_obj.Pager(sorts, limit, page_reverse, marker) + metering_labels = metering_objs.MeteringLabel.get_objects(context, + _pager=pager, + **filters) + return [self._make_metering_label_dict(ml) for ml in metering_labels] @staticmethod def _make_metering_label_rule_dict(metering_label_rule, fields=None): @@ -104,26 +94,23 @@ class MeteringDbMixin(metering.MeteringPluginBase, def get_metering_label_rules(self, context, filters=None, fields=None, sorts=None, limit=None, marker=None, page_reverse=False): - marker_obj = self._get_marker_obj(context, 'metering_label_rules', - limit, marker) + filters = filters or {} + pager = base_obj.Pager(sorts, limit, page_reverse, marker) + metering_label_rules = metering_objs.MeteringLabelRule.get_objects( + context, _pager=pager, **filters) + return [self._make_metering_label_rule_dict(mlr) + for mlr in metering_label_rules] - return model_query.get_collection(context, - metering_models.MeteringLabelRule, - self._make_metering_label_rule_dict, - filters=filters, fields=fields, - sorts=sorts, - limit=limit, - marker_obj=marker_obj, - page_reverse=page_reverse) + def _get_metering_label_rule(self, context, rule_id): + metering_label_rule = metering_objs.MeteringLabelRule.get_object( + context, id=rule_id) + if not metering_label_rule: + raise metering.MeteringLabelRuleNotFound(rule_id=rule_id) + return metering_label_rule def get_metering_label_rule(self, context, rule_id, fields=None): - try: - metering_label_rule = model_query.get_by_id( - context, metering_models.MeteringLabelRule, rule_id) - except orm.exc.NoResultFound: - raise metering.MeteringLabelRuleNotFound(rule_id=rule_id) - - return self._make_metering_label_rule_dict(metering_label_rule, fields) + return self._make_metering_label_rule_dict( + self._get_metering_label_rule(context, rule_id), fields) def _validate_cidr(self, context, label_id, remote_ip_prefix, direction, excluded): @@ -153,28 +140,21 @@ class MeteringDbMixin(metering.MeteringPluginBase, self._validate_cidr(context, label_id, ip_prefix, direction, excluded) - metering_db = metering_models.MeteringLabelRule( - id=uuidutils.generate_uuid(), - metering_label_id=label_id, - direction=direction, + rule = metering_objs.MeteringLabelRule( + context, id=uuidutils.generate_uuid(), + metering_label_id=label_id, direction=direction, excluded=m['excluded'], - remote_ip_prefix=ip_prefix) - context.session.add(metering_db) - + remote_ip_prefix=netaddr.IPNetwork(ip_prefix)) + rule.create() except db_exc.DBReferenceError: raise metering.MeteringLabelNotFound(label_id=label_id) - return self._make_metering_label_rule_dict(metering_db) + return self._make_metering_label_rule_dict(rule) def delete_metering_label_rule(self, context, rule_id): with db_api.context_manager.writer.using(context): - try: - rule = model_query.get_by_id(context, - metering_models.MeteringLabelRule, - rule_id) - except orm.exc.NoResultFound: - raise metering.MeteringLabelRuleNotFound(rule_id=rule_id) - context.session.delete(rule) + rule = self._get_metering_label_rule(context, rule_id) + rule.delete() return self._make_metering_label_rule_dict(rule) @@ -233,6 +213,7 @@ class MeteringDbMixin(metering.MeteringPluginBase, metering_models.MeteringLabel).get( rule['metering_label_id']) + # TODO(electrocucaracha) This depends on the Router OVO implementation if label.shared: routers = model_query.get_collection_query( context, l3_models.Router) diff --git a/neutron/objects/metering.py b/neutron/objects/metering.py new file mode 100644 index 00000000000..76b89cac965 --- /dev/null +++ b/neutron/objects/metering.py @@ -0,0 +1,74 @@ +# Copyright (c) 2016 Intel Corporation. +# +# 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.common import utils +from neutron.db.models import metering as metering_models +from neutron.objects import base +from neutron.objects import common_types + + +@obj_base.VersionedObjectRegistry.register +class MeteringLabelRule(base.NeutronDbObject): + # Version 1.0: Initial version + VERSION = '1.0' + + db_model = metering_models.MeteringLabelRule + + foreign_keys = {'MeteringLabel': {'metering_label_id': 'id'}} + + fields = { + 'id': common_types.UUIDField(), + 'direction': common_types.FlowDirectionEnumField(nullable=True), + 'remote_ip_prefix': common_types.IPNetworkField(nullable=True), + 'metering_label_id': common_types.UUIDField(), + 'excluded': obj_fields.BooleanField(default=False), + } + + @classmethod + def modify_fields_from_db(cls, db_obj): + result = super(MeteringLabelRule, cls).modify_fields_from_db(db_obj) + if 'remote_ip_prefix' in result: + result['remote_ip_prefix'] = utils.AuthenticIPNetwork( + result['remote_ip_prefix']) + return result + + @classmethod + def modify_fields_to_db(cls, fields): + result = super(MeteringLabelRule, cls).modify_fields_to_db(fields) + if 'remote_ip_prefix' in result: + result['remote_ip_prefix'] = cls.filter_to_str( + result['remote_ip_prefix']) + return result + + +@obj_base.VersionedObjectRegistry.register +class MeteringLabel(base.NeutronDbObject): + # Version 1.0: Initial version + VERSION = '1.0' + + db_model = metering_models.MeteringLabel + synthetic_fields = ['rules'] + + fields = { + 'id': common_types.UUIDField(), + 'project_id': obj_fields.StringField(nullable=True), + 'name': obj_fields.StringField(), + 'description': obj_fields.StringField(), + 'rules': obj_fields.ListOfObjectsField('MeteringLabelRule', + nullable=True), + 'shared': obj_fields.BooleanField(default=False), + } diff --git a/neutron/tests/unit/objects/test_metering.py b/neutron/tests/unit/objects/test_metering.py new file mode 100644 index 00000000000..74f81211712 --- /dev/null +++ b/neutron/tests/unit/objects/test_metering.py @@ -0,0 +1,50 @@ +# Copyright (c) 2016 Intel Corporation. +# +# 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 neutron.objects import metering +from neutron.tests.unit.objects import test_base as obj_test_base +from neutron.tests.unit import testlib_api + + +class MeteringLabelRuleObjectTestCase(obj_test_base.BaseObjectIfaceTestCase): + + _test_class = metering.MeteringLabelRule + + +class MeteringLabelRuleDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, + testlib_api.SqlTestCase): + + _test_class = metering.MeteringLabelRule + + def _create_test_metering_label_id(self, **attrs): + attrs = self.get_random_object_fields(metering.MeteringLabel) + metering_label = metering.MeteringLabel(self.context, **attrs) + metering_label.create() + return metering_label.id + + def setUp(self): + super(MeteringLabelRuleDbObjectTestCase, self).setUp() + self.update_obj_fields( + {'metering_label_id': self._create_test_metering_label_id}) + + +class MeteringLabelObjectTestCase(obj_test_base.BaseObjectIfaceTestCase): + + _test_class = metering.MeteringLabel + + +class MeteringLabelDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, + testlib_api.SqlTestCase): + + _test_class = metering.MeteringLabel diff --git a/neutron/tests/unit/objects/test_objects.py b/neutron/tests/unit/objects/test_objects.py index 1352265e4f2..8a596342d4b 100644 --- a/neutron/tests/unit/objects/test_objects.py +++ b/neutron/tests/unit/objects/test_objects.py @@ -48,6 +48,8 @@ object_data = { 'IpamAllocation': '1.0-ace65431abd0a7be84cc4a5f32d034a3', 'IpamAllocationPool': '1.0-c4fa1460ed1b176022ede7af7d1510d5', 'IpamSubnet': '1.0-713de401682a70f34891e13af645fa08', + 'MeteringLabel': '1.0-cc4b620a3425222447cbe459f62de533', + 'MeteringLabelRule': '1.0-b5c5717e7bab8d1af1623156012a5842', 'Network': '1.0-f2f6308f79731a767b92b26b0f4f3849', 'NetworkDNSDomain': '1.0-420db7910294608534c1e2e30d6d8319', 'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3', diff --git a/neutron/tests/unit/services/metering/test_metering_plugin.py b/neutron/tests/unit/services/metering/test_metering_plugin.py index 4dba6316eb4..53715296640 100644 --- a/neutron/tests/unit/services/metering/test_metering_plugin.py +++ b/neutron/tests/unit/services/metering/test_metering_plugin.py @@ -18,6 +18,7 @@ from neutron_lib.plugins import directory from oslo_utils import uuidutils from neutron.api.v2 import attributes as attr +from neutron.common import utils from neutron.db import api as db_api from neutron.db.metering import metering_rpc from neutron.db.models import agent as agent_model @@ -247,7 +248,8 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'tenant_id': self.tenant_id, '_metering_labels': [ {'rule': { - 'remote_ip_prefix': '10.0.0.0/24', + 'remote_ip_prefix': utils.AuthenticIPNetwork( + '10.0.0.0/24'), 'direction': 'ingress', 'metering_label_id': self.uuid, 'excluded': False, @@ -263,7 +265,8 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'tenant_id': self.tenant_id, '_metering_labels': [ {'rule': { - 'remote_ip_prefix': '10.0.0.0/24', + 'remote_ip_prefix': utils.AuthenticIPNetwork( + '10.0.0.0/24'), 'direction': 'ingress', 'metering_label_id': self.uuid, 'excluded': False,