From 2b66c6a2ed77dcebcbe37ed6c6702c9190249b6e Mon Sep 17 00:00:00 2001 From: Manjeet Singh Bhatia Date: Thu, 28 Jul 2016 21:05:51 +0000 Subject: [PATCH] Relocate L3 DB Models As we have started oslo versioned objects implementations. There would be issue of cyclic import while implementation for objects which have db models definitions and mixins in same file. This patch will move routers models as discussed in [1]. For example DNS models and some queries are in same file [2]. for object implementation I have separate models definitions and mixins where queries were being done [3]. [1]. https://www.mail-archive.com/openstack-dev@lists.openstack.org/msg88910.html [2]. https://review.openstack.org/#/c/334695/15/neutron/db/dns_db.py [3]. https://review.openstack.org/#/c/334695/15/neutron/db/models/dns_models.py Change-Id: I9b9a44da5d28252be58cea1a920a64e18d8bbf32 Partial-Bug: #1597913 --- neutron/db/dns_db.py | 4 +- neutron/db/external_net_db.py | 13 +- neutron/db/extraroute_db.py | 3 +- neutron/db/l3_db.py | 173 +++++------------- neutron/db/l3_dvr_db.py | 19 +- neutron/db/l3_gwmode_db.py | 3 +- neutron/db/l3_hamode_db.py | 4 +- neutron/db/l3_hascheduler_db.py | 6 +- neutron/db/metering/metering_db.py | 10 +- neutron/db/migration/models/head.py | 1 - neutron/db/models/l3.py | 105 +++++++++++ neutron/scheduler/l3_agent_scheduler.py | 9 +- .../services/l3_router/l3_router_plugin.py | 6 +- .../tests/unit/db/test_db_base_plugin_v2.py | 20 +- neutron/tests/unit/db/test_l3_db.py | 7 +- neutron/tests/unit/extensions/test_flavors.py | 4 +- neutron/tests/unit/extensions/test_l3.py | 7 +- .../unit/extensions/test_l3_ext_gw_mode.py | 5 +- .../unit/plugins/ml2/drivers/l2pop/test_db.py | 4 +- neutron/tests/unit/plugins/ml2/test_db.py | 4 +- neutron/tests/unit/plugins/ml2/test_plugin.py | 4 +- 21 files changed, 224 insertions(+), 187 deletions(-) create mode 100644 neutron/db/models/l3.py diff --git a/neutron/db/dns_db.py b/neutron/db/dns_db.py index 09fe11bcabc..69d5f4d4f65 100644 --- a/neutron/db/dns_db.py +++ b/neutron/db/dns_db.py @@ -24,7 +24,7 @@ from sqlalchemy import orm from neutron._i18n import _, _LE from neutron.common import utils from neutron.db import db_base_plugin_v2 -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import dns from neutron.extensions import l3 @@ -70,7 +70,7 @@ class FloatingIPDNS(model_base.BASEV2): # Add a relationship to the FloatingIP model in order to instruct # SQLAlchemy to eagerly load this association - floatingip = orm.relationship(l3_db.FloatingIP, + floatingip = orm.relationship(l3_models.FloatingIP, backref=orm.backref("dns", lazy='joined', uselist=False, diff --git a/neutron/db/external_net_db.py b/neutron/db/external_net_db.py index 56725ccc6a5..399b883eab3 100644 --- a/neutron/db/external_net_db.py +++ b/neutron/db/external_net_db.py @@ -30,7 +30,7 @@ from neutron.callbacks import exceptions as c_exc from neutron.callbacks import registry from neutron.callbacks import resources from neutron.db import db_base_plugin_v2 -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.db import rbac_db_models as rbac_db from neutron.extensions import external_net @@ -231,12 +231,12 @@ class External_net_db_mixin(object): ports = context.session.query(models_v2.Port.id).filter_by( device_owner=DEVICE_OWNER_ROUTER_GW, network_id=policy['object_id']) - router = context.session.query(l3_db.Router).filter( - l3_db.Router.gw_port_id.in_(ports)) + router = context.session.query(l3_models.Router).filter( + l3_models.Router.gw_port_id.in_(ports)) rbac = rbac_db.NetworkRBAC if policy['target_tenant'] != '*': router = router.filter( - l3_db.Router.tenant_id == policy['target_tenant']) + l3_models.Router.tenant_id == policy['target_tenant']) # if there is a wildcard entry we can safely proceed without the # router lookup because they will have access either way if context.session.query(rbac_db.NetworkRBAC).filter( @@ -261,11 +261,12 @@ class External_net_db_mixin(object): rbac.action == 'access_as_external', rbac.target_tenant != '*')) router = router.filter( - ~l3_db.Router.tenant_id.in_(tenants_with_entries)) + ~l3_models.Router.tenant_id.in_(tenants_with_entries)) if new_tenant: # if this is an update we also need to ignore any router # interfaces that belong to the new target. - router = router.filter(l3_db.Router.tenant_id != new_tenant) + router = router.filter( + l3_models.Router.tenant_id != new_tenant) if router.count(): msg = _("There are routers attached to this network that " "depend on this policy for access.") diff --git a/neutron/db/extraroute_db.py b/neutron/db/extraroute_db.py index 019ebddbf71..42d0cb63980 100644 --- a/neutron/db/extraroute_db.py +++ b/neutron/db/extraroute_db.py @@ -24,6 +24,7 @@ from neutron._i18n import _ from neutron.common import utils from neutron.db import db_base_plugin_v2 from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import extraroute from neutron.extensions import l3 @@ -46,7 +47,7 @@ class RouterRoute(model_base.BASEV2, models_v2.Route): ondelete="CASCADE"), primary_key=True) - router = orm.relationship(l3_db.Router, + router = orm.relationship(l3_models.Router, backref=orm.backref("route_list", lazy='joined', cascade='delete')) diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index 05af8a0ed5d..75f57215526 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -19,32 +19,29 @@ from debtcollector import removals import netaddr from neutron_lib.api import validators from neutron_lib import constants as lib_constants -from neutron_lib.db import model_base from neutron_lib import exceptions as n_exc from oslo_log import log as logging from oslo_utils import excutils from oslo_utils import uuidutils import six -import sqlalchemy as sa from sqlalchemy import orm from sqlalchemy.orm import exc from neutron._i18n import _, _LI from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api -from neutron.api.v2 import attributes from neutron.callbacks import events from neutron.callbacks import exceptions from neutron.callbacks import registry from neutron.callbacks import resources +from neutron.common import _deprecate from neutron.common import constants as n_const from neutron.common import ipv6_utils from neutron.common import rpc as n_rpc from neutron.common import utils from neutron.db import api as db_api from neutron.db import common_db_mixin -from neutron.db import l3_agentschedulers_db as l3_agt +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 -from neutron.db import standard_attr from neutron.db import standardattrdescription_db as st_attr from neutron.extensions import external_net from neutron.extensions import l3 @@ -55,6 +52,11 @@ from neutron.plugins.common import utils as p_utils LOG = logging.getLogger(__name__) +_deprecate._moved_global('RouterPort', new_module=l3_models) +_deprecate._moved_global('Router', new_module=l3_models) +_deprecate._moved_global('FloatingIP', new_module=l3_models) + + DEVICE_OWNER_HA_REPLICATED_INT = lib_constants.DEVICE_OWNER_HA_REPLICATED_INT DEVICE_OWNER_ROUTER_INTF = lib_constants.DEVICE_OWNER_ROUTER_INTF DEVICE_OWNER_ROUTER_GW = lib_constants.DEVICE_OWNER_ROUTER_GW @@ -68,90 +70,6 @@ API_TO_DB_COLUMN_MAP = {'port_id': 'fixed_port_id'} CORE_ROUTER_ATTRS = ('id', 'name', 'tenant_id', 'admin_state_up', 'status') -class RouterPort(model_base.BASEV2): - router_id = sa.Column( - sa.String(36), - sa.ForeignKey('routers.id', ondelete="CASCADE"), - primary_key=True) - port_id = sa.Column( - sa.String(36), - sa.ForeignKey('ports.id', ondelete="CASCADE"), - primary_key=True, - unique=True) - revises_on_change = ('router', ) - # The port_type attribute is redundant as the port table already specifies - # it in DEVICE_OWNER.However, this redundancy enables more efficient - # queries on router ports, and also prevents potential error-prone - # conditions which might originate from users altering the DEVICE_OWNER - # property of router ports. - port_type = sa.Column(sa.String(attributes.DEVICE_OWNER_MAX_LEN)) - port = orm.relationship( - models_v2.Port, - backref=orm.backref('routerport', uselist=False, cascade="all,delete"), - lazy='joined') - - -class Router(standard_attr.HasStandardAttributes, model_base.BASEV2, - model_base.HasId, model_base.HasProject): - """Represents a v2 neutron router.""" - - name = sa.Column(sa.String(attributes.NAME_MAX_LEN)) - status = sa.Column(sa.String(16)) - admin_state_up = sa.Column(sa.Boolean) - gw_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id')) - gw_port = orm.relationship(models_v2.Port, lazy='joined') - flavor_id = sa.Column(sa.String(36), - sa.ForeignKey("flavors.id"), nullable=True) - attached_ports = orm.relationship( - RouterPort, - backref='router', - lazy='dynamic') - l3_agents = orm.relationship( - 'Agent', lazy='joined', viewonly=True, - secondary=l3_agt.RouterL3AgentBinding.__table__) - api_collections = [l3.ROUTERS] - - -class FloatingIP(standard_attr.HasStandardAttributes, model_base.BASEV2, - model_base.HasId, model_base.HasProject): - """Represents a floating IP address. - - This IP address may or may not be allocated to a tenant, and may or - may not be associated with an internal port/ip address/router. - """ - - floating_ip_address = sa.Column(sa.String(64), nullable=False) - floating_network_id = sa.Column(sa.String(36), nullable=False) - floating_port_id = sa.Column(sa.String(36), - sa.ForeignKey('ports.id', ondelete="CASCADE"), - nullable=False) - - # The ORM-level "delete" cascade relationship between port and floating_ip - # is required for causing the in-Python event "after_delete" that needs for - # proper quota management in case when cascade removal of the floating_ip - # happens after removal of the floating_port - port = orm.relationship(models_v2.Port, - backref=orm.backref('floating_ips', - cascade='all,delete-orphan'), - foreign_keys='FloatingIP.floating_port_id') - fixed_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id')) - fixed_ip_address = sa.Column(sa.String(64)) - router_id = sa.Column(sa.String(36), sa.ForeignKey('routers.id')) - # Additional attribute for keeping track of the router where the floating - # ip was associated in order to be able to ensure consistency even if an - # asynchronous backend is unavailable when the floating IP is disassociated - last_known_router_id = sa.Column(sa.String(36)) - status = sa.Column(sa.String(16)) - router = orm.relationship(Router, backref='floating_ips') - __table_args__ = ( - sa.UniqueConstraint( - floating_network_id, fixed_port_id, fixed_ip_address, - name=('uniq_floatingips0floatingnetworkid' - '0fixedportid0fixedipaddress')), - model_base.BASEV2.__table_args__,) - api_collections = [l3.FLOATINGIPS] - - class L3_NAT_dbonly_mixin(l3.RouterPluginBase, st_attr.StandardAttrDescriptionMixin): """Mixin class to add L3/NAT router methods to db_base_plugin_v2.""" @@ -193,7 +111,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, def _get_router(self, context, router_id): try: - router = self._get_by_id(context, Router, router_id) + router = self._get_by_id(context, l3_models.Router, router_id) except exc.NoResultFound: raise l3.RouterNotFound(router_id=router_id) return router @@ -230,6 +148,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, only part of a router's information was populated in sync_routers due to it being deleted during the sync. """ + Router = l3_models.Router router_ids = set(r['id'] for r in routers) query = (context.session.query(Router.id). filter( @@ -250,12 +169,13 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, status = router.get('status', n_const.ROUTER_STATUS_ACTIVE) router.setdefault('id', uuidutils.generate_uuid()) router['tenant_id'] = tenant_id - router_db = Router(id=router['id'], - tenant_id=router['tenant_id'], - name=router['name'], - admin_state_up=router['admin_state_up'], - status=status, - description=router.get('description')) + router_db = l3_models.Router( + id=router['id'], + tenant_id=router['tenant_id'], + name=router['name'], + admin_state_up=router['admin_state_up'], + status=status, + description=router.get('description')) context.session.add(router_db) registry.notify(resources.ROUTER, events.PRECOMMIT_CREATE, self, context=context, router=router, @@ -407,7 +327,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, with context.session.begin(subtransactions=True): router.gw_port = self._core_plugin._get_port( context.elevated(), gw_port['id']) - router_port = RouterPort( + router_port = l3_models.RouterPort( router_id=router.id, port_id=gw_port['id'], port_type=DEVICE_OWNER_ROUTER_GW @@ -593,7 +513,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, sorts=None, limit=None, marker=None, page_reverse=False): marker_obj = self._get_marker_obj(context, 'router', limit, marker) - return self._get_collection(context, Router, + return self._get_collection(context, l3_models.Router, self._make_router_dict, filters=filters, fields=fields, sorts=sorts, @@ -603,7 +523,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, @db_api.retry_if_session_inactive() def get_routers_count(self, context, filters=None): - return self._get_collection_count(context, Router, + return self._get_collection_count(context, l3_models.Router, filters=filters) def _check_for_dup_router_subnets(self, context, router, @@ -824,7 +744,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, if new_port: with mgr: with context.session.begin(subtransactions=True): - router_port = RouterPort( + router_port = l3_models.RouterPort( port_id=port['id'], router_id=router.id, port_type=device_owner @@ -864,7 +784,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, subnet_id): subnet = self._core_plugin.get_subnet(context, subnet_id) subnet_cidr = netaddr.IPNetwork(subnet['cidr']) - fip_qry = context.session.query(FloatingIP) + fip_qry = context.session.query(l3_models.FloatingIP) try: kwargs = {'context': context, 'router_id': router_id, 'subnet_id': subnet_id} @@ -884,7 +804,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, def _remove_interface_by_port(self, context, router_id, port_id, subnet_id, owner): - qry = context.session.query(RouterPort) + qry = context.session.query(l3_models.RouterPort) qry = qry.filter_by( port_id=port_id, router_id=router_id, @@ -916,10 +836,11 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, subnet = self._core_plugin.get_subnet(context, subnet_id) try: - rport_qry = context.session.query(models_v2.Port).join(RouterPort) + rport_qry = context.session.query(models_v2.Port).join( + l3_models.RouterPort) ports = rport_qry.filter( - RouterPort.router_id == router_id, - RouterPort.port_type == owner, + l3_models.RouterPort.router_id == router_id, + l3_models.RouterPort.port_type == owner, models_v2.Port.network_id == subnet['network_id'] ) @@ -985,7 +906,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, def _get_floatingip(self, context, id): try: - floatingip = self._get_by_id(context, FloatingIP, id) + floatingip = self._get_by_id(context, l3_models.FloatingIP, id) except exc.NoResultFound: raise l3.FloatingIPNotFound(floatingip_id=id) return floatingip @@ -1038,6 +959,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, # Among them, if the router's interface address matches # with subnet's gateway-ip, return that router. # Otherwise return the first router. + RouterPort = l3_models.RouterPort gw_port = orm.aliased(models_v2.Port, name="gw_port") routerport_qry = context.session.query( RouterPort.router_id, models_v2.IPAllocation.ip_address).join( @@ -1146,7 +1068,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, # Floating IP association is not changed. return port_id, internal_ip_address, router_id - fip_qry = context.session.query(FloatingIP) + fip_qry = context.session.query(l3_models.FloatingIP) try: fip_qry.filter_by( fixed_port_id=fip['port_id'], @@ -1261,7 +1183,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, floating_fixed_ip = external_ipv4_ips[0] floating_ip_address = floating_fixed_ip['ip_address'] - floatingip_db = FloatingIP( + floatingip_db = l3_models.FloatingIP( id=fip_id, tenant_id=fip['tenant_id'], status=initial_status, @@ -1326,8 +1248,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, @db_api.retry_if_session_inactive() def update_floatingip_status(self, context, floatingip_id, status): """Update operational status for floating IP in neutron DB.""" - fip_query = self._model_query(context, FloatingIP).filter( - FloatingIP.id == floatingip_id) + fip_query = self._model_query(context, l3_models.FloatingIP).filter( + l3_models.FloatingIP.id == floatingip_id) fip_query.update({'status': status}, synchronize_session=False) def _delete_floatingip(self, context, id): @@ -1364,7 +1286,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, if key in filters: filters[val] = filters.pop(key) - return self._get_collection(context, FloatingIP, + return self._get_collection(context, l3_models.FloatingIP, self._make_floatingip_dict, filters=filters, fields=fields, sorts=sorts, @@ -1374,7 +1296,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, @db_api.retry_if_session_inactive() def delete_disassociated_floatingips(self, context, network_id): - query = self._model_query(context, FloatingIP) + query = self._model_query(context, l3_models.FloatingIP) query = query.filter_by(floating_network_id=network_id, fixed_port_id=None, router_id=None) @@ -1383,7 +1305,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, @db_api.retry_if_session_inactive() def get_floatingips_count(self, context, filters=None): - return self._get_collection_count(context, FloatingIP, + return self._get_collection_count(context, l3_models.FloatingIP, filters=filters) def _router_exists(self, context, router_id): @@ -1459,7 +1381,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, router_ids = set() with context.session.begin(subtransactions=True): - fip_qry = context.session.query(FloatingIP) + fip_qry = context.session.query(l3_models.FloatingIP) floating_ips = fip_qry.filter_by(fixed_port_id=port_id) for floating_ip in floating_ips: router_ids.add(floating_ip['router_id']) @@ -1496,7 +1418,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, if active is not None: filters['admin_state_up'] = [active] router_dicts = self._get_collection( - context, Router, self._make_router_dict_with_gw_port, + context, l3_models.Router, self._make_router_dict_with_gw_port, filters=filters) if not router_dicts: return [] @@ -1509,7 +1431,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, def _unique_floatingip_iterator(query): """Iterates over only one row per floating ip. Ignores others.""" # Group rows by fip id. They must be sorted by same. - q = query.order_by(FloatingIP.id) + q = query.order_by(l3_models.FloatingIP.id) keyfunc = lambda row: row[0]['id'] group_iterator = itertools.groupby(q, keyfunc) @@ -1535,10 +1457,10 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, if not router_ids: return [] - query = context.session.query(FloatingIP, + query = context.session.query(l3_models.FloatingIP, models_v2.SubnetPool.address_scope_id) query = query.join(models_v2.Port, - FloatingIP.fixed_port_id == models_v2.Port.id) + l3_models.FloatingIP.fixed_port_id == models_v2.Port.id) # Outer join of Subnet can cause each ip to have more than one row. query = query.outerjoin(models_v2.Subnet, models_v2.Subnet.network_id == models_v2.Port.network_id) @@ -1547,7 +1469,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, models_v2.Subnet.subnetpool_id == models_v2.SubnetPool.id) # Filter out on router_ids - query = query.filter(FloatingIP.router_id.in_(router_ids)) + query = query.filter(l3_models.FloatingIP.router_id.in_(router_ids)) return [self._make_floatingip_dict_with_scope(*row) for row in self._unique_floatingip_iterator(query)] @@ -1558,10 +1480,10 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, DEVICE_OWNER_HA_REPLICATED_INT] if not router_ids: return [] - qry = context.session.query(RouterPort) + qry = context.session.query(l3_models.RouterPort) qry = qry.filter( - RouterPort.router_id.in_(router_ids), - RouterPort.port_type.in_(device_owners) + l3_models.RouterPort.router_id.in_(router_ids), + l3_models.RouterPort.port_type.in_(device_owners) ) interfaces = [self._core_plugin._make_port_dict(rp.port, None) @@ -1893,14 +1815,14 @@ def _notify_subnetpool_address_scope_update(resource, event, context = kwargs['context'] subnetpool_id = kwargs['subnetpool_id'] - query = context.session.query(RouterPort.router_id) + query = context.session.query(l3_models.RouterPort.router_id) query = query.join(models_v2.Port) query = query.join( models_v2.Subnet, models_v2.Subnet.network_id == models_v2.Port.network_id) query = query.filter( models_v2.Subnet.subnetpool_id == subnetpool_id, - RouterPort.port_type.in_(n_const.ROUTER_PORT_OWNERS)) + l3_models.RouterPort.port_type.in_(n_const.ROUTER_PORT_OWNERS)) query = query.distinct() router_ids = [r[0] for r in query] @@ -1915,3 +1837,6 @@ def _notify_subnetpool_address_scope_update(resource, event, ) def subscribe(): pass + + +_deprecate._MovedGlobals() diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index 0525e684045..37ed671cbd0 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -34,6 +34,7 @@ from neutron.db import l3_agentschedulers_db as l3_sched_db from neutron.db import l3_attrs_db from neutron.db import l3_db from neutron.db.models import allowed_address_pair as aap_models +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import l3 from neutron.extensions import portbindings @@ -303,7 +304,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, def _get_floatingip_on_port(self, context, port_id=None): """Helper function to retrieve the fip associated with port.""" - fip_qry = context.session.query(l3_db.FloatingIP) + fip_qry = context.session.query(l3_models.FloatingIP) floating_ip = fip_qry.filter_by(fixed_port_id=port_id) return floating_ip.first() @@ -351,7 +352,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, port['fixed_ips'][-1]['subnet_id']) with context.session.begin(subtransactions=True): - router_port = l3_db.RouterPort( + router_port = l3_models.RouterPort( port_id=port['id'], router_id=router.id, port_type=device_owner @@ -538,10 +539,10 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, """Query router interfaces that relate to list of router_ids.""" if not router_ids: return [] - qry = context.session.query(l3_db.RouterPort) + qry = context.session.query(l3_models.RouterPort) qry = qry.filter( - l3_db.RouterPort.router_id.in_(router_ids), - l3_db.RouterPort.port_type == const.DEVICE_OWNER_ROUTER_SNAT + l3_models.RouterPort.router_id.in_(router_ids), + l3_models.RouterPort.port_type == const.DEVICE_OWNER_ROUTER_SNAT ) interfaces = collections.defaultdict(list) for rp in qry: @@ -775,7 +776,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, def _get_snat_interface_ports_for_router(self, context, router_id): """Return all existing snat_router_interface ports.""" - qry = context.session.query(l3_db.RouterPort) + qry = context.session.query(l3_models.RouterPort) qry = qry.filter_by( router_id=router_id, port_type=const.DEVICE_OWNER_ROUTER_SNAT @@ -802,7 +803,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, raise n_exc.BadRequest(resource='router', msg=msg) with context.session.begin(subtransactions=True): - router_port = l3_db.RouterPort( + router_port = l3_models.RouterPort( port_id=snat_port['id'], router_id=router.id, port_type=const.DEVICE_OWNER_ROUTER_SNAT @@ -1029,8 +1030,8 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, (port_dict['status'] == const.PORT_STATUS_ACTIVE)) if not port_valid_state: return - query = context.session.query(l3_db.FloatingIP).filter( - l3_db.FloatingIP.fixed_ip_address == port_addr_pair_ip) + query = context.session.query(l3_models.FloatingIP).filter( + l3_models.FloatingIP.fixed_ip_address == port_addr_pair_ip) fip = query.first() return self._core_plugin.get_port( context, fip.fixed_port_id) if fip else None diff --git a/neutron/db/l3_gwmode_db.py b/neutron/db/l3_gwmode_db.py index ad218233dc6..ec7c7b4b48c 100644 --- a/neutron/db/l3_gwmode_db.py +++ b/neutron/db/l3_gwmode_db.py @@ -20,6 +20,7 @@ from sqlalchemy import sql from neutron._i18n import _ from neutron.db import db_base_plugin_v2 from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.extensions import l3 @@ -32,7 +33,7 @@ cfg.CONF.register_opts(OPTS) EXTERNAL_GW_INFO = l3.EXTERNAL_GW_INFO # Modify the Router Data Model adding the enable_snat attribute -setattr(l3_db.Router, 'enable_snat', +setattr(l3_models.Router, 'enable_snat', sa.Column(sa.Boolean, default=True, server_default=sql.true(), nullable=False)) diff --git a/neutron/db/l3_hamode_db.py b/neutron/db/l3_hamode_db.py index a865f7a6983..d63e1b89a86 100644 --- a/neutron/db/l3_hamode_db.py +++ b/neutron/db/l3_hamode_db.py @@ -39,9 +39,9 @@ from neutron.db import api as db_api from neutron.db.availability_zone import router as router_az_db from neutron.db import common_db_mixin from neutron.db import l3_attrs_db -from neutron.db import l3_db from neutron.db import l3_dvr_db from neutron.db.l3_dvr_db import is_distributed_router +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import l3 from neutron.extensions import l3_ext_ha_mode as l3_ha @@ -345,7 +345,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, def _create_ha_port_binding(self, context, router_id, port_id): try: with context.session.begin(): - routerportbinding = l3_db.RouterPort( + routerportbinding = l3_models.RouterPort( port_id=port_id, router_id=router_id, port_type=constants.DEVICE_OWNER_ROUTER_HA_INTF) context.session.add(routerportbinding) diff --git a/neutron/db/l3_hascheduler_db.py b/neutron/db/l3_hascheduler_db.py index b2ddf2aaa7d..e6d5c8cae7c 100644 --- a/neutron/db/l3_hascheduler_db.py +++ b/neutron/db/l3_hascheduler_db.py @@ -22,7 +22,7 @@ from neutron.callbacks import resources from neutron.db import agents_db from neutron.db import l3_agentschedulers_db as l3_sch_db from neutron.db import l3_attrs_db -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.extensions import portbindings from neutron import manager from neutron.plugins.common import constants as service_constants @@ -46,11 +46,11 @@ class L3_HA_scheduler_db_mixin(l3_sch_db.AZL3AgentSchedulerDbMixin): join(l3_attrs_db.RouterExtraAttributes, binding_model.router_id == l3_attrs_db.RouterExtraAttributes.router_id). - join(l3_db.Router). + join(l3_models.Router). filter(l3_attrs_db.RouterExtraAttributes.ha == sql.true()). group_by(binding_model.router_id).subquery()) - query = (context.session.query(l3_db.Router, sub_query.c.count). + query = (context.session.query(l3_models.Router, sub_query.c.count). join(sub_query)) return [(self._make_router_dict(router), agent_count) diff --git a/neutron/db/metering/metering_db.py b/neutron/db/metering/metering_db.py index 01cea0b397e..8e922ca6331 100644 --- a/neutron/db/metering/metering_db.py +++ b/neutron/db/metering/metering_db.py @@ -23,7 +23,7 @@ from neutron.api.rpc.agentnotifiers import metering_rpc_agent_api from neutron.api.v2 import attributes as attr from neutron.common import constants from neutron.db import common_db_mixin as base_db -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.extensions import metering @@ -46,7 +46,7 @@ class MeteringLabel(model_base.BASEV2, rules = orm.relationship(MeteringLabelRule, backref="label", cascade="delete", lazy="joined") routers = orm.relationship( - l3_db.Router, + l3_models.Router, primaryjoin="MeteringLabel.tenant_id==Router.tenant_id", foreign_keys='MeteringLabel.tenant_id', uselist=True) @@ -214,7 +214,7 @@ class MeteringDbMixin(metering.MeteringPluginBase, if label.shared: if not all_routers: all_routers = self._get_collection_query(context, - l3_db.Router) + l3_models.Router) routers = all_routers else: routers = label.routers @@ -238,7 +238,7 @@ class MeteringDbMixin(metering.MeteringPluginBase, rule['metering_label_id']) if label.shared: - routers = self._get_collection_query(context, l3_db.Router) + routers = self._get_collection_query(context, l3_models.Router) else: routers = label.routers @@ -259,6 +259,6 @@ class MeteringDbMixin(metering.MeteringPluginBase, labels = labels.filter(MeteringLabel.id == label_id) elif router_ids: labels = (labels.join(MeteringLabel.routers). - filter(l3_db.Router.id.in_(router_ids))) + filter(l3_models.Router.id.in_(router_ids))) return self._process_sync_metering_data(context, labels) diff --git a/neutron/db/migration/models/head.py b/neutron/db/migration/models/head.py index 93002f9a1b6..00f3a0b7867 100644 --- a/neutron/db/migration/models/head.py +++ b/neutron/db/migration/models/head.py @@ -36,7 +36,6 @@ from neutron.db import extraroute_db # noqa from neutron.db import flavors_db # noqa from neutron.db import l3_agentschedulers_db # noqa from neutron.db import l3_attrs_db # noqa -from neutron.db import l3_db # noqa from neutron.db import l3_dvrscheduler_db # noqa from neutron.db import l3_gwmode_db # noqa from neutron.db import l3_hamode_db # noqa diff --git a/neutron/db/models/l3.py b/neutron/db/models/l3.py new file mode 100644 index 00000000000..a37a7f6e468 --- /dev/null +++ b/neutron/db/models/l3.py @@ -0,0 +1,105 @@ +# 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_lib.db import model_base +import sqlalchemy as sa +from sqlalchemy import orm + +from neutron.api.v2 import attributes +from neutron.db import l3_agentschedulers_db as l3_agt +from neutron.db import models_v2 +from neutron.db import standard_attr +from neutron.extensions import l3 + + +class RouterPort(model_base.BASEV2): + router_id = sa.Column( + sa.String(36), + sa.ForeignKey('routers.id', ondelete="CASCADE"), + primary_key=True) + port_id = sa.Column( + sa.String(36), + sa.ForeignKey('ports.id', ondelete="CASCADE"), + primary_key=True, + unique=True) + revises_on_change = ('router', ) + # The port_type attribute is redundant as the port table already specifies + # it in DEVICE_OWNER.However, this redundancy enables more efficient + # queries on router ports, and also prevents potential error-prone + # conditions which might originate from users altering the DEVICE_OWNER + # property of router ports. + port_type = sa.Column(sa.String(attributes.DEVICE_OWNER_MAX_LEN)) + port = orm.relationship( + models_v2.Port, + backref=orm.backref('routerport', uselist=False, cascade="all,delete"), + lazy='joined') + + +class Router(standard_attr.HasStandardAttributes, model_base.BASEV2, + model_base.HasId, model_base.HasProject): + """Represents a v2 neutron router.""" + + name = sa.Column(sa.String(attributes.NAME_MAX_LEN)) + status = sa.Column(sa.String(16)) + admin_state_up = sa.Column(sa.Boolean) + gw_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id')) + gw_port = orm.relationship(models_v2.Port, lazy='joined') + flavor_id = sa.Column(sa.String(36), + sa.ForeignKey("flavors.id"), nullable=True) + attached_ports = orm.relationship( + RouterPort, + backref='router', + lazy='dynamic') + l3_agents = orm.relationship( + 'Agent', lazy='joined', viewonly=True, + secondary=l3_agt.RouterL3AgentBinding.__table__) + api_collections = [l3.ROUTERS] + + +class FloatingIP(standard_attr.HasStandardAttributes, model_base.BASEV2, + model_base.HasId, model_base.HasProject): + """Represents a floating IP address. + + This IP address may or may not be allocated to a tenant, and may or + may not be associated with an internal port/ip address/router. + """ + + floating_ip_address = sa.Column(sa.String(64), nullable=False) + floating_network_id = sa.Column(sa.String(36), nullable=False) + floating_port_id = sa.Column(sa.String(36), + sa.ForeignKey('ports.id', ondelete="CASCADE"), + nullable=False) + + # The ORM-level "delete" cascade relationship between port and floating_ip + # is required for causing the in-Python event "after_delete" that needs for + # proper quota management in case when cascade removal of the floating_ip + # happens after removal of the floating_port + port = orm.relationship(models_v2.Port, + backref=orm.backref('floating_ips', + cascade='all,delete-orphan'), + foreign_keys='FloatingIP.floating_port_id') + fixed_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id')) + fixed_ip_address = sa.Column(sa.String(64)) + router_id = sa.Column(sa.String(36), sa.ForeignKey('routers.id')) + # Additional attribute for keeping track of the router where the floating + # ip was associated in order to be able to ensure consistency even if an + # asynchronous backend is unavailable when the floating IP is disassociated + last_known_router_id = sa.Column(sa.String(36)) + status = sa.Column(sa.String(16)) + router = orm.relationship(Router, backref='floating_ips') + __table_args__ = ( + sa.UniqueConstraint( + floating_network_id, fixed_port_id, fixed_ip_address, + name=('uniq_floatingips0floatingnetworkid' + '0fixedportid0fixedipaddress')), + model_base.BASEV2.__table_args__,) + api_collections = [l3.FLOATINGIPS] diff --git a/neutron/scheduler/l3_agent_scheduler.py b/neutron/scheduler/l3_agent_scheduler.py index 0300f411247..2d956ff01aa 100644 --- a/neutron/scheduler/l3_agent_scheduler.py +++ b/neutron/scheduler/l3_agent_scheduler.py @@ -31,8 +31,8 @@ from neutron.common import constants from neutron.common import utils from neutron.db import api as db_api from neutron.db import l3_agentschedulers_db -from neutron.db import l3_db from neutron.db import l3_hamode_db +from neutron.db.models import l3 as l3_models from neutron.extensions import availability_zone as az_ext from neutron.extensions import l3 @@ -85,10 +85,11 @@ class L3Scheduler(object): """Get routers with no agent binding.""" # TODO(gongysh) consider the disabled agent's router no_agent_binding = ~sql.exists().where( - l3_db.Router.id == + l3_models.Router.id == l3_agentschedulers_db.RouterL3AgentBinding.router_id) - query = context.session.query(l3_db.Router.id).filter(no_agent_binding) - query = query.filter(l3_db.Router.status == + query = context.session.query( + l3_models.Router.id).filter(no_agent_binding) + query = query.filter(l3_models.Router.status == constants.ROUTER_STATUS_ACTIVE) unscheduled_router_ids = [router_id_[0] for router_id_ in query] if unscheduled_router_ids: diff --git a/neutron/services/l3_router/l3_router_plugin.py b/neutron/services/l3_router/l3_router_plugin.py index 6525490eaf3..2a3c585734c 100644 --- a/neutron/services/l3_router/l3_router_plugin.py +++ b/neutron/services/l3_router/l3_router_plugin.py @@ -25,12 +25,12 @@ from neutron.common import topics from neutron.db import common_db_mixin from neutron.db import dns_db from neutron.db import extraroute_db -from neutron.db import l3_db from neutron.db import l3_dvr_ha_scheduler_db from neutron.db import l3_dvrscheduler_db from neutron.db import l3_gwmode_db from neutron.db import l3_hamode_db from neutron.db import l3_hascheduler_db +from neutron.db.models import l3 as l3_models from neutron.extensions import l3 from neutron.plugins.common import constants from neutron.quota import resource_registry @@ -64,8 +64,8 @@ class L3RouterPlugin(service_base.ServicePluginBase, __native_pagination_support = True __native_sorting_support = True - @resource_registry.tracked_resources(router=l3_db.Router, - floatingip=l3_db.FloatingIP) + @resource_registry.tracked_resources(router=l3_models.Router, + floatingip=l3_models.FloatingIP) def __init__(self): self.router_scheduler = importutils.import_object( cfg.CONF.router_scheduler_driver) diff --git a/neutron/tests/unit/db/test_db_base_plugin_v2.py b/neutron/tests/unit/db/test_db_base_plugin_v2.py index 7c6dc2df9c8..f41c4abcbc7 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -50,7 +50,7 @@ from neutron import context from neutron.db import api as db_api from neutron.db import db_base_plugin_common from neutron.db import ipam_backend_mixin -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db.models import securitygroup as sg_models from neutron.db import models_v2 from neutron.db import standard_attr @@ -4457,11 +4457,11 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): # to make this port belong to a router ctx = context.get_admin_context() with ctx.session.begin(): - router = l3_db.Router() + router = l3_models.Router() ctx.session.add(router) with ctx.session.begin(): - rp = l3_db.RouterPort(router_id=router.id, - port_id=port['port']['id']) + rp = l3_models.RouterPort(router_id=router.id, + port_id=port['port']['id']) ctx.session.add(rp) data = {'subnet': {'gateway_ip': '10.0.0.99'}} req = self.new_update_request('subnets', data, @@ -6046,15 +6046,15 @@ class DbModelMixin(object): def _make_floating_ip(self, ctx, port_id): with ctx.session.begin(): - flip = l3_db.FloatingIP(floating_ip_address='1.2.3.4', - floating_network_id='somenet', - floating_port_id=port_id) + flip = l3_models.FloatingIP(floating_ip_address='1.2.3.4', + floating_network_id='somenet', + floating_port_id=port_id) ctx.session.add(flip) return flip def _make_router(self, ctx): with ctx.session.begin(): - router = l3_db.Router() + router = l3_models.Router() ctx.session.add(router) return router @@ -6104,7 +6104,7 @@ class DbModelMixin(object): ctx = context.get_admin_context() router = self._make_router(ctx) self._test_staledata_error_on_concurrent_object_update( - l3_db.Router, router['id']) + l3_models.Router, router['id']) def test_staledata_error_on_concurrent_object_update_floatingip(self): ctx = context.get_admin_context() @@ -6112,7 +6112,7 @@ class DbModelMixin(object): port = self._make_port(ctx, network.id) flip = self._make_floating_ip(ctx, port.id) self._test_staledata_error_on_concurrent_object_update( - l3_db.FloatingIP, flip['id']) + l3_models.FloatingIP, flip['id']) def test_staledata_error_on_concurrent_object_update_sg(self): ctx = context.get_admin_context() diff --git a/neutron/tests/unit/db/test_l3_db.py b/neutron/tests/unit/db/test_l3_db.py index faa9658fdd7..b336539409e 100644 --- a/neutron/tests/unit/db/test_l3_db.py +++ b/neutron/tests/unit/db/test_l3_db.py @@ -22,6 +22,7 @@ from neutron.callbacks import events from neutron.callbacks import registry from neutron.callbacks import resources from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.extensions import l3 from neutron import manager from neutron.tests import base @@ -141,7 +142,7 @@ class TestL3_NAT_dbonly_mixin(base.BaseTestCase): query.reset_mock() result = list( l3_db.L3_NAT_dbonly_mixin._unique_floatingip_iterator(query)) - query.order_by.assert_called_once_with(l3_db.FloatingIP.id) + query.order_by.assert_called_once_with(l3_models.FloatingIP.id) self.assertEqual([({'id': 'id1'}, 'scope1'), ({'id': 'id2'}, 'scope2'), ({'id': 'id3'}, 'scope3')], result) @@ -212,7 +213,7 @@ class TestL3_NAT_dbonly_mixin(base.BaseTestCase): def test__check_and_get_fip_assoc_with_extra_association_no_change(self): fip = {'extra_key': 'value'} context = mock.MagicMock() - floatingip_db = l3_db.FloatingIP( + floatingip_db = l3_models.FloatingIP( id='fake_fip_id', floating_network_id='fake_floating_network_id', floating_ip_address='8.8.8.8', @@ -234,7 +235,7 @@ class L3_NAT_db_mixin(base.BaseTestCase): self.db = l3_db.L3_NAT_db_mixin() def _test_create_router(self, external_gateway_info=None): - router_db = l3_db.Router(id='123') + router_db = l3_models.Router(id='123') router_dict = {'id': '123', 'tenant_id': '456', 'external_gateway_info': external_gateway_info} # Need to use a copy here as the create_router method pops the gateway diff --git a/neutron/tests/unit/extensions/test_flavors.py b/neutron/tests/unit/extensions/test_flavors.py index b036e3c62fd..74e0973729c 100644 --- a/neutron/tests/unit/extensions/test_flavors.py +++ b/neutron/tests/unit/extensions/test_flavors.py @@ -25,7 +25,7 @@ from neutron.api.v2 import attributes as attr from neutron import context from neutron.db import api as dbapi from neutron.db import flavors_db -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db import servicetype_db from neutron.extensions import flavors from neutron.plugins.common import constants @@ -669,7 +669,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, # make use of router since it has a flavor id fl, data = self._create_flavor() with self.ctx.session.begin(): - self.ctx.session.add(l3_db.Router(flavor_id=fl['id'])) + self.ctx.session.add(l3_models.Router(flavor_id=fl['id'])) self.assertRaises( flavors.FlavorInUse, self.plugin.delete_flavor, diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py index 9b26696c6b7..2ac6ee7b811 100644 --- a/neutron/tests/unit/extensions/test_l3.py +++ b/neutron/tests/unit/extensions/test_l3.py @@ -44,6 +44,7 @@ from neutron.db import l3_attrs_db from neutron.db import l3_db from neutron.db import l3_dvr_db from neutron.db import l3_dvrscheduler_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import external_net from neutron.extensions import l3 @@ -2807,18 +2808,18 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): internal_subnet, external_network_id): gw_port = orm.aliased(models_v2.Port, name="gw_port") routerport_qry = context.session.query( - l3_db.RouterPort.router_id, + l3_models.RouterPort.router_id, models_v2.IPAllocation.ip_address ).join( models_v2.Port, models_v2.IPAllocation ).filter( models_v2.Port.network_id == internal_port['network_id'], - l3_db.RouterPort.port_type.in_( + l3_models.RouterPort.port_type.in_( lib_constants.ROUTER_INTERFACE_OWNERS ), models_v2.IPAllocation.subnet_id == internal_subnet['id'] ).join( - gw_port, gw_port.device_id == l3_db.RouterPort.router_id + gw_port, gw_port.device_id == l3_models.RouterPort.router_id ).filter( gw_port.network_id == external_network_id, ).distinct() diff --git a/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py b/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py index 4298c9c7a2b..0fd5ad38cd5 100644 --- a/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py +++ b/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py @@ -28,6 +28,7 @@ from neutron.db import api as db_api from neutron.db import external_net_db from neutron.db import l3_db from neutron.db import l3_gwmode_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import l3 from neutron.extensions import l3_ext_gw_mode @@ -138,7 +139,7 @@ class TestL3GwModeMixin(testlib_api.SqlTestCase): # foreign key violations self.context.session.flush() self.context.session.add(self.net_ext) - self.router = l3_db.Router( + self.router = l3_models.Router( id=_uuid(), name=None, tenant_id=self.tenant_id, @@ -217,7 +218,7 @@ class TestL3GwModeMixin(testlib_api.SqlTestCase): network_id=self.int_net.id, subnet_id=self.int_sub_id, ip_address='3.3.3.3') - self.fip = l3_db.FloatingIP( + self.fip = l3_models.FloatingIP( id=_uuid(), floating_ip_address='1.1.1.2', floating_network_id=self.ext_net_id, diff --git a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_db.py b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_db.py index dbd56054902..77944793d52 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_db.py +++ b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_db.py @@ -19,8 +19,8 @@ from neutron.common import constants as n_const from neutron.common import utils from neutron import context from neutron.db import l3_attrs_db -from neutron.db import l3_db from neutron.db import l3_hamode_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.extensions import portbindings from neutron.plugins.ml2.drivers.l2pop import db as l2pop_db @@ -51,7 +51,7 @@ class TestL2PopulationDBTestCase(testlib_api.SqlTestCase): def _create_router(self, distributed=True, ha=False): with self.ctx.session.begin(subtransactions=True): - self.ctx.session.add(l3_db.Router(id=TEST_ROUTER_ID)) + self.ctx.session.add(l3_models.Router(id=TEST_ROUTER_ID)) self.ctx.session.add(l3_attrs_db.RouterExtraAttributes( router_id=TEST_ROUTER_ID, distributed=distributed, ha=ha)) diff --git a/neutron/tests/unit/plugins/ml2/test_db.py b/neutron/tests/unit/plugins/ml2/test_db.py index ab2271e7bd7..675475fe5a4 100644 --- a/neutron/tests/unit/plugins/ml2/test_db.py +++ b/neutron/tests/unit/plugins/ml2/test_db.py @@ -22,7 +22,7 @@ from sqlalchemy.orm import query from neutron import context from neutron.db import db_base_plugin_v2 -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.db import segments_db from neutron.extensions import portbindings @@ -293,7 +293,7 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase): def _setup_neutron_router(self): with self.ctx.session.begin(subtransactions=True): - router = l3_db.Router() + router = l3_models.Router() self.ctx.session.add(router) return router diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 402e7c7349f..28642b4281c 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -38,7 +38,7 @@ from neutron import context from neutron.db import agents_db from neutron.db import api as db_api from neutron.db import db_base_plugin_v2 as base_plugin -from neutron.db import l3_db +from neutron.db.models import l3 as l3_models from neutron.db import models_v2 from neutron.db import provisioning_blocks from neutron.db import segments_db @@ -1404,7 +1404,7 @@ class TestMl2DvrPortsV2(TestMl2PortsV2): # lie to turn the port into an SNAT interface with self.context.session.begin(): - rp = self.context.session.query(l3_db.RouterPort).filter_by( + rp = self.context.session.query(l3_models.RouterPort).filter_by( port_id=p['port_id']).first() rp.port_type = constants.DEVICE_OWNER_ROUTER_SNAT