Merge "Add QoS policy port binding OVO"

This commit is contained in:
Jenkins 2017-07-06 17:59:09 +00:00 committed by Gerrit Code Review
commit 94d32069cd
9 changed files with 141 additions and 53 deletions

View File

@ -40,6 +40,11 @@ class PortQosBindingNotFound(e.NotFound):
"could not be found.")
class PortQosBindingError(e.NeutronException):
message = _("QoS binding for port %(port_id)s and policy %(policy_id)s "
"could not be created: %(db_error)s.")
class NetworkQosBindingNotFound(e.NotFound):
message = _("QoS binding for network %(net_id)s and policy %(policy_id)s "
"could not be found.")

View File

@ -46,33 +46,3 @@ def get_network_ids_by_network_policy_binding(context, policy_id):
query = (db_utils.model_query(context, models.QosNetworkPolicyBinding)
.filter_by(policy_id=policy_id).all())
return [entry.network_id for entry in query]
def create_policy_port_binding(context, policy_id, port_id):
try:
with context.session.begin(subtransactions=True):
db_obj = models.QosPortPolicyBinding(policy_id=policy_id,
port_id=port_id)
context.session.add(db_obj)
except oslo_db_exception.DBReferenceError:
raise n_exc.PortQosBindingNotFound(port_id=port_id,
policy_id=policy_id)
def delete_policy_port_binding(context, policy_id, port_id):
try:
with context.session.begin(subtransactions=True):
db_object = (db_utils.model_query(context,
models.QosPortPolicyBinding)
.filter_by(policy_id=policy_id,
port_id=port_id).one())
context.session.delete(db_object)
except orm_exc.NoResultFound:
raise n_exc.PortQosBindingNotFound(port_id=port_id,
policy_id=policy_id)
def get_port_ids_by_port_policy_binding(context, policy_id):
query = (db_utils.model_query(context, models.QosPortPolicyBinding)
.filter_by(policy_id=policy_id).all())
return [entry.port_id for entry in query]

View File

@ -23,10 +23,10 @@ from neutron.db import api as db_api
from neutron.db.models import dns as dns_models
from neutron.db.models import securitygroup as sg_models
from neutron.db import models_v2
from neutron.db.qos import models as qos_models
from neutron.objects import base
from neutron.objects import common_types
from neutron.objects.db import api as obj_db_api
from neutron.objects.qos import binding
from neutron.plugins.ml2 import models as ml2_models
@ -311,16 +311,13 @@ class Port(base.NeutronDbObject):
self._attach_qos_policy(fields['qos_policy_id'])
def _attach_qos_policy(self, qos_policy_id):
# TODO(ihrachys): introduce an object for the binding to isolate
# database access in a single place, currently scattered between port
# and policy objects
obj_db_api.delete_objects(
self.obj_context, qos_models.QosPortPolicyBinding, port_id=self.id)
binding.QosPolicyPortBinding.delete_objects(
self.obj_context, port_id=self.id)
if qos_policy_id:
obj_db_api.create_object(
self.obj_context, qos_models.QosPortPolicyBinding,
{'port_id': self.id, 'policy_id': qos_policy_id}
)
port_binding_obj = binding.QosPolicyPortBinding(
self.obj_context, policy_id=qos_policy_id, port_id=self.id)
port_binding_obj.create()
self.qos_policy_id = qos_policy_id
self.obj_reset_changes(['qos_policy_id'])

View File

@ -0,0 +1,36 @@
# Copyright 2017 Intel Corporation.
# 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 neutron.db.qos import models as qos_db_model
from neutron.objects import base
from neutron.objects import common_types
@obj_base.VersionedObjectRegistry.register
class QosPolicyPortBinding(base.NeutronDbObject):
# Version 1.0: Initial version
VERSION = '1.0'
db_model = qos_db_model.QosPortPolicyBinding
fields = {
'policy_id': common_types.UUIDField(),
'port_id': common_types.UUIDField()
}
primary_keys = ['port_id']
fields_no_update = ['policy_id', 'port_id']

