Merge "RouterPort OVO integration"
This commit is contained in:
commit
58e5a6c64e
neutron
db
objects
tests/unit
@ -51,6 +51,8 @@ from neutron.db import models_v2
|
||||
from neutron.db import standardattrdescription_db as st_attr
|
||||
from neutron.extensions import external_net
|
||||
from neutron.extensions import l3
|
||||
from neutron.objects import ports as port_obj
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron.plugins.common import utils as p_utils
|
||||
from neutron import worker as neutron_worker
|
||||
|
||||
@ -369,13 +371,14 @@ 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 = l3_models.RouterPort(
|
||||
router_port = l3_obj.RouterPort(
|
||||
context,
|
||||
router_id=router.id,
|
||||
port_id=gw_port['id'],
|
||||
port_type=DEVICE_OWNER_ROUTER_GW
|
||||
)
|
||||
context.session.add(router)
|
||||
context.session.add(router_port)
|
||||
router_port.create()
|
||||
|
||||
def _validate_gw_info(self, context, gw_port, info, ext_ips):
|
||||
network_id = info['network_id'] if info else None
|
||||
@ -853,13 +856,12 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
||||
self._notify_attaching_interface(context, router_db=router,
|
||||
port=port,
|
||||
interface_info=interface_info)
|
||||
with context.session.begin(subtransactions=True):
|
||||
router_port = l3_models.RouterPort(
|
||||
port_id=port['id'],
|
||||
router_id=router.id,
|
||||
port_type=device_owner
|
||||
)
|
||||
context.session.add(router_port)
|
||||
l3_obj.RouterPort(
|
||||
context,
|
||||
port_id=port['id'],
|
||||
router_id=router.id,
|
||||
port_type=device_owner
|
||||
).create()
|
||||
# Update owner after actual process again in order to
|
||||
# make sure the records in routerports table and ports
|
||||
# table are consistent.
|
||||
@ -915,15 +917,19 @@ 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(l3_models.RouterPort)
|
||||
qry = qry.filter_by(
|
||||
obj = l3_obj.RouterPort.get_object(
|
||||
context,
|
||||
port_id=port_id,
|
||||
router_id=router_id,
|
||||
port_type=owner
|
||||
)
|
||||
try:
|
||||
port = self._core_plugin.get_port(context, qry.one().port_id)
|
||||
except (n_exc.PortNotFound, exc.NoResultFound):
|
||||
if obj:
|
||||
try:
|
||||
port = self._core_plugin.get_port(context, obj.port_id)
|
||||
except n_exc.PortNotFound:
|
||||
raise l3.RouterInterfaceNotFound(router_id=router_id,
|
||||
port_id=port_id)
|
||||
else:
|
||||
raise l3.RouterInterfaceNotFound(router_id=router_id,
|
||||
port_id=port_id)
|
||||
port_subnet_ids = [fixed_ip['subnet_id']
|
||||
@ -947,13 +953,8 @@ 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(
|
||||
l3_models.RouterPort)
|
||||
ports = rport_qry.filter(
|
||||
l3_models.RouterPort.router_id == router_id,
|
||||
l3_models.RouterPort.port_type == owner,
|
||||
models_v2.Port.network_id == subnet['network_id']
|
||||
)
|
||||
ports = port_obj.Port.get_ports_by_router(
|
||||
context, router_id, owner, subnet)
|
||||
|
||||
for p in ports:
|
||||
try:
|
||||
@ -1074,6 +1075,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
||||
# Otherwise return the first router.
|
||||
RouterPort = l3_models.RouterPort
|
||||
gw_port = orm.aliased(models_v2.Port, name="gw_port")
|
||||
# TODO(lujinluo): Need IPAllocation and Port object
|
||||
routerport_qry = context.session.query(
|
||||
RouterPort.router_id, models_v2.IPAllocation.ip_address).join(
|
||||
models_v2.Port, models_v2.IPAllocation).filter(
|
||||
@ -1599,14 +1601,12 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
||||
DEVICE_OWNER_HA_REPLICATED_INT]
|
||||
if not router_ids:
|
||||
return []
|
||||
qry = context.session.query(l3_models.RouterPort)
|
||||
qry = qry.filter(
|
||||
l3_models.RouterPort.router_id.in_(router_ids),
|
||||
l3_models.RouterPort.port_type.in_(device_owners)
|
||||
)
|
||||
# TODO(lujinluo): Need Port as synthetic field
|
||||
objs = l3_obj.RouterPort.get_objects(
|
||||
context, router_id=router_ids, port_type=list(device_owners))
|
||||
|
||||
interfaces = [self._core_plugin._make_port_dict(rp.port)
|
||||
for rp in qry]
|
||||
interfaces = [self._core_plugin._make_port_dict(rp.db_obj.port)
|
||||
for rp in objs]
|
||||
return interfaces
|
||||
|
||||
@staticmethod
|
||||
@ -1794,17 +1794,9 @@ class L3RpcNotifierMixin(object):
|
||||
context = kwargs['context']
|
||||
subnetpool_id = kwargs['subnetpool_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,
|
||||
l3_models.RouterPort.port_type.in_(n_const.ROUTER_PORT_OWNERS))
|
||||
query = query.distinct()
|
||||
router_ids = l3_obj.RouterPort.get_router_ids_by_subnetpool(
|
||||
context, subnetpool_id)
|
||||
|
||||
router_ids = [r[0] for r in query]
|
||||
l3plugin = directory.get_plugin(plugin_constants.L3)
|
||||
if l3plugin:
|
||||
l3plugin.notify_routers_updated(context, router_ids)
|
||||
|
@ -42,6 +42,7 @@ from neutron.extensions import l3
|
||||
from neutron.ipam import utils as ipam_utils
|
||||
from neutron.objects import agent as ag_obj
|
||||
from neutron.objects import l3agent as rb_obj
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron.plugins.common import utils as p_utils
|
||||
|
||||
|
||||
@ -168,14 +169,14 @@ class DVRResourceOperationHandler(object):
|
||||
|
||||
def _get_snat_interface_ports_for_router(self, context, router_id):
|
||||
"""Return all existing snat_router_interface ports."""
|
||||
qry = context.session.query(l3_models.RouterPort)
|
||||
qry = qry.filter_by(
|
||||
objs = l3_obj.RouterPort.get_objects(
|
||||
context,
|
||||
router_id=router_id,
|
||||
port_type=const.DEVICE_OWNER_ROUTER_SNAT
|
||||
)
|
||||
port_type=const.DEVICE_OWNER_ROUTER_SNAT)
|
||||
|
||||
ports = [self.l3plugin._core_plugin._make_port_dict(rp.port)
|
||||
for rp in qry]
|
||||
# TODO(lujinluo): Need Port as synthetic field
|
||||
ports = [self.l3plugin._core_plugin._make_port_dict(rp.db_obj.port)
|
||||
for rp in objs]
|
||||
return ports
|
||||
|
||||
def _add_csnat_router_interface_port(
|
||||
@ -194,13 +195,12 @@ class DVRResourceOperationHandler(object):
|
||||
msg = _("Unable to create the SNAT Interface Port")
|
||||
raise n_exc.BadRequest(resource='router', msg=msg)
|
||||
|
||||
with context.session.begin(subtransactions=True):
|
||||
router_port = l3_models.RouterPort(
|
||||
port_id=snat_port['id'],
|
||||
router_id=router.id,
|
||||
port_type=const.DEVICE_OWNER_ROUTER_SNAT
|
||||
)
|
||||
context.session.add(router_port)
|
||||
l3_obj.RouterPort(
|
||||
context,
|
||||
port_id=snat_port['id'],
|
||||
router_id=router.id,
|
||||
port_type=const.DEVICE_OWNER_ROUTER_SNAT
|
||||
).create()
|
||||
|
||||
if do_pop:
|
||||
return self.l3plugin._populate_mtu_and_subnets_for_ports(
|
||||
@ -566,15 +566,16 @@ class _DVRAgentInterfaceMixin(object):
|
||||
"""Query router interfaces that relate to list of router_ids."""
|
||||
if not router_ids:
|
||||
return []
|
||||
qry = context.session.query(l3_models.RouterPort)
|
||||
qry = qry.filter(
|
||||
l3_models.RouterPort.router_id.in_(router_ids),
|
||||
l3_models.RouterPort.port_type == const.DEVICE_OWNER_ROUTER_SNAT
|
||||
)
|
||||
objs = l3_obj.RouterPort.get_objects(
|
||||
context,
|
||||
router_id=router_ids,
|
||||
port_type=const.DEVICE_OWNER_ROUTER_SNAT)
|
||||
|
||||
interfaces = collections.defaultdict(list)
|
||||
for rp in qry:
|
||||
for rp in objs:
|
||||
# TODO(lujinluo): Need Port as synthetic field
|
||||
interfaces[rp.router_id].append(
|
||||
self._core_plugin._make_port_dict(rp.port))
|
||||
self._core_plugin._make_port_dict(rp.db_obj.port))
|
||||
LOG.debug("Return the SNAT ports: %s", interfaces)
|
||||
return interfaces
|
||||
|
||||
|
@ -44,11 +44,10 @@ from neutron.db.availability_zone import router as router_az_db
|
||||
from neutron.db import l3_dvr_db
|
||||
from neutron.db.l3_dvr_db import is_distributed_router
|
||||
from neutron.db.models import agent as agent_model
|
||||
from neutron.db.models import l3 as l3_models
|
||||
from neutron.db.models import l3ha as l3ha_model
|
||||
from neutron.extensions import l3
|
||||
from neutron.extensions import l3_ext_ha_mode as l3_ha
|
||||
from neutron.objects import router as l3_objs
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron.plugins.common import utils as p_utils
|
||||
|
||||
|
||||
@ -268,10 +267,11 @@ 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_models.RouterPort(
|
||||
port_id=port_id, router_id=router_id,
|
||||
port_type=constants.DEVICE_OWNER_ROUTER_HA_INTF)
|
||||
context.session.add(routerportbinding)
|
||||
l3_obj.RouterPort(
|
||||
context,
|
||||
port_id=port_id,
|
||||
router_id=router_id,
|
||||
port_type=constants.DEVICE_OWNER_ROUTER_HA_INTF).create()
|
||||
portbinding = l3ha_model.L3HARouterAgentPortBinding(
|
||||
port_id=port_id, router_id=router_id)
|
||||
context.session.add(portbinding)
|
||||
@ -722,7 +722,7 @@ def is_ha_router_port(context, device_owner, router_id):
|
||||
if device_owner == constants.DEVICE_OWNER_HA_REPLICATED_INT:
|
||||
return True
|
||||
elif device_owner == constants.DEVICE_OWNER_ROUTER_SNAT:
|
||||
return l3_objs.RouterExtraAttributes.objects_exist(
|
||||
return l3_obj.RouterExtraAttributes.objects_exist(
|
||||
context, router_id=router_id, ha=True)
|
||||
else:
|
||||
return False
|
||||
|
@ -21,6 +21,7 @@ from neutron.common import constants
|
||||
from neutron.common import utils
|
||||
from neutron.db import api as db_api
|
||||
from neutron.db.models import dns as dns_models
|
||||
from neutron.db.models import l3
|
||||
from neutron.db.models import securitygroup as sg_models
|
||||
from neutron.db import models_v2
|
||||
from neutron.objects import base
|
||||
@ -417,3 +418,14 @@ class Port(base.NeutronDbObject):
|
||||
|
||||
if _target_version < (1, 1):
|
||||
primitive.pop('data_plane_status', None)
|
||||
|
||||
@classmethod
|
||||
def get_ports_by_router(cls, context, router_id, owner, subnet):
|
||||
rport_qry = context.session.query(models_v2.Port).join(
|
||||
l3.RouterPort)
|
||||
ports = rport_qry.filter(
|
||||
l3.RouterPort.router_id == router_id,
|
||||
l3.RouterPort.port_type == owner,
|
||||
models_v2.Port.network_id == subnet['network_id']
|
||||
)
|
||||
return [cls._load_object(context, db_obj) for db_obj in ports.all()]
|
||||
|
@ -16,11 +16,13 @@ from oslo_versionedobjects import base as obj_base
|
||||
from oslo_versionedobjects import fields as obj_fields
|
||||
from sqlalchemy import func
|
||||
|
||||
from neutron.common import constants as n_const
|
||||
from neutron.common import utils
|
||||
from neutron.db.models import dvr as dvr_models
|
||||
from neutron.db.models import l3
|
||||
from neutron.db.models import l3_attrs
|
||||
from neutron.db.models import l3agent as rb_model
|
||||
from neutron.db import models_v2
|
||||
from neutron.extensions import availability_zone as az_ext
|
||||
from neutron.objects import base
|
||||
from neutron.objects import common_types
|
||||
@ -136,6 +138,19 @@ class RouterPort(base.NeutronDbObject):
|
||||
'port_type': obj_fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_router_ids_by_subnetpool(cls, context, subnetpool_id):
|
||||
query = context.session.query(l3.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,
|
||||
l3.RouterPort.port_type.in_(n_const.ROUTER_PORT_OWNERS))
|
||||
query = query.distinct()
|
||||
return [r[0] for r in query]
|
||||
|
||||
|
||||
@obj_base.VersionedObjectRegistry.register
|
||||
class DVRMacAddress(base.NeutronDbObject):
|
||||
|
@ -58,6 +58,7 @@ from neutron.db import rbac_db_models
|
||||
from neutron.db import standard_attr
|
||||
from neutron.ipam.drivers.neutrondb_ipam import driver as ipam_driver
|
||||
from neutron.ipam import exceptions as ipam_exc
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron.tests import base
|
||||
from neutron.tests import tools
|
||||
from neutron.tests.unit.api import test_extensions
|
||||
@ -4620,18 +4621,18 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
with db_api.context_manager.writer.using(ctx):
|
||||
router = l3_models.Router()
|
||||
ctx.session.add(router)
|
||||
with db_api.context_manager.writer.using(ctx):
|
||||
rp = l3_models.RouterPort(router_id=router.id,
|
||||
port_id=port['port']['id'])
|
||||
ctx.session.add(rp)
|
||||
rp = l3_obj.RouterPort(ctx, router_id=router.id,
|
||||
port_id=port['port']['id'])
|
||||
rp.create()
|
||||
|
||||
data = {'subnet': {'gateway_ip': '10.0.0.99'}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
s['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(409, res.status_int)
|
||||
# should work fine if it's not a router port
|
||||
rp.delete()
|
||||
with db_api.context_manager.writer.using(ctx):
|
||||
ctx.session.delete(rp)
|
||||
ctx.session.delete(router)
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
|
@ -39,13 +39,14 @@ from neutron._i18n import _
|
||||
from neutron.common import utils
|
||||
from neutron.db import agents_db
|
||||
from neutron.db import api as db_api
|
||||
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
|
||||
from neutron.extensions import availability_zone as az_ext
|
||||
from neutron.extensions import external_net
|
||||
from neutron.extensions import multiprovidernet as mpnet
|
||||
from neutron.objects import base as base_obj
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron.plugins.common import constants as p_const
|
||||
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
||||
from neutron.plugins.ml2 import config
|
||||
@ -1514,9 +1515,11 @@ class TestMl2DvrPortsV2(TestMl2PortsV2):
|
||||
|
||||
# lie to turn the port into an SNAT interface
|
||||
with db_api.context_manager.reader.using(self.context):
|
||||
rp = self.context.session.query(l3_models.RouterPort).filter_by(
|
||||
port_id=p['port_id']).first()
|
||||
rp.port_type = constants.DEVICE_OWNER_ROUTER_SNAT
|
||||
pager = base_obj.Pager(limit=1)
|
||||
rp = l3_obj.RouterPort.get_objects(
|
||||
self.context, _pager=pager, port_id=p['port_id'])
|
||||
rp[0].port_type = constants.DEVICE_OWNER_ROUTER_SNAT
|
||||
rp[0].update()
|
||||
|
||||
# take the port away before csnat gets a chance to delete it
|
||||
# to simulate a concurrent delete
|
||||
|
Loading…
x
Reference in New Issue
Block a user