Metering to OVO

This patch introduces and implements OVO for metering

Change-Id: I168e113de6651b3a91183ed148338a26bef663cb
Partially-Implements: blueprint adopt-oslo-versioned-objects-for-db
Co-Authored-By: Eli Qiao <liyong.qiao@intel.com>
This commit is contained in:
Victor Morales 2017-02-13 09:13:49 -06:00 committed by Ihar Hrachyshka
parent 7b7be92bfb
commit fdc3e8146c
5 changed files with 180 additions and 70 deletions

View File

@ -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)

View File

@ -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),
}

View File

@ -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

View File

@ -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',

View File

@ -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,