View File

@ -15,6 +15,7 @@
import itertools
from oslo_db import exception as db_exc
from oslo_utils import versionutils
from oslo_versionedobjects import base as obj_base
from oslo_versionedobjects import exception
@ -30,6 +31,7 @@ from neutron.db.rbac_db_models import QosPolicyRBAC
from neutron.objects import base as base_db
from neutron.objects import common_types
from neutron.objects.db import api as obj_db_api
from neutron.objects.qos import binding
from neutron.objects.qos import rule as rule_obj_impl
from neutron.objects import rbac_db
@ -67,8 +69,11 @@ class QosPolicy(rbac_db.NeutronRbacObject):
extra_filter_names = {'is_default'}
binding_models = {'network': network_binding_model,
'port': port_binding_model}
binding_models = {'network': network_binding_model}
#NOTE(ralonsoh): once 'network_binding_model' is converted to OVO, both
# bindings will be in the same variable.
binding_models2 = {'port': binding.QosPolicyPortBinding}
def obj_load_attr(self, attrname):
if attrname == 'rules':
@ -172,6 +177,8 @@ class QosPolicy(rbac_db.NeutronRbacObject):
def delete(self):
with db_api.autonested_transaction(self.obj_context.session):
#NOTE(ralonsoh): once 'network_binding_model' is converted to OVO,
# this loop will be deleted.
for object_type, model in self.binding_models.items():
binding_db_obj = obj_db_api.get_object(self.obj_context, model,
policy_id=self.id)
@ -181,6 +188,17 @@ class QosPolicy(rbac_db.NeutronRbacObject):
object_type=object_type,
object_id=binding_db_obj['%s_id' % object_type])
for object_type, obj_class in self.binding_models2.items():
pager = base_db.Pager(limit=1)
binding_obj = obj_class.get_objects(self.obj_context,
policy_id=self.id,
_pager=pager)
if binding_obj:
raise exceptions.QosPolicyInUse(
policy_id=self.id,
object_type=object_type,
object_id=binding_obj[0]['%s_id' % object_type])
super(QosPolicy, self).delete()
def attach_network(self, network_id):
@ -189,9 +207,14 @@ class QosPolicy(rbac_db.NeutronRbacObject):
network_id=network_id)
def attach_port(self, port_id):
qos_db_api.create_policy_port_binding(self.obj_context,
policy_id=self.id,
port_id=port_id)
port_binding_obj = binding.QosPolicyPortBinding(
self.obj_context, policy_id=self.id, port_id=port_id)
try:
port_binding_obj.create()
except db_exc.DBReferenceError as e:
raise exceptions.PortQosBindingError(policy_id=self.id,
port_id=port_id,
db_error=e)
def detach_network(self, network_id):
qos_db_api.delete_policy_network_binding(self.obj_context,
@ -199,9 +222,11 @@ class QosPolicy(rbac_db.NeutronRbacObject):
network_id=network_id)
def detach_port(self, port_id):
qos_db_api.delete_policy_port_binding(self.obj_context,
policy_id=self.id,
port_id=port_id)
deleted = binding.QosPolicyPortBinding.delete_objects(self.obj_context,
port_id=port_id)
if not deleted:
raise exceptions.PortQosBindingNotFound(port_id=port_id,
policy_id=self.id)
def set_default(self):
if not self.get_default():
@ -230,8 +255,11 @@ class QosPolicy(rbac_db.NeutronRbacObject):
self.obj_context, self.id)
def get_bound_ports(self):
return qos_db_api.get_port_ids_by_port_policy_binding(
self.obj_context, self.id)
return [
pb.port_id
for pb in binding.QosPolicyPortBinding.get_objects(
self.obj_context, policy_id=self.id)
]
@classmethod
def _get_bound_tenant_ids(cls, session, binding_db, bound_db,

View File

@ -0,0 +1,40 @@
# 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.qos import binding
from neutron.objects.qos import policy
from neutron.tests.unit.objects import test_base
from neutron.tests.unit import testlib_api
class QosPolicyPortBindingObjectTestCase(test_base.BaseObjectIfaceTestCase):
_test_class = binding.QosPolicyPortBinding
class QosPolicyPortBindingDbObjectTestCase(test_base.BaseDbObjectTestCase,
testlib_api.SqlTestCase):
_test_class = binding.QosPolicyPortBinding
def _create_test_qos_policy(self, **qos_policy_attrs):
qos_policy = policy.QosPolicy(self.context, **qos_policy_attrs)
qos_policy.create()
return qos_policy
def setUp(self):
super(QosPolicyPortBindingDbObjectTestCase, self).setUp()
network_id = self._create_test_network_id()
for db_obj in self.db_objs:
self._create_test_qos_policy(id=db_obj['policy_id'])
self._create_test_port(network_id=network_id,
id=db_obj['port_id'])

View File

@ -203,8 +203,8 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
def test_attach_port_nonexistent_port(self):
obj = self._create_test_policy()
self.assertRaises(n_exc.PortQosBindingNotFound,
obj.attach_port, 'non-existent-port')
self.assertRaises(n_exc.PortQosBindingError,
obj.attach_port, uuidutils.generate_uuid())
def test_attach_network_nonexistent_policy(self):
@ -215,7 +215,7 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
def test_attach_port_nonexistent_policy(self):
policy_obj = self._make_object(self.obj_fields[0])
self.assertRaises(n_exc.PortQosBindingNotFound,
self.assertRaises(n_exc.PortQosBindingError,
policy_obj.attach_port, self._port['id'])
def test_attach_port_get_port_policy(self):

View File

@ -69,6 +69,7 @@ object_data = {
'QosRuleType': '1.2-e6fd08fcca152c339cbd5e9b94b1b8e7',
'QosPolicy': '1.6-4adb0cde3102c10d8970ec9487fd7fe7',
'QosPolicyDefault': '1.0-59e5060eedb1f06dd0935a244d27d11c',
'QosPolicyPortBinding': '1.0-66cb364ac99aa64523ade07f9f868ea6',
'Quota': '1.0-6bb6a0f1bd5d66a2134ffa1a61873097',
'QuotaUsage': '1.0-6fbf820368681aac7c5d664662605cf9',
'Reservation': '1.0-49929fef8e82051660342eed51b48f2a',

View File

@ -17,6 +17,7 @@ import testscenarios
from neutron.objects import base as obj_base
from neutron.objects import network
from neutron.objects import ports
from neutron.objects.qos import binding
from neutron.objects.qos import policy
from neutron.tests import tools
from neutron.tests.unit.objects import test_base as obj_test_base
@ -307,6 +308,10 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
obj = ports.Port.get_object(self.context, id=obj.id)
self.assertEqual(policy_obj.id, obj.qos_policy_id)
qos_binding_obj = binding.QosPolicyPortBinding.get_object(
self.context, port_id=obj.id)
self.assertEqual(qos_binding_obj.policy_id, obj.qos_policy_id)
old_policy_id = policy_obj.id
policy_obj2 = policy.QosPolicy(self.context)
policy_obj2.create()
@ -314,6 +319,12 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
obj = ports.Port.get_object(self.context, id=obj.id)
self.assertEqual(policy_obj2.id, obj.qos_policy_id)
qos_binding_obj2 = binding.QosPolicyPortBinding.get_object(
self.context, port_id=obj.id)
self.assertEqual(qos_binding_obj2.policy_id, obj.qos_policy_id)
qos_binding_obj = binding.QosPolicyPortBinding.get_objects(
self.context, policy_id=old_policy_id)
self.assertEqual(0, len(qos_binding_obj))
def test_get_objects_queries_constant(self):
self.skipTest(