Add support for provisioning L2 connectivity for L3 GW ports
Change-Id: I2a0eab2bcb087f206252b3d8e5ea095187d1a07echanges/86/881686/3
parent
95bde30e4f
commit
cec3251ee7
|
@ -271,7 +271,8 @@ def get_router_instances(instance_id=None):
|
|||
"""Returns filtered list of routers that may be relevant on CVX"""
|
||||
return get_instances(device_owners=[n_const.DEVICE_OWNER_DVR_INTERFACE,
|
||||
n_const.DEVICE_OWNER_ROUTER_HA_INTF,
|
||||
n_const.DEVICE_OWNER_ROUTER_INTF],
|
||||
n_const.DEVICE_OWNER_ROUTER_INTF,
|
||||
n_const.DEVICE_OWNER_ROUTER_GW],
|
||||
instance_id=instance_id)
|
||||
|
||||
|
||||
|
@ -314,7 +315,8 @@ def get_router_ports(port_id=None):
|
|||
"""Returns filtered list of routers that may be relevant on CVX"""
|
||||
return get_ports(device_owners=[n_const.DEVICE_OWNER_DVR_INTERFACE,
|
||||
n_const.DEVICE_OWNER_ROUTER_HA_INTF,
|
||||
n_const.DEVICE_OWNER_ROUTER_INTF],
|
||||
n_const.DEVICE_OWNER_ROUTER_INTF,
|
||||
n_const.DEVICE_OWNER_ROUTER_GW],
|
||||
port_id=port_id)
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ SUPPORTED_DEVICE_OWNERS = [
|
|||
n_const.DEVICE_OWNER_DVR_INTERFACE,
|
||||
n_const.DEVICE_OWNER_ROUTER_HA_INTF,
|
||||
n_const.DEVICE_OWNER_ROUTER_INTF,
|
||||
n_const.DEVICE_OWNER_ROUTER_GW,
|
||||
t_const.TRUNK_SUBPORT_OWNER]
|
||||
|
||||
|
||||
|
|
|
@ -336,17 +336,6 @@ class Dhcps(AristaResourcesBase):
|
|||
|
||||
class Routers(AristaResourcesBase):
|
||||
|
||||
def set_router_host_id(device_owner, resource):
|
||||
if device_owner == n_const.DEVICE_OWNER_ROUTER_HA_INTF:
|
||||
return 'HA Router'
|
||||
|
||||
if device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
|
||||
return 'distributed'
|
||||
|
||||
if device_owner == n_const.DEVICE_OWNER_ROUTER_INTF:
|
||||
portbinding = getattr(resource, 'PortBinding')
|
||||
return utils.hostname(portbinding.host) if portbinding else ''
|
||||
|
||||
def modify_blank_project_id(project_id, resource):
|
||||
if len(project_id) == 0:
|
||||
l3ha_router = getattr(resource, 'Router')
|
||||
|
@ -357,7 +346,7 @@ class Routers(AristaResourcesBase):
|
|||
formatter = [AttributeFormatter('device_id', 'id',
|
||||
submodel='Port'),
|
||||
AttributeFormatter('device_owner', 'hostId',
|
||||
set_router_host_id,
|
||||
lambda *args: '(see router ports)',
|
||||
submodel='Port'),
|
||||
AttributeFormatter('project_id', 'tenantId',
|
||||
modify_blank_project_id,
|
||||
|
|
|
@ -166,6 +166,7 @@ class AristaDriver(driver_api.MechanismDriver):
|
|||
n_const.DEVICE_OWNER_DVR_INTERFACE: a_const.ROUTER_RESOURCE,
|
||||
n_const.DEVICE_OWNER_ROUTER_INTF: a_const.ROUTER_RESOURCE,
|
||||
n_const.DEVICE_OWNER_ROUTER_HA_INTF: a_const.ROUTER_RESOURCE,
|
||||
n_const.DEVICE_OWNER_ROUTER_GW: a_const.ROUTER_RESOURCE,
|
||||
trunk_consts.TRUNK_SUBPORT_OWNER: a_const.VM_RESOURCE}
|
||||
if port['device_owner'] in owner_to_type.keys():
|
||||
return owner_to_type[port['device_owner']]
|
||||
|
|
|
@ -21,6 +21,7 @@ from eventlet import queue
|
|||
import mock
|
||||
from pstats import Stats
|
||||
|
||||
from neutron_lib.api.definitions import l3 as l3_const
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib import constants as n_const
|
||||
import neutron_lib.context
|
||||
|
@ -425,14 +426,18 @@ class L3HARouterTestFramework(MechTestBase):
|
|||
super(L3HARouterTestFramework, self).setUp()
|
||||
self.l3_plugin = directory.get_plugin(p_const.L3)
|
||||
self.l3_rpc_cb = l3_rpc.L3RpcCallback()
|
||||
self.ext_net = None
|
||||
|
||||
def create_router(self, ha=False):
|
||||
router = self.l3_plugin.create_router(
|
||||
self.context, {'router': {'name': 'router',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': self._tenant_id,
|
||||
'ha': ha,
|
||||
'distributed': False}})
|
||||
def create_router(self, ha=False, ext_net=None):
|
||||
router_dict = {'router': {'name': 'router',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': self._tenant_id,
|
||||
'ha': ha,
|
||||
'distributed': False}}
|
||||
if ext_net:
|
||||
router_dict['router'][l3_const.EXTERNAL_GW_INFO] = {'network_id':
|
||||
ext_net['id']}
|
||||
router = self.l3_plugin.create_router(self.context, router_dict)
|
||||
self.l3_plugin.schedule_router(self.context, router['id'])
|
||||
for host in self.l3_agents:
|
||||
self.sync_routers(router['id'], host['host'])
|
||||
|
@ -503,7 +508,7 @@ class L3HARouterTestFramework(MechTestBase):
|
|||
|
||||
def resource_created():
|
||||
cvx_data = list(self.cvx.endpoint_data[endpoint].values())
|
||||
expected_data = {'hostId': host,
|
||||
expected_data = {'hostId': '(see router ports)',
|
||||
'tenantId': router['project_id'],
|
||||
'id': router['id']}
|
||||
return cvx_data and cvx_data[0] == expected_data
|
||||
|
@ -514,7 +519,7 @@ class L3HARouterTestFramework(MechTestBase):
|
|||
|
||||
def resource_created():
|
||||
cvx_data = list(self.cvx.endpoint_data[endpoint].values())
|
||||
expected_data = {'hostId': 'HA Router',
|
||||
expected_data = {'hostId': '(see router ports)',
|
||||
'tenantId': router['project_id'],
|
||||
'id': router['id']}
|
||||
return cvx_data and cvx_data[0] == expected_data
|
||||
|
|
|
@ -580,23 +580,23 @@ class AristaRouterTest(AristaInstancesTestBase):
|
|||
legacy_id_base = n_const.DEVICE_OWNER_ROUTER_INTF + 'normal'
|
||||
expect_created = {'%s1' % id_base:
|
||||
{'tenantId': 't1',
|
||||
'hostId': 'distributed',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s1' % id_base},
|
||||
'%s2' % id_base:
|
||||
{'tenantId': 't2',
|
||||
'hostId': 'distributed',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s2' % id_base},
|
||||
'%s' % ha_id_base:
|
||||
{'tenantId': 'ha-router-project',
|
||||
'hostId': 'HA Router',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s' % ha_id_base},
|
||||
'%s1' % legacy_id_base:
|
||||
{'tenantId': 't1',
|
||||
'hostId': 'host1',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s1' % legacy_id_base},
|
||||
'%s2' % legacy_id_base:
|
||||
{'tenantId': 't2',
|
||||
'hostId': 'host2',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s2' % legacy_id_base}}
|
||||
self.run_scenario(expect_created)
|
||||
|
||||
|
@ -607,15 +607,15 @@ class AristaRouterTest(AristaInstancesTestBase):
|
|||
ha_id_base = n_const.DEVICE_OWNER_ROUTER_HA_INTF + 'normal'
|
||||
expect_created = {'%s2' % id_base:
|
||||
{'tenantId': 't2',
|
||||
'hostId': 'distributed',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s2' % id_base},
|
||||
'%s2' % legacy_id_base:
|
||||
{'id': '%s2' % legacy_id_base,
|
||||
'tenantId': 't2',
|
||||
'hostId': 'host2'},
|
||||
'hostId': '(see router ports)'},
|
||||
'%s' % ha_id_base:
|
||||
{'tenantId': 'ha-router-project',
|
||||
'hostId': 'HA Router',
|
||||
'hostId': '(see router ports)',
|
||||
'id': '%s' % ha_id_base}}
|
||||
self.run_scenario(expect_created)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import mock
|
||||
|
||||
from neutron.tests.common import helpers
|
||||
from neutron_lib.api.definitions import external_net as extnet_const
|
||||
from neutron_lib import constants as n_const
|
||||
from oslo_config import cfg
|
||||
|
||||
|
@ -1325,41 +1326,57 @@ class ManagedPhysnetNoHpbTestCase(ml2_test_base.MechTestBase):
|
|||
class BasicL3HARouterTests(object):
|
||||
|
||||
def test_create_delete_router(self):
|
||||
ha_router_ports = []
|
||||
router = self.create_router(ha=True)
|
||||
router_ports = []
|
||||
ext_net = None
|
||||
if self.ext_net:
|
||||
ext_net, ext_net_ctx = self.create_network(self.ext_net)
|
||||
router = self.create_router(ha=True, ext_net=ext_net)
|
||||
for l3_agent in self.l3_agents:
|
||||
port = self.update_routers_states(router['id'], l3_agent)
|
||||
ha_router_ports.append(port)
|
||||
router_ports.append(port)
|
||||
ha_network_id = self.get_ha_network(router)
|
||||
ha_segments = self.get_network_segments(ha_network_id)
|
||||
segments = self.get_network_segments(ha_network_id)
|
||||
if self.ext_net:
|
||||
segments.extend(self.get_network_segments(ext_net['id']))
|
||||
router_ports.append(self.plugin.get_port(self.context,
|
||||
router['gw_port_id']))
|
||||
self.assertTenantCreated(router['project_id'])
|
||||
self.assertL3HANetworkCreated(router, ha_network_id)
|
||||
self.assertRouterCreated(router['id'])
|
||||
self.assertL3HARouterCreated(router)
|
||||
for port in ha_router_ports:
|
||||
self.assertL3HAPortCreated(router, port['id'])
|
||||
for port in router_ports:
|
||||
if port['device_owner'] != n_const.DEVICE_OWNER_ROUTER_GW:
|
||||
self.assertL3HAPortCreated(router, port['id'])
|
||||
else:
|
||||
self.assertRouterPortCreated(port['id'])
|
||||
self.assertPortBindingCreated((port['id'],
|
||||
port[portbindings.HOST_ID]))
|
||||
self.assertSegmentsCreated(ha_segments)
|
||||
self.assertSegmentsCreated(segments)
|
||||
|
||||
# Delete the router
|
||||
self.delete_router(router['id'])
|
||||
self.assertRouterPortsDeleted([p['id'] for p in ha_router_ports])
|
||||
if self.ext_net:
|
||||
self.delete_network(ext_net['id'])
|
||||
self.assertRouterPortsDeleted([p['id'] for p in router_ports])
|
||||
self.assertRouterDeleted(router['id'])
|
||||
self.assertSegmentsDeleted(ha_segments)
|
||||
self.assertSegmentsDeleted(segments)
|
||||
self.assertNetworkDeleted(ha_network_id)
|
||||
self.assertTenantDeleted(router['project_id'])
|
||||
for port in ha_router_ports:
|
||||
for port in router_ports:
|
||||
self.assertPortBindingDeleted((port['id'],
|
||||
port[portbindings.HOST_ID]))
|
||||
|
||||
|
||||
class BasicRouterTests(object):
|
||||
|
||||
def test_create_delete_router(self):
|
||||
router = self.create_router()
|
||||
net_list = []
|
||||
port_list = []
|
||||
segment_list = []
|
||||
ext_net = None
|
||||
if self.ext_net:
|
||||
ext_net, ext_net_ctx = self.create_network(self.ext_net)
|
||||
router = self.create_router(ext_net=ext_net)
|
||||
for net in self.net_dict:
|
||||
network, net_ctx = self.create_network(net)
|
||||
net_list.append((network, net_ctx))
|
||||
|
@ -1371,6 +1388,11 @@ class BasicRouterTests(object):
|
|||
port = self.get_legacy_router_port(intf['port_id'])
|
||||
self.assertNotEqual(len(port), 0)
|
||||
port_list.append(port)
|
||||
if self.ext_net:
|
||||
net_list.append((ext_net, ext_net_ctx))
|
||||
port = self.get_legacy_router_port(router['gw_port_id'])
|
||||
self.assertNotEqual(len(port), 0)
|
||||
port_list.append(port)
|
||||
self.assertLegacyRouterCreated(router, self.l3_agent1['host'])
|
||||
for network, _ in net_list:
|
||||
self.assertNetworkCreated(network['id'])
|
||||
|
@ -1396,11 +1418,23 @@ class BasicRouterTests(object):
|
|||
network, net_ctx = net_list[1]
|
||||
interface_info = {'subnet_id': net_ctx.current['subnets'][0]}
|
||||
intf = self.remove_router_interface(router, interface_info)
|
||||
self.assertRouterDeleted(router['id'])
|
||||
# If there's still an external gateway port, the router will
|
||||
# still exist on CVX. Otherwise, it will be deleted
|
||||
if not self.ext_net:
|
||||
self.assertRouterDeleted(router['id'])
|
||||
else:
|
||||
self.assertRouterCreated(router['id'])
|
||||
self.assertRouterPortDeleted(intf['port_id'])
|
||||
self.assertPortBindingDeleted((intf['port_id'],
|
||||
port[portbindings.HOST_ID]))
|
||||
|
||||
# Delete router to delete external gateway port
|
||||
self.delete_router(router['id'])
|
||||
self.assertRouterDeleted(router['id'])
|
||||
self.assertRouterPortDeleted(router['gw_port_id'])
|
||||
self.assertPortBindingDeleted((router['gw_port_id'],
|
||||
port[portbindings.HOST_ID]))
|
||||
|
||||
for network, _ in net_list:
|
||||
self.delete_network(network['id'])
|
||||
self.assertNetworkDeleted(network['id'])
|
||||
|
@ -1483,3 +1517,47 @@ class BasicHpbRouterTestCases(ml2_test_base.L3HARouterTestFramework,
|
|||
for r in range(1, 3)]
|
||||
self.total_segments = 4
|
||||
self.l3_agents = [self.l3_agent1]
|
||||
|
||||
|
||||
class RouterGatewayTestCases(ml2_test_base.L3HARouterTestFramework,
|
||||
BasicRouterTests):
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override('tenant_network_types', 'vlan', 'ml2')
|
||||
super(RouterGatewayTestCases, self).setUp()
|
||||
self.l3_agent1 = self._register_l3_agent(host=self.host1)
|
||||
self.ext_net = {'network': {'name': 'ext_net',
|
||||
'tenant_id': self._tenant_id,
|
||||
'admin_state_up': True,
|
||||
'shared': False,
|
||||
'provider:physical_network': self.physnet,
|
||||
'provider:network_type': 'vlan',
|
||||
extnet_const.EXTERNAL: True}}
|
||||
self.net_dict = [
|
||||
{'network': {'name': 'net-%d' % r,
|
||||
'tenant_id': self._tenant_id,
|
||||
'admin_state_up': True,
|
||||
'shared': False,
|
||||
'provider:physical_network': self.physnet,
|
||||
'provider:network_type': 'vlan'}}
|
||||
for r in range(1, 3)]
|
||||
self.total_segments = 3
|
||||
self.l3_agents = [self.l3_agent1]
|
||||
|
||||
|
||||
class RouterGatewayL3HARouterTestCases(ml2_test_base.L3HARouterTestFramework,
|
||||
BasicL3HARouterTests):
|
||||
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override('tenant_network_types', 'vlan', 'ml2')
|
||||
super(RouterGatewayL3HARouterTestCases, self).setUp()
|
||||
cfg.CONF.set_override('max_l3_agents_per_router', 2)
|
||||
self.l3_agent1 = self._register_l3_agent(host=self.host1)
|
||||
self.l3_agent2 = self._register_l3_agent(host=self.host2)
|
||||
self.l3_agents = [self.l3_agent1, self.l3_agent2]
|
||||
self.ext_net = {'network': {'name': 'ext_net',
|
||||
'tenant_id': self._tenant_id,
|
||||
'admin_state_up': True,
|
||||
'shared': False,
|
||||
'provider:physical_network': self.physnet,
|
||||
'provider:network_type': 'vlan',
|
||||
extnet_const.EXTERNAL: True}}
|
||||
|
|
Loading…
Reference in New Issue