Add QoS policy network binding OVO

Added QoS policy network binding OVO. Direct access to
'qos_network_policy_bindings' DB table is removed.

Partially-Implements: blueprint adopt-oslo-versioned-objects-for-db
Change-Id: I2a2037dae5a071bd220fa04b0988bc8e7172eb59
This commit is contained in:
Rodolfo Alonso Hernandez 2017-05-26 14:46:15 +01:00
parent c2e12079f6
commit 188aee25c6
10 changed files with 93 additions and 98 deletions

View File

@ -50,6 +50,11 @@ class NetworkQosBindingNotFound(e.NotFound):
"could not be found.")
class NetworkQosBindingError(e.NeutronException):
message = _("QoS binding for network %(net_id)s and policy %(policy_id)s "
"could not be created: %(db_error)s.")
class PlacementEndpointNotFound(e.NotFound):
message = _("Placement API endpoint not found")

View File

@ -1,48 +0,0 @@
# 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_db import exception as oslo_db_exception
from sqlalchemy.orm import exc as orm_exc
from neutron.common import exceptions as n_exc
from neutron.db import _utils as db_utils
from neutron.db.qos import models
def create_policy_network_binding(context, policy_id, network_id):
try:
with context.session.begin(subtransactions=True):
db_obj = models.QosNetworkPolicyBinding(policy_id=policy_id,
network_id=network_id)
context.session.add(db_obj)
except oslo_db_exception.DBReferenceError:
raise n_exc.NetworkQosBindingNotFound(net_id=network_id,
policy_id=policy_id)
def delete_policy_network_binding(context, policy_id, network_id):
try:
with context.session.begin(subtransactions=True):
db_object = (db_utils.model_query(context,
models.QosNetworkPolicyBinding)
.filter_by(policy_id=policy_id,
network_id=network_id).one())
context.session.delete(db_object)
except orm_exc.NoResultFound:
raise n_exc.NetworkQosBindingNotFound(net_id=network_id,
policy_id=policy_id)
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]

View File

@ -21,13 +21,12 @@ from neutron.db.models import external_net as ext_net_model
from neutron.db.models import segment as segment_model
from neutron.db import models_v2
from neutron.db.port_security import models as ps_models
from neutron.db.qos import models as qos_models
from neutron.db import rbac_db_models
from neutron.extensions import availability_zone as az_ext
from neutron.objects import base
from neutron.objects import common_types
from neutron.objects.db import api as obj_db_api
from neutron.objects.extensions import port_security as base_ps
from neutron.objects.qos import binding
from neutron.objects import rbac_db
@ -221,18 +220,13 @@ class Network(rbac_db.NeutronRbacObject):
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.QosNetworkPolicyBinding,
network_id=self.id,
)
binding.QosPolicyNetworkBinding.delete_objects(
self.obj_context, network_id=self.id)
if qos_policy_id:
obj_db_api.create_object(
self.obj_context, qos_models.QosNetworkPolicyBinding,
{'network_id': self.id, 'policy_id': qos_policy_id}
)
net_binding_obj = binding.QosPolicyNetworkBinding(
self.obj_context, policy_id=qos_policy_id, network_id=self.id)
net_binding_obj.create()
self.qos_policy_id = qos_policy_id
self.obj_reset_changes(['qos_policy_id'])

View File

@ -34,3 +34,19 @@ class QosPolicyPortBinding(base.NeutronDbObject):
primary_keys = ['port_id']
fields_no_update = ['policy_id', 'port_id']
@obj_base.VersionedObjectRegistry.register
class QosPolicyNetworkBinding(base.NeutronDbObject):
# Version 1.0: Initial version
VERSION = '1.0'
db_model = qos_db_model.QosNetworkPolicyBinding
fields = {
'policy_id': common_types.UUIDField(),
'network_id': common_types.UUIDField()
}
primary_keys = ['network_id']
fields_no_update = ['policy_id', 'network_id']

View File

@ -25,7 +25,6 @@ from neutron.common import constants as n_const
from neutron.common import exceptions
from neutron.db import api as db_api
from neutron.db import models_v2
from neutron.db.qos import api as qos_db_api
from neutron.db.qos import models as qos_db_model
from neutron.db.rbac_db_models import QosPolicyRBAC
from neutron.objects import base as base_db
@ -69,11 +68,8 @@ class QosPolicy(rbac_db.NeutronRbacObject):
extra_filter_names = {'is_default'}
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}
binding_models = {'port': binding.QosPolicyPortBinding,
'network': binding.QosPolicyNetworkBinding}
def obj_load_attr(self, attrname):
if attrname == 'rules':
@ -177,18 +173,7 @@ 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)
if binding_db_obj:
raise exceptions.QosPolicyInUse(
policy_id=self.id,
object_type=object_type,
object_id=binding_db_obj['%s_id' % object_type])
for object_type, obj_class in self.binding_models2.items():
for object_type, obj_class in self.binding_models.items():
pager = base_db.Pager(limit=1)
binding_obj = obj_class.get_objects(self.obj_context,
policy_id=self.id,
@ -202,9 +187,16 @@ class QosPolicy(rbac_db.NeutronRbacObject):
super(QosPolicy, self).delete()
def attach_network(self, network_id):
qos_db_api.create_policy_network_binding(self.obj_context,
policy_id=self.id,
network_id=network_id)
network_binding = {'policy_id': self.id,
'network_id': network_id}
network_binding_obj = binding.QosPolicyNetworkBinding(
self.obj_context, **network_binding)
try:
network_binding_obj.create()
except db_exc.DBReferenceError as e:
raise exceptions.NetworkQosBindingError(policy_id=self.id,
net_id=network_id,
db_error=e)
def attach_port(self, port_id):
port_binding_obj = binding.QosPolicyPortBinding(
@ -217,9 +209,11 @@ class QosPolicy(rbac_db.NeutronRbacObject):
db_error=e)
def detach_network(self, network_id):
qos_db_api.delete_policy_network_binding(self.obj_context,
policy_id=self.id,
network_id=network_id)
deleted = binding.QosPolicyNetworkBinding.delete_objects(
self.obj_context, network_id=network_id)
if not deleted:
raise exceptions.NetworkQosBindingNotFound(net_id=network_id,
policy_id=self.id)
def detach_port(self, port_id):
deleted = binding.QosPolicyPortBinding.delete_objects(self.obj_context,
@ -251,8 +245,11 @@ class QosPolicy(rbac_db.NeutronRbacObject):
return qos_default_policy.qos_policy_id
def get_bound_networks(self):
return qos_db_api.get_network_ids_by_network_policy_binding(
self.obj_context, self.id)
return [
nb.network_id
for nb in binding.QosPolicyNetworkBinding.get_objects(
self.obj_context, policy_id=self.id)
]
def get_bound_ports(self):
return [

View File

@ -11,7 +11,6 @@
# 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
@ -26,11 +25,6 @@ class QosPolicyPortBindingDbObjectTestCase(test_base.BaseDbObjectTestCase,
_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()
@ -38,3 +32,20 @@ class QosPolicyPortBindingDbObjectTestCase(test_base.BaseDbObjectTestCase,
self._create_test_qos_policy(id=db_obj['policy_id'])
self._create_test_port(network_id=network_id,
id=db_obj['port_id'])
class QosPolicyNetworkBindingObjectTestCase(test_base.BaseObjectIfaceTestCase):
_test_class = binding.QosPolicyNetworkBinding
class QosPolicyNetworkBindingDbObjectTestCase(test_base.BaseDbObjectTestCase,
testlib_api.SqlTestCase):
_test_class = binding.QosPolicyNetworkBinding
def setUp(self):
super(QosPolicyNetworkBindingDbObjectTestCase, self).setUp()
for db_obj in self.db_objs:
self._create_test_qos_policy(id=db_obj['policy_id'])
self._create_test_network(network_id=db_obj['network_id'])

View File

@ -171,8 +171,8 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
def test_attach_network_nonexistent_network(self):
obj = self._create_test_policy()
self.assertRaises(n_exc.NetworkQosBindingNotFound,
obj.attach_network, 'non-existent-network')
self.assertRaises(n_exc.NetworkQosBindingError,
obj.attach_network, uuidutils.generate_uuid())
def test_attach_network_get_policy_network(self):
@ -209,7 +209,7 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
def test_attach_network_nonexistent_policy(self):
policy_obj = self._make_object(self.obj_fields[0])
self.assertRaises(n_exc.NetworkQosBindingNotFound,
self.assertRaises(n_exc.NetworkQosBindingError,
policy_obj.attach_network, self._network_id)
def test_attach_port_nonexistent_policy(self):

View File

@ -43,6 +43,7 @@ from neutron.objects import flavor
from neutron.objects.logapi import event_types
from neutron.objects import network as net_obj
from neutron.objects import ports
from neutron.objects.qos import policy as qos_policy
from neutron.objects import rbac_db
from neutron.objects import securitygroup
from neutron.objects import subnet
@ -1336,8 +1337,10 @@ class BaseDbObjectTestCase(_BaseObjectTestCase,
objclass.db_model(**objclass_fields)
]
def _create_test_network(self, name='test-network1'):
_network = net_obj.Network(self.context, name=name)
def _create_test_network(self, name='test-network1', network_id=None):
network_id = (uuidutils.generate_uuid() if network_id is None
else network_id)
_network = net_obj.Network(self.context, name=name, id=network_id)
_network.create()
return _network
@ -1466,6 +1469,11 @@ class BaseDbObjectTestCase(_BaseObjectTestCase,
service_profile_obj.create()
return service_profile_obj.id
def _create_test_qos_policy(self, **qos_policy_attrs):
_qos_policy = qos_policy.QosPolicy(self.context, **qos_policy_attrs)
_qos_policy.create()
return _qos_policy
def test_get_standard_attr_id(self):
if not self._test_class.has_standard_attributes():

View File

@ -14,6 +14,7 @@ import mock
from neutron.objects import base as obj_base
from neutron.objects import network
from neutron.objects.qos import binding
from neutron.objects.qos import policy
from neutron.tests.unit.objects import test_base as obj_test_base
from neutron.tests.unit import testlib_api
@ -130,6 +131,10 @@ class NetworkDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
obj = network.Network.get_object(self.context, id=obj.id)
self.assertEqual(policy_obj.id, obj.qos_policy_id)
qos_binding_obj = binding.QosPolicyNetworkBinding.get_object(
self.context, network_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()
@ -137,6 +142,12 @@ class NetworkDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
obj = network.Network.get_object(self.context, id=obj.id)
self.assertEqual(policy_obj2.id, obj.qos_policy_id)
qos_binding_obj2 = binding.QosPolicyNetworkBinding.get_object(
self.context, network_id=obj.id)
self.assertEqual(qos_binding_obj2.policy_id, obj.qos_policy_id)
qos_binding_obj = binding.QosPolicyNetworkBinding.get_objects(
self.context, policy_id=old_policy_id)
self.assertEqual(0, len(qos_binding_obj))
def test_dns_domain(self):
obj = self._make_object(self.obj_fields[0])

View File

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