Adds support for multiple subnets per external network

With this patch neutron routers hosted in ASR1k devices can now
be attached to external networks that have multiple subnets.

The global routers in the ASR1k will always be connected to
*all* subnets of an external network regardless if the tenant
gateway routers are connected to all those subnets.

The patch also adds UTs for the new capability.

Addresses: DE3191, DE3092, DE2865, DE2877, DE2882, DE2886

Change-Id: I65775b58361bcfee9ea3d36ff87b9981ba750601
Closes-Bug: #1660988
This commit is contained in:
Bob Melander 2017-01-24 12:36:41 +01:00
parent 6140a21494
commit 6e6e2025d5
28 changed files with 4319 additions and 405 deletions

View File

@ -72,8 +72,6 @@ else:
setattr(constants, 'L3', getattr(svc_constants, 'L3_ROUTER_NAT'))
core_opts = base_config.core_opts
#extensions = extensions
#model_base = model_base
# Bring in the union of all constants in neutron.common.constants
# and neutron_lib.constants. Handle any duplicates by using the

View File

@ -524,12 +524,97 @@ def _mock_stuff():
pingable_patcher.start()
# NOTE(bobmel): call mock_ncclient() in main() of cfg_agent.py to run config
# agent with a fake ncclient. That mocked mode of running the config agent is
# useful for end-2-end-like debugging without actual backend hosting devices.
def mock_ncclient():
import mock
from ncclient.transport import errors as ncc_exc
from networking_cisco.plugins.cisco.common import (cisco_ios_xe_simulator
as cisco_ios_xe)
import os
def _fake_connect(host, port, username, password, device_params, timeout):
sim = cisco_ios_xe.CiscoIOSXESimulator(
'', host, "255.255.255.0", port, username, password,
device_params, "GigabitEthernet0", timeout)
connection_mock = mock.MagicMock()
connection_mock.edit_config.side_effect = _get_fake_edit_config(sim)
connection_mock.get_config.side_effect = (
_get_fake_get_config(sim))
return connection_mock
def _get_fake_edit_config(simulator):
def edit_config(config, format='xml', target='candidate',
default_operation=None, test_option=None,
error_option=None):
if not _fake_is_pingable(rc_emul.host_ip):
raise ncc_exc.SSHError('SSH error')
rc_emul.edit_config(config)
print(rc_emul.get_config())
return ok_xml_obj
ok_xml_obj = mock.MagicMock()
ok_xml_obj.xml = "<ok />"
rc_emul = simulator
return edit_config
def _get_fake_get_config(simulator):
def get_running_config(source):
if not _fake_is_pingable(rc_emul.host_ip):
raise ncc_exc.SSHError('SSH error')
head = ('<?xml version="1.0" encoding="UTF-8"?><rpc-reply '
'message-id="urn:uuid:ec8bab72-a500-11e5-a92f'
'-74a2e6d55908" xmlns="urn:ietf:params:xml:ns:netconf:'
'base:1.0"><data><cli-config-data-block>!')
tail = '</cli-config-data-block></data></rpc-reply>'
raw_rc = rc_emul.get_config()
return cisco_ios_xe.FakeRunningConfig(head + raw_rc + tail)
rc_emul = simulator
return get_running_config
def _fake_is_pingable(ip):
# if a file with a certain name (derived from the 'ip' argument):
#
# /opt/stack/data/neutron/DEAD__10_0_5_8 (ip = 10.0.5.8)
#
# exists then the (faked) hosting device with that IP address
# will appear to NOT respond to pings
path = '/opt/stack/data/neutron'
indicator_filename = path + '/DEAD_' + str(ip).replace('.', '_')
return not os.path.isfile(indicator_filename)
targets = ['networking_cisco.plugins.cisco.cfg_agent.device_drivers.'
'csr1kv.csr1kv_routing_driver.manager',
'networking_cisco.plugins.cisco.cfg_agent.device_drivers.'
'csr1kv.iosxe_routing_driver.manager']
ncc_patchers = []
ncclient_mgr_mock = mock.MagicMock()
ncclient_mgr_mock.connect.side_effect = _fake_connect
for target in targets:
patcher = mock.patch(target, ncclient_mgr_mock)
patcher.start()
ncc_patchers.append(patcher)
is_pingable_mock = mock.MagicMock()
is_pingable_mock.side_effect = _fake_is_pingable
pingable_patcher = mock.patch(
'networking_cisco.plugins.cisco.cfg_agent.device_status._is_pingable',
is_pingable_mock)
pingable_patcher.start()
def main(manager='networking_cisco.plugins.cisco.cfg_agent.'
'cfg_agent.CiscoCfgAgentWithStateReport'):
# NOTE(bobmel): call _mock_stuff() to run config agent with fake ncclient
# This mocked mode of running the config agent is useful for end-2-end-like
# debugging without actual backend hosting devices.
#_mock_stuff()
#mock_ncclient()
conf = cfg.CONF
conf.register_opts(OPTS, "cfg_agent")
config.register_agent_state_opts_helper(conf)

View File

@ -34,6 +34,8 @@ LOG = logging.getLogger(__name__)
ROUTER_ROLE_ATTR = routerrole.ROUTER_ROLE_ATTR
ROUTER_ROLE_HA_REDUNDANCY = cisco_constants.ROUTER_ROLE_HA_REDUNDANCY
NROUTER_REGEX = "nrouter-(\w{6,6})"
NROUTER_MULTI_REGION_REGEX = "nrouter-(\w{6,6})-(\w{1,7})"
@ -44,12 +46,12 @@ VRF_REGEX_NEW = "vrf definition " + NROUTER_REGEX
VRF_MULTI_REGION_REGEX = "ip vrf " + NROUTER_MULTI_REGION_REGEX
VRF_MULTI_REGION_REGEX_NEW = "vrf definition " + NROUTER_MULTI_REGION_REGEX
#INTF_NAME_REGEX = "(PortChannel\d+|\d+Ethernet\d+\/d+\/d+)"
INTF_REGEX = "interface \S+\.(\d+)"
INTF_DESC_REGEX = "\s*description OPENSTACK_NEUTRON_INTF"
INTF_DESC_MULTI_REGION_REGEX = ("\s*description"
" OPENSTACK_NEUTRON_(\w{1,7})_INTF")
INTF_DESC_REGEX = (
"\s*description OPENSTACK_NEUTRON_INTF|OPENSTACK_NEUTRON_EXTERNAL_INTF")
INTF_DESC_MULTI_REGION_REGEX = (
"\s*description OPENSTACK_NEUTRON_(\w{1,7})_INTF|"
"OPENSTACK_NEUTRON_EXTERNAL_(\w{1,7})_INTF")
VRF_EXT_INTF_REGEX = "\s*ip vrf forwarding .*"
VRF_INTF_REGEX = "\s*ip vrf forwarding " + NROUTER_REGEX
VRF_INTF_MULTI_REGION_REGEX = ("\s*ip vrf forwarding " +
@ -219,9 +221,13 @@ class ConfigSyncer(object):
interface_segment_dict[segment_id] = []
if segment_id not in segment_nat_dict:
segment_nat_dict[segment_id] = False
interface['is_external'] = (
router[ROUTER_ROLE_ATTR] ==
cisco_constants.ROUTER_ROLE_GLOBAL)
if (router[ROUTER_ROLE_ATTR] ==
cisco_constants.ROUTER_ROLE_GLOBAL):
interface['is_external'] = True
if (segment_id not in self.segment_gw_dict):
self.segment_gw_dict[segment_id] = [interface]
else:
interface['is_external'] = False
interface_segment_dict[segment_id].append(interface)
# Mark which segments have NAT enabled
@ -235,16 +241,16 @@ class ConfigSyncer(object):
cisco_constants.ROUTER_ROLE_GLOBAL):
if (gw_segment_id not in self.segment_gw_dict):
self.segment_gw_dict[gw_segment_id] = gw_port
self.segment_gw_dict[gw_segment_id] = [gw_port]
if '_interfaces' in router.keys():
interfaces = router['_interfaces']
for intf in interfaces:
if intf['device_owner'] == \
bc.constants.DEVICE_OWNER_ROUTER_INTF:
if (intf['device_owner'] ==
bc.constants.DEVICE_OWNER_ROUTER_INTF):
if is_port_v6(intf) is not True:
intf_segment_id = \
intf['hosting_info']['segmentation_id']
intf_segment_id = (
intf['hosting_info']['segmentation_id'])
segment_nat_dict[gw_segment_id] = True
segment_nat_dict[intf_segment_id] = True
@ -261,7 +267,6 @@ class ConfigSyncer(object):
LOG.info(_LI("neutron router db records"))
for router_id, router in six.iteritems(router_id_dict):
#LOG.info("ROUTER ID: %s DATA: %s\n\n" % (router_id, router))
LOG.info(_LI("ROUTER_ID: %s"), router_id)
LOG.info(_LI("\n"))
@ -451,17 +456,18 @@ class ConfigSyncer(object):
continue
# Check IPs and netmask
# TODO(sridar) rework this to old model, further
# investigation needed and cleanup.
# pool_info = router['gw_port']['nat_pool_info']
# pool_ip = pool_info['pool_ip']
# pool_net = netaddr.IPNetwork(pool_info['pool_cidr'])
pool_ip = str(router['gw_port']['fixed_ips'][0]['ip_address'])
# pool_net = router['gw_port']['subnets'][0]['cidr']
pool_net = netaddr.IPNetwork(
router['gw_port']['subnets'][0]['cidr'])
if router.get(ROUTER_ROLE_ATTR) == ROUTER_ROLE_HA_REDUNDANCY:
the_port = router['gw_port'][ha.HA_INFO]['ha_port']
else:
the_port = router['gw_port']
found = False
for i in range(len(the_port['fixed_ips'])):
pool_ip = str(the_port['fixed_ips'][i]['ip_address'])
if start_ip == pool_ip:
found = True
break
if start_ip != pool_ip:
if found is False:
LOG.info(_LI("start IP %(start_ip)s for "
"pool does not match %(pool_ip)s, deleting") %
{'start_ip': start_ip, 'pool_ip': pool_ip})
@ -473,6 +479,7 @@ class ConfigSyncer(object):
delete_pool_list.append(pool.text)
continue
pool_net = netaddr.IPNetwork(the_port['subnets'][i]['cidr'])
if netmask != str(pool_net.netmask):
LOG.info(
_LI("netmask for pool does not match, netmask:%(netmask)s,"
@ -557,8 +564,17 @@ class ConfigSyncer(object):
continue
# Check that nexthop matches gw_ip of external network
gw_ip = gw_port['subnets'][0]['gateway_ip']
if next_hop.lower() != gw_ip.lower():
if router.get(ROUTER_ROLE_ATTR) == ROUTER_ROLE_HA_REDUNDANCY:
the_port = router['gw_port'][ha.HA_INFO]['ha_port']
else:
the_port = router['gw_port']
found = False
for i in range(len(the_port['subnets'])):
gw_ip = the_port['subnets'][i]['gateway_ip']
if next_hop.lower() == gw_ip.lower():
found = True
break
if found is False:
LOG.info(_LI("route has incorrect next-hop, deleting"))
delete_route_list.append(route.text)
continue
@ -644,8 +660,6 @@ class ConfigSyncer(object):
# Check that hsrp group name is correct
gw_port = router['gw_port']
#gw_net_id = gw_port['network_id']
#gw_hsrp_num = self._get_hsrp_grp_num_from_net_id(gw_net_id)
gw_hsrp_num = int(gw_port[ha.HA_INFO]['group'])
gw_segment_id = int(gw_port['hosting_info']['segmentation_id'])
if segment_id != gw_segment_id:
@ -889,14 +903,18 @@ class ConfigSyncer(object):
checks running-cfg derived ip_addr and netmask against neutron-db
gw_port
"""
if (gw_port is not None):
target_ip = gw_port['fixed_ips'][0]['ip_address']
target_net = netaddr.IPNetwork(gw_port['subnets'][0]['cidr'])
if (ip_addr != target_ip):
if gw_port is not None:
found = False
for i in range(len(gw_port['fixed_ips'])):
target_ip = gw_port['fixed_ips'][i]['ip_address']
if ip_addr == target_ip:
found = True
break
if found is False:
LOG.info(_LI("Subintf real IP is incorrect, deleting"))
return False
if (netmask != str(target_net.netmask)):
target_net = netaddr.IPNetwork(gw_port['subnets'][i]['cidr'])
if netmask != str(target_net.netmask):
LOG.info(_LI("Subintf has incorrect netmask, deleting"))
return False
@ -904,7 +922,7 @@ class ConfigSyncer(object):
return False
def subintf_real_ip_check(self, intf_list, is_external, ip_addr, netmask):
def subintf_real_ip_check(self, intf_list, ip_addr, netmask):
for target_intf in intf_list:
target_ip = target_intf['fixed_ips'][0]['ip_address']
@ -972,18 +990,16 @@ class ConfigSyncer(object):
def gw_port_hsrp_ip_check(self, gw_port, ip_addr):
if (gw_port is not None):
if gw_port is not None:
ha_port = gw_port[ha.HA_INFO]['ha_port']
target_ip = ha_port['fixed_ips'][0]['ip_address']
LOG.info(_LI("target_ip: %(target_ip)s, actual_ip: %(ip_addr)s") %
{'target_ip': target_ip,
'ip_addr': ip_addr})
if ip_addr != target_ip:
LOG.info(_LI("HSRP VIP mismatch on gw_port, deleting"))
return False
else:
return True
for fixed_ip in ha_port['fixed_ips']:
target_ip = fixed_ip['ip_address']
LOG.info(_LI("target_ip: %(target_ip)s, "
"actual_ip: %(ip_addr)s") %
{'target_ip': target_ip, 'ip_addr': ip_addr})
if ip_addr == target_ip:
return True
LOG.info(_LI("HSRP VIP mismatch on gw_port, deleting"))
return False
def subintf_hsrp_ip_check(self, intf_list, is_external, ip_addr):
@ -1043,19 +1059,29 @@ class ConfigSyncer(object):
def clean_interfaces_ipv4_hsrp_check(self, intf, intf_db_dict):
# Check HSRP VIP
hsrp_vip_cfg_list = intf.re_search_children(HSRP_V4_VIP_REGEX)
if len(hsrp_vip_cfg_list) < 1:
num_vips = len(hsrp_vip_cfg_list)
num_vips_db = len(intf_db_dict[intf.segment_id][0]['fixed_ips'])
if num_vips < 1:
LOG.info(_LI("Interface is missing HSRP VIP, deleting"))
return False
hsrp_vip_cfg = hsrp_vip_cfg_list[0]
match_obj = re.match(HSRP_V4_VIP_REGEX, hsrp_vip_cfg.text)
hsrp_vip_grp_num, hsrp_vip = match_obj.group(1, 2)
elif num_vips != num_vips_db:
LOG.info(_LI("Subintf has wrong number of HSRP VIP addresses ("
"should have %(n_v)d, but has %(n_v_d)d), deleting"),
{'n_v': num_vips, 'n_v_d': num_vips_db})
return False
if intf.is_external:
return self.gw_port_hsrp_ip_check(
intf_db_dict[intf.segment_id],
hsrp_vip)
for hsrp_vip_cfg in hsrp_vip_cfg_list:
match_obj = re.match(HSRP_V4_VIP_REGEX, hsrp_vip_cfg.text)
hsrp_vip_grp_num, hsrp_vip = match_obj.group(1, 2)
if self.gw_port_hsrp_ip_check(intf_db_dict[intf.segment_id][0],
hsrp_vip) is False:
return False
return True
else:
hsrp_vip_cfg = hsrp_vip_cfg_list[0]
match_obj = re.match(HSRP_V4_VIP_REGEX, hsrp_vip_cfg.text)
hsrp_vip_grp_num, hsrp_vip = match_obj.group(1, 2)
return self.subintf_hsrp_ip_check(
intf_db_dict[intf.segment_id],
intf.is_external,
@ -1065,23 +1091,32 @@ class ConfigSyncer(object):
# Check that real IP address is correct
ipv4_addr = intf.re_search_children(INTF_V4_ADDR_REGEX)
if len(ipv4_addr) < 1:
num_addrs = len(ipv4_addr)
num_addrs_db = len(intf_db_dict[intf.segment_id][0]['fixed_ips'])
if num_addrs < 1:
LOG.info(_LI("Subintf has no IP address, deleting"))
return False
ipv4_addr_cfg = ipv4_addr[0]
match_obj = re.match(INTF_V4_ADDR_REGEX, ipv4_addr_cfg.text)
ip_addr, netmask = match_obj.group(1, 2)
elif num_addrs != num_addrs_db:
LOG.info(_LI("Subintf has wrong number of addresses (should have "
"%(n_a)d, but has %(n_a_d)d), deleting"), num_addrs,
num_addrs_db)
return False
if intf.is_external:
return self.subintf_real_ip_check_gw_port(
intf_db_dict[intf.segment_id],
ip_addr, netmask)
for ipv4_addr_cfg in ipv4_addr:
match_obj = re.match(INTF_V4_ADDR_REGEX, ipv4_addr_cfg.text)
ip_addr, netmask = match_obj.group(1, 2)
if (self.subintf_real_ip_check_gw_port(
intf_db_dict[intf.segment_id][0], ip_addr, netmask) is
False):
return False
return True
else:
ipv4_addr_cfg = ipv4_addr[0]
match_obj = re.match(INTF_V4_ADDR_REGEX, ipv4_addr_cfg.text)
ip_addr, netmask = match_obj.group(1, 2)
return self.subintf_real_ip_check(
intf_db_dict[intf.segment_id],
intf.is_external,
ip_addr, netmask)
intf_db_dict[intf.segment_id], ip_addr, netmask)
def clean_interfaces_ipv6_check(self, intf, intf_segment_dict):
# Check that real IP address is correct
@ -1188,11 +1223,10 @@ class ConfigSyncer(object):
# Is this an "external network" segment_id?
if intf.is_external:
db_intf = self.segment_gw_dict[intf.segment_id]
db_intf = self.segment_gw_dict[intf.segment_id][0]
else:
db_intf = intf_segment_dict[intf.segment_id][0]
# intf.is_external = db_intf['is_external']
intf.has_ipv6 = is_port_v6(db_intf)
# Check VRF config
@ -1251,8 +1285,6 @@ class ConfigSyncer(object):
pending_delete_list.append(intf)
continue
# self.existing_cfg_dict['interfaces'][intf.segment_id] = intf
correct_grp_num = int(db_intf[ha.HA_INFO]['group'])
if intf.is_external:
@ -1262,43 +1294,33 @@ class ConfigSyncer(object):
if intf.has_ipv6 is False:
if self.clean_interfaces_nat_check(intf,
segment_nat_dict) \
is False:
segment_nat_dict) is False:
pending_delete_list.append(intf)
continue
if self.clean_interfaces_ipv4_check(intf,
intf_db) \
is False:
if self.clean_interfaces_ipv4_check(intf, intf_db) is False:
pending_delete_list.append(intf)
continue
if self.clean_interfaces_ipv4_hsrp_check(intf,
intf_db) \
is False:
intf_db) is False:
pending_delete_list.append(intf)
continue
else:
if self.clean_interfaces_ipv6_check(intf, intf_db) \
is False:
if self.clean_interfaces_ipv6_check(intf, intf_db) is False:
pending_delete_list.append(intf)
continue
# Delete if there's any hsrp config with wrong group number
#del_hsrp_cmd = XML_CMD_TAG % (intf.text)
hsrp_cfg_list = intf.re_search_children(HSRP_REGEX)
needs_hsrp_delete = False
for hsrp_cfg in hsrp_cfg_list:
hsrp_num = int(hsrp_cfg.re_match(HSRP_REGEX, group=1))
if hsrp_num != correct_grp_num:
needs_hsrp_delete = True
#del_hsrp_cmd += XML_CMD_TAG % ("no %s" % (hsrp_cfg.text))
if needs_hsrp_delete:
LOG.info(_LI("Bad HSRP config for interface, deleting"))
pending_delete_list.append(intf)
continue
#confstr = XML_FREEFORM_SNIPPET % (del_hsrp_cmd)
#LOG.info("Deleting bad HSRP config: %s" % (confstr))
#rpc_obj = conn.edit_config(target='running', config=confstr)
self.existing_cfg_dict['interfaces'][intf.segment_id] = intf.text
@ -1307,7 +1329,6 @@ class ConfigSyncer(object):
del_cmd = XML_CMD_TAG % ("no %s" % (intf.text))
confstr = XML_FREEFORM_SNIPPET % (del_cmd)
LOG.info(_LI("Deleting %s"), (intf.text))
#LOG.info(confstr)
conn.edit_config(target='running', config=confstr)
LOG.debug("pending_delete_list (interfaces) = %s" %

View File

@ -74,7 +74,8 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
self._edit_running_config(conf_str, 'EMPTY_SNIPPET')
def internal_network_added(self, ri, port):
gw_ip = port['subnets'][0]['gateway_ip']
gw_ip = self._get_item(
port['subnets'], port['ip_info']['subnet_id'], 'id')['gateway_ip']
if self._is_port_v6(port):
LOG.debug("Adding IPv6 internal network port: %(port)s for router "
"%(r_id)s", {'port': port, 'r_id': ri.id})
@ -107,7 +108,9 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
if self._is_global_router(ri):
self._remove_sub_interface(ext_gw_port)
else:
ex_gw_ip = ext_gw_port['subnets'][0]['gateway_ip']
ex_gw_ip = self._get_item(
ext_gw_port['subnets'],
ext_gw_port['ip_info']['subnet_id'], 'id')['gateway_ip']
if (ex_gw_ip and
ext_gw_port['device_owner'] == DEVICE_OWNER_ROUTER_GW):
# Remove default route via this network's gateway ip
@ -216,26 +219,32 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
def _handle_external_gateway_added_global_router(self, ri, ext_gw_port):
# TODO(bobmel): Get the HA virtual IP correctly
# TODO(sridar):
# This seems to work fine. Keeping this todo until more testing.
# NOTE(sridar): This seems to work fine. Keeping this todo until
# more testing.
virtual_gw_port = ext_gw_port[ha.HA_INFO]['ha_port']
sub_itfc_ip = virtual_gw_port['fixed_ips'][0]['ip_address']
subnet_id = ext_gw_port['ip_info']['subnet_id']
sub_itfc_ip = self._get_item(virtual_gw_port['fixed_ips'],
subnet_id)['ip_address']
if self._is_port_v6(ext_gw_port):
LOG.debug("Adding IPv6 external network port: %(port)s for global "
"router %(r_id)s", {'port': ext_gw_port['id'],
'r_id': ri.id})
self._create_sub_interface_v6(ri, ext_gw_port, True, sub_itfc_ip)
else:
LOG.debug("Adding IPv4 external network port: %(port)s for global "
"router %(r_id)s", {'port': ext_gw_port['id'],
'r_id': ri.id})
LOG.debug("Adding IPv4 external network port: %(port)s on "
"subnet: (subnet)s for global router %(r_id)s",
{'port': ext_gw_port['id'], 'subnet': subnet_id,
'r_id': ri.id})
self._create_sub_interface(ri, ext_gw_port, True, sub_itfc_ip)
def _handle_external_gateway_added_normal_router(self, ri, ext_gw_port):
# Default routes are mapped to tenant router VRFs . Global Router
# is not aware of tenant routers with ext network assigned. Thus,
# default route must be handled per tenant router.
ex_gw_ip = ext_gw_port['subnets'][0]['gateway_ip']
ex_gw_ip = self._get_item(
ext_gw_port['subnets'],
ext_gw_port['ip_info']['subnet_id'], 'id')['gateway_ip']
sub_interface = self._get_interface_name_from_hosting_port(ext_gw_port)
vlan_id = self._get_interface_vlan_from_hosting_port(ext_gw_port)
if (self._fullsync and
@ -266,11 +275,17 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
LOG.info(_LI("Sub-interface already exists, skipping"))
return
vrf_name = self._get_vrf_name(ri)
net_mask = netaddr.IPNetwork(port['ip_cidr']).netmask
hsrp_ip = port['fixed_ips'][0]['ip_address']
net_mask = netaddr.IPNetwork(port['ip_info']['ip_cidr']).netmask
# get port's ip address for the subnet we're processing
hsrp_ip = self._get_item(port['fixed_ips'],
port['ip_info']['subnet_id'])['ip_address']
sub_interface = self._get_interface_name_from_hosting_port(port)
self._do_create_sub_interface(sub_interface, vlan, vrf_name, hsrp_ip,
net_mask, is_external)
if port['ip_info']['is_primary'] is True:
self._do_create_sub_interface(
sub_interface, vlan, vrf_name, hsrp_ip, net_mask, is_external)
else:
# this will only happen for global routers
self._do_set_secondary(sub_interface, hsrp_ip, net_mask)
# Always do HSRP
if ri.router.get(ha.ENABLED, False):
if port.get(ha.HA_INFO) is not None:
@ -281,6 +296,12 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
'port': port}
raise cfg_exc.HAParamsMissingException(**params)
def _do_set_secondary(self, sub_interface, ip, mask):
conf_str = (
asr1k_snippets.SET_SUBINTERFACE_SECONDARY_IP % (
sub_interface, ip, mask))
self._edit_running_config(conf_str, 'SET_SUBINTERFACE_SECONDARY_IP')
def _do_create_sub_interface(self, sub_interface, vlan_id, vrf_name, ip,
mask, is_external=False):
is_multi_region_enabled = cfg.CONF.multi_region.enable_multi_region
@ -329,41 +350,31 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
def _set_nat_pool(self, ri, gw_port, is_delete):
vrf_name = self._get_vrf_name(ri)
if ri.router.get(ROUTER_ROLE_ATTR) == ROUTER_ROLE_HA_REDUNDANCY:
pool_ip = gw_port[ha.HA_INFO]['ha_port']['fixed_ips'][0][
'ip_address']
pool_ip_prefix_len = gw_port['fixed_ips'][0]['prefixlen']
the_port = gw_port[ha.HA_INFO]['ha_port']
else:
pool_ip = gw_port['fixed_ips'][0]['ip_address']
pool_ip_prefix_len = gw_port['fixed_ips'][0]['prefixlen']
# TODO(sridar) reverting to old model, needs more investigation
# and cleanup
# pool_info = gw_port['nat_pool_info']
# pool_ip = pool_info['pool_ip']
the_port = gw_port
subnet_id = gw_port['ip_info']['subnet_id']
fixed_ip = self._get_item(the_port['fixed_ips'], subnet_id)
pool_ip = fixed_ip['ip_address']
pool_ip_prefix_len = fixed_ip['prefixlen']
#TODO(ebobmel) We need to modify the pool name generation if we
# will have multiple NAT pools per VRF
pool_name = "%s_nat_pool" % (vrf_name)
#pool_net = netaddr.IPNetwork(pool_info['pool_cidr'])
#pool_net = netaddr.IPNetwork(gw_port['ip_cidr'])
pool_net = "%s/%s" % (pool_ip, pool_ip_prefix_len)
pool_net = netaddr.IPNetwork(pool_net)
if self._fullsync and pool_ip in self._existing_cfg_dict['pools']:
LOG.info(_LI("Pool already exists, skipping"))
return
#LOG.debug("SET_NAT_POOL pool netmask: %s, gw_port %s" % (
# pool_net.netmask, gw_port))
try:
if is_delete:
conf_str = asr1k_snippets.DELETE_NAT_POOL % (
pool_name, pool_ip, pool_ip, pool_net.netmask)
#self._edit_running_config(conf_str, '%s DELETE_NAT_POOL' %
# self.target_asr['name'])
# TODO(update so that hosting device name is passed down)
self._edit_running_config(conf_str, 'DELETE_NAT_POOL')
else:
conf_str = asr1k_snippets.CREATE_NAT_POOL % (
pool_name, pool_ip, pool_ip, pool_net.netmask)
#self._edit_running_config(conf_str, '%s CREATE_NAT_POOL' %
# self.target_asr['name'])
# TODO(update so that hosting device name is passed down)
self._edit_running_config(conf_str, 'CREATE_NAT_POOL')
#except cfg_exc.CSR1kvConfigException as cse:
@ -376,7 +387,9 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
self._existing_cfg_dict['routes']):
LOG.debug("Default route already exists, skipping")
return
ext_gw_ip = ext_gw_port['subnets'][0]['gateway_ip']
ext_gw_ip = self._get_item(
ext_gw_port['subnets'],
ext_gw_port['ip_info']['subnet_id'], 'id')['gateway_ip']
if ext_gw_ip:
vrf_name = self._get_vrf_name(ri)
out_itfc = self._get_interface_name_from_hosting_port(ext_gw_port)
@ -385,7 +398,9 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
self._edit_running_config(conf_str, 'SET_DEFAULT_ROUTE_WITH_INTF')
def _remove_default_route(self, ri, ext_gw_port):
ext_gw_ip = ext_gw_port['subnets'][0]['gateway_ip']
ext_gw_ip = self._get_item(
ext_gw_port['subnets'],
ext_gw_port['ip_info']['subnet_id'], 'id')['gateway_ip']
if ext_gw_ip:
vrf_name = self._get_vrf_name(ri)
out_itfc = self._get_interface_name_from_hosting_port(ext_gw_port)
@ -405,29 +420,40 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
priority = ri.router[ha.DETAILS][ha.PRIORITY]
port_ha_info = port[ha.HA_INFO]
group = port_ha_info['group']
ip = port_ha_info['ha_port']['fixed_ips'][0]['ip_address']
subnet_id = port['ip_info']['subnet_id']
ip = self._get_item(port_ha_info['ha_port']['fixed_ips'],
subnet_id)['ip_address']
vlan = port['hosting_info']['segmentation_id']
if ip and group and priority:
vrf_name = self._get_vrf_name(ri)
is_primary = port['ip_info']['is_primary']
sub_interface = self._get_interface_name_from_hosting_port(port)
self._do_set_ha_hsrp(sub_interface, vrf_name,
priority, group, ip, vlan)
self._do_set_ha_hsrp(sub_interface, vrf_name, priority, group, ip,
vlan, is_primary)
def _do_set_ha_hsrp(self, sub_interface, vrf_name, priority, group,
ip, vlan):
conf_str = asr1k_snippets.SET_INTC_ASR_HSRP_EXTERNAL % (sub_interface,
group,
priority,
group, ip,
group, group,
group, vlan)
self._edit_running_config(conf_str, 'SET_INTC_ASR_HSRP_EXTERNAL')
ip, vlan, is_primary=True):
if is_primary is True:
conf_str = asr1k_snippets.SET_INTC_ASR_HSRP_EXTERNAL % (
sub_interface,
group,
priority,
group, ip,
group, group,
group, vlan)
self._edit_running_config(conf_str, 'SET_INTC_ASR_HSRP_EXTERNAL')
else:
conf_str = asr1k_snippets.SET_INTC_ASR_SECONDARY_HSRP_EXTERNAL % (
sub_interface,
group, ip)
self._edit_running_config(conf_str,
'SET_INTC_ASR_SECONDARY_HSRP_EXTERNAL')
def _create_sub_interface_v6(self, ri, port, is_external=False, gw_ip=""):
if self._v6_port_needs_config(port) is not True:
return
vrf_name = self._get_vrf_name(ri)
ip_cidr = port['ip_cidr']
ip_cidr = port['ip_info']['ip_cidr']
vlan = self._get_interface_vlan_from_hosting_port(port)
sub_interface = self._get_interface_name_from_hosting_port(port)
self._do_create_sub_interface_v6(sub_interface, vlan, vrf_name,
@ -486,6 +512,20 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
return False
return True
@staticmethod
def _get_item(list_containing_dicts_entries, attribute_value,
attribute_name='subnet_id'):
"""Searches a list of dicts and returns the first matching entry
The dict entry returned contains the attribute 'attribute_name' whose
value equals 'attribute_value'. If no such dict is found in the list
an empty dict is returned.
"""
for item in list_containing_dicts_entries:
if item.get(attribute_name) == attribute_value:
return item
return {}
@staticmethod
def _port_is_hsrp(port):
hsrp_types = [bc.constants.DEVICE_OWNER_ROUTER_HA_INTF]
@ -496,9 +536,11 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
return (ri.router.get(ROUTER_ROLE_ATTR) ==
cisco_constants.ROUTER_ROLE_GLOBAL)
@staticmethod
def _is_port_v6(port):
return netaddr.IPNetwork(port['subnets'][0]['cidr']).version == 6
@classmethod
def _is_port_v6(cls, port):
cidr = cls._get_item(port['subnets'],
port['ip_info']['subnet_id'], 'id')['cidr']
return netaddr.IPNetwork(cidr).version == 6
@staticmethod
def _get_hsrp_grp_num_from_ri(ri):
@ -507,7 +549,7 @@ class ASR1kRoutingDriver(iosxe_driver.IosXeRoutingDriver):
def _add_internal_nw_nat_rules(self, ri, port, ext_port):
vrf_name = self._get_vrf_name(ri)
acl_no = self._generate_acl_num_from_port(port)
internal_cidr = port['ip_cidr']
internal_cidr = port['ip_info']['ip_cidr']
internal_net = netaddr.IPNetwork(internal_cidr).network
net_mask = netaddr.IPNetwork(internal_cidr).hostmask
inner_itfc = self._get_interface_name_from_hosting_port(port)

View File

@ -81,6 +81,20 @@ CREATE_SUBINTERFACE_EXT_REGION_ID_WITH_ID = """
</config>
"""
# ===================================================
# Add secondary ip for additional subnets
# $(config)interface GigabitEthernet 2.500
# $(config)ip address 192.168.0.1 255.255.255.0 secondary
# ===================================================
SET_SUBINTERFACE_SECONDARY_IP = """
<config>
<cli-config-data>
<cmd>interface %s</cmd>
<cmd>ip address %s %s secondary</cmd>
</cli-config-data>
</config>
"""
# ===================================================
# Enable HSRP on a Subinterface
# $(config)interface GigabitEthernet0/0/0.314
@ -129,6 +143,20 @@ SET_INTC_ASR_HSRP_EXTERNAL = """
</config>
"""
# ===================================================
# Enable HSRP on a External Network Subinterface secondary IP
# $(config)interface GigabitEthernet0/0/0.314
# $(config)standby 1621 ip 10.0.3.1 secondary
# ===================================================
SET_INTC_ASR_SECONDARY_HSRP_EXTERNAL = """
<config>
<cli-config-data>
<cmd>interface %s</cmd>
<cmd>standby %s ip %s secondary</cmd>
</cli-config-data>
</config>
"""
# ===========================================================================
# Set Static source translation on an interface
# Syntax: ip nat inside source static <fixed_ip> <floating_ip>

View File

@ -17,6 +17,7 @@ import eventlet
import netaddr
import pprint as pp
from operator import itemgetter
from oslo_config import cfg
from oslo_log import log as logging
import oslo_messaging
@ -30,6 +31,8 @@ from neutron.common import topics
from neutron.common import utils as common_utils
from neutron import context as n_context
from neutron_lib import exceptions as n_lib_exc
from networking_cisco._i18n import _, _LE, _LI, _LW
from networking_cisco import backwards_compatibility as bc
from networking_cisco.plugins.cisco.cfg_agent import cfg_exceptions
@ -54,6 +57,16 @@ SYNC_ROUTERS_MAX_CHUNK_SIZE = 64
SYNC_ROUTERS_MIN_CHUNK_SIZE = 8
class IPAddressMissingException(n_lib_exc.NeutronException):
message = _("Router port %(port_id)s has no IP address on subnet "
"%(subnet_id)s.")
class MultipleIPv4SubnetsException(n_lib_exc.NeutronException):
message = _("There should not be multiple IPv4 subnets %(subnets)s on "
"router port %(port_id)s")
class RouterInfo(object):
"""Wrapper class around the (neutron) router dictionary.
@ -726,9 +739,41 @@ class RoutingServiceHelper(object):
self._enable_router_interface(ri, port)
def _process_new_ports(self, ri, new_ports, ex_gw_port, list_port_ids_up):
#TODO(bmelande): 1. We need to handle the case where an external
# network, to which a global router is connected,
# is given another subnet. The global router must
# then attached to that subnet. That attachment
# does NOT result in a new router port. Instead, it
# is done as an update to an EXISTING router port
# which gets another ip address (from the newly
# added subnet.
for p in new_ports:
self._set_subnet_info(p)
# We sort the port's subnets on subnet_id so we can be sure that
# the same ip address is used as primary on the HA master router
# as well as on all HA backup routers.
port_subnets = sorted(p['subnets'], key=itemgetter('id'))
num_subnets_on_port = len(port_subnets)
LOG.debug("Number of subnets associated with router port = %d" %
num_subnets_on_port)
if (ri.router[ROUTER_ROLE_ATTR] is None and
num_subnets_on_port > 1):
LOG.error(_LE("Ignoring router port with multiple IPv4 "
"subnets associated"))
raise MultipleIPv4SubnetsException(
port_id=p['id'], subnets=pp.pformat(port_subnets))
# Configure the primary IP address
self._set_subnet_info(p, port_subnets[0]['id'])
self._internal_network_added(ri, p, ex_gw_port)
# Process the secondary subnets. Only router ports of global
# routers can have multiple ipv4 subnets since we connect such
# routers to external networks using regular router ports.
for p_sn in port_subnets[1:]:
self._set_subnet_info(p, p_sn['id'], is_primary=False)
self._internal_network_added(ri, p, ex_gw_port)
ri.internal_ports.append(p)
list_port_ids_up.append(p['id'])
@ -738,13 +783,37 @@ class RoutingServiceHelper(object):
ri.internal_ports.remove(p)
def _process_gateway_set(self, ri, ex_gw_port, list_port_ids_up):
self._set_subnet_info(ex_gw_port)
# We sort the port's subnets on subnet_id so we can be sure that
# the same ip address is used as primary on the HA master router
# as well as on all HA backup routers.
gw_port_subnets = sorted(ex_gw_port['subnets'], key=itemgetter('id'))
# Configure the primary IP address
self._set_subnet_info(ex_gw_port, gw_port_subnets[0]['id'])
self._external_gateway_added(ri, ex_gw_port)
# Process the secondary subnets
for gw_p_sn in gw_port_subnets[1:]:
self._set_subnet_info(ex_gw_port, gw_p_sn['id'], is_primary=False)
self._external_gateway_added(ri, ex_gw_port)
list_port_ids_up.append(ex_gw_port['id'])
def _process_gateway_cleared(self, ri, ex_gw_port):
# We sort the port's subnets on subnet_id so we can be sure that
# the same ip address is used as primary on the HA master router
# as well as on all HA backup routers.
gw_port_subnets = sorted(ex_gw_port['subnets'], key=itemgetter('id'))
# Deconfigure the primary IP address
self._set_subnet_info(ex_gw_port, gw_port_subnets[0]['id'])
self._external_gateway_removed(ri, ex_gw_port)
# Process the secondary subnets
for gw_p_sn in gw_port_subnets[1:]:
self._set_subnet_info(ex_gw_port, gw_p_sn['id'], is_primary=False)
self._external_gateway_removed(ri, ex_gw_port)
def _add_rid_to_vrf_list(self, ri):
# not needed in base service helper
pass
@ -1074,26 +1143,14 @@ class RoutingServiceHelper(object):
ri.routes = new_routes
@staticmethod
def _set_subnet_info(port):
ips = port['fixed_ips']
def _set_subnet_info(port, subnet_id, is_primary=True):
ips = [i['ip_address'] for i in port['fixed_ips']
if i['subnet_id'] == subnet_id]
if not ips:
raise Exception(_("Router port %s has no IP address") % port['id'])
if len(ips) > 1:
LOG.error(_LE("Ignoring multiple IPs on router port %s"),
port['id'])
port_subnets = port['subnets']
num_subnets_on_port = len(port_subnets)
LOG.debug("number of subnets associated with port = %d" %
num_subnets_on_port)
# TODO(What should we do if multiple subnets are somehow associated)
# TODO(with a port?)
if (num_subnets_on_port > 1):
LOG.error(_LE("Ignoring port with multiple subnets associated"))
raise Exception(("Multiple subnets configured on port. %s") %
pp.pformat(port_subnets))
else:
subnet = port_subnets[0]
prefixlen = netaddr.IPNetwork(subnet['cidr']).prefixlen
port['ip_cidr'] = "%s/%s" % (ips[0]['ip_address'], prefixlen)
raise IPAddressMissingException(port_id=port['id'],
subnet_id=subnet_id)
subnet = port['subnets'][0]
prefixlen = netaddr.IPNetwork(subnet['cidr']).prefixlen
port['ip_info'] = {'subnet_id': subnet_id, 'is_primary': is_primary,
'ip_cidr': "%s/%s" % (ips[0], prefixlen)}

View File

@ -19,8 +19,11 @@ from oslo_log import log as logging
from networking_cisco import backwards_compatibility as bc
from networking_cisco.plugins.cisco.cfg_agent.service_helpers import (
routing_svc_helper as helper)
from networking_cisco.plugins.cisco.common import (cisco_constants as
c_constants)
from networking_cisco.plugins.cisco.extensions import routerrole
ROUTER_ROLE_ATTR = routerrole.ROUTER_ROLE_ATTR
LOG = logging.getLogger(__name__)
@ -33,11 +36,15 @@ class RoutingServiceHelperAci(helper.RoutingServiceHelper):
self._router_ids_by_vrf = {}
self._router_ids_by_vrf_and_ext_net = {}
def _is_global_router(self, ri):
return (ri.router.get(ROUTER_ROLE_ATTR) ==
c_constants.ROUTER_ROLE_GLOBAL)
def _process_new_ports(self, ri, new_ports, ex_gw_port, list_port_ids_up):
# Only add internal networks if we have an
# external gateway -- otherwise we have no parameters
# to use to configure the interface (e.g. VRF, IP, etc.)
if ex_gw_port:
if ex_gw_port or self._is_global_router(ri):
super(RoutingServiceHelperAci,
self)._process_new_ports(
ri, new_ports, ex_gw_port, list_port_ids_up)
@ -51,7 +58,7 @@ class RoutingServiceHelperAci(helper.RoutingServiceHelper):
# the relevant information (VRF and external network
# parameters), which come from the GW port. Go ahead
# and remove the interface from our internal state
if gw_port:
if gw_port or self._is_global_router(ri):
self._internal_network_removed(ri, p, gw_port)
ri.internal_ports.remove(p)

View File

@ -0,0 +1,239 @@
# Copyright 2016 Cisco Systems, Inc. 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.
# A tiny and simple Cisco IOS XE running config simulator.
# The intended use is to allow a developer to observe how the running config
# of an IOS XE device evolves as CLI commands are issued.
#
# Simple implies here that no CLI syntax or semantical checks are made so it
# is entirely up to the command issuer to ensure the correctness of the
# commands and their arguments.
#
# Bob Melander (bob.melander@gmail.com)
import re
import six
from oslo_utils import timeutils
class CiscoIOSXESimulator(object):
# set of commands to be logged only
log_only_commands = set()
# set of commands bound to immediately preceding line
parent_bound_commands = {'exit-address-family'}
exclamation = {'vrf definition', ' exit-address-family'}
def __init__(self, path, host_ip, netmask, port, username, password,
device_params, mgmt_interface, timeout):
self.host_ip = host_ip
self.netmask = netmask
self.port = port
self.username = username
self.password = password
self.device_params = device_params
self.mgmt_interface = mgmt_interface
self.timeout = timeout
self.last_update = timeutils.utcnow()
self.rc = self._get_dict()
self._set_default_config()
def get_config(self):
change_date = timeutils.strtime(self.last_update, '%a %b %d %Y')
change_time = timeutils.strtime(self.last_update, '%H:%M:%S')
intro_lines = ("! Last configuration change at " + change_time + " " +
"UTC " + change_date + " by " + self.username + "\n!\n")
intro_lines += ("hostname ASR-1002X-" +
self.host_ip.replace('.', '_') + "\n!\n")
intro_lines += ("boot-start-marker\nboot system flash "
"bootflash:/asr1002x-simulated.03.16.00.S-ext."
"SPA.bin\nboot-end-marker\n!\n")
rc_data = {'rc_str': intro_lines}
cmds = sorted(self.rc.keys())
if 'vrf' in cmds:
cmds.remove('vrf')
cmds.insert(0, 'vrf')
#for cmd, args in sorted(six.iteritems(self.rc)):
for cmd in cmds:
args = self.rc[cmd]
line = cmd
self._build_line(rc_data, args, line, 0)
print(rc_data['rc_str'])
return rc_data['rc_str']
def edit_config(self, snippet):
command_lines = self._get_command_lines(snippet)
if not command_lines:
return
self._process_next_level(self.rc, self.rc, command_lines, None, True)
self.last_update = timeutils.utcnow()
return True
def _set_default_config(self):
mgmt_gw_ip = '.'.join((self.host_ip.split('.')[:-1]) + ['1'])
command_chunks = [
["vrf definition Mgmt-intf",
"address-family ipv4",
"exit-address-family",
"address-family ipv6",
"exit-address-family"],
["interface " + self.mgmt_interface,
"vrf forwarding Mgmt-intf",
"ip address " + self.host_ip + " " + self.netmask,
"negotiation auto"],
["ip tftp source - interface " + self.mgmt_interface],
["ip route vrf Mgmt - intf 0.0.0.0 0.0.0.0 " + mgmt_gw_ip],
["ip ssh source - interface " + self.mgmt_interface],
["ip ssh version 2"]
]
for commands in command_chunks:
self._process_next_level(self.rc, self.rc, commands, None, True)
def _build_line(self, rc_data, current, baseline, level):
for string, the_rest in sorted(six.iteritems(current)):
if string == 'EOL':
continue
#line = baseline
line = " " if baseline == "" and level >= 1 else baseline
#line += ' ' + string if line != "" else string
line += ' ' + string if line != "" and line != " " else string
if 'EOL' in the_rest:
#termination = "\n!\n" if self._to_exclamate(line) else "\n"
if self._to_exclamate(line):
termination = "\n !\n" if level >= 1 else "\n!\n"
else:
#termination = " \n" if level == 1 else "\n"
termination = "\n"
rc_data['rc_str'] += line + termination
line = ""
self._build_line(rc_data, the_rest, line, level + 1)
if level == 0:
rc_data['rc_str'] += "!\n"
def _to_exclamate(self, line):
for statement in self.exclamation:
if line.startswith(statement):
return True
return False
def _process_next_level(self, parent, current, remaining_lines,
last_processed, is_root=False):
if not remaining_lines:
return
pre, cmd_line = self._get_command_prepending(remaining_lines[0])
if pre is None:
self._process_set(cmd_line, parent, current,
remaining_lines, last_processed, is_root)
elif pre.lower() == "no":
self._process_unset(cmd_line.split(" "), current)
def _process_set(self, cmd_line, parent, current, remaining_lines,
last_processed, is_root):
cmd, args = self._get_command_and_args(cmd_line)
if cmd in self.log_only_commands:
self._process_next_level(parent, current,
remaining_lines[1:], last_processed)
return
if cmd in self.parent_bound_commands:
this_one = last_processed.get(cmd)
start = last_processed
else:
this_one = parent.get(cmd)
start = current
if this_one is None:
this_one, current_parent = self._get_successor_and_its_parent(
parent, cmd, start, is_root)
else:
current_parent = start
for arg in args:
next_one, current_parent = self._get_successor_and_its_parent(
current_parent, arg, this_one, is_root)
this_one = next_one
this_one['EOL'] = True
if is_root is True:
current = this_one
self._process_next_level(current_parent, current, remaining_lines[1:],
this_one)
def _process_unset(self, remaining, current):
if not remaining:
return
arg = remaining[0]
rest = remaining[1:]
if arg in current:
if not rest:
del current[arg]
else:
self._process_unset(rest, current[arg])
num_items = len(current[arg])
if num_items == 0:
del current[arg]
def _get_successor_and_its_parent(self, parent, string, current, is_root):
successor = current.get(string)
if successor is None:
successor = self._get_dict()
current[string] = successor
current_parent = parent if is_root is False else successor
else:
current_parent = current
return successor, current_parent
def _get_command_lines(self, snippet):
if not snippet:
return []
lines = snippet.split('\n')
commands = []
for line in lines:
if self._should_skip_line(line):
continue
cmd = self._get_embedded_command_string(line)
if cmd is not None:
commands.append(cmd)
return commands
def _should_skip_line(self, line):
if line == "":
return True
if line.find("config>") != -1:
return True
elif line.find("cli-config-data>") != -1:
return True
return False
def _get_embedded_command_string(self, line):
match_obj = re.match(r'\s*<cmd>(.*)</cmd>\s*', line)
if match_obj:
return match_obj.group(1)
return None
def _get_command_prepending(self, cmd):
match_obj = re.match(r'\s*(no|do) (.*)\s*', cmd)
if match_obj:
return match_obj.group(1), match_obj.group(2)
return None, cmd
def _get_command_and_args(self, cmd_line):
str_list = cmd_line.split(" ")
return str_list[0], str_list[1:]
def _get_dict(self):
return {}
# A simple Cisco IOS XE CLI simulator
class FakeRunningConfig(object):
def __init__(self, rc):
self._raw = rc

View File

@ -430,8 +430,13 @@ class HA_db_mixin(object):
# Now add gw to redundancy routers
rr_ids = []
for r_b_db in router_db.redundancy_bindings:
spec = {EXTERNAL_GW_INFO: copy.copy(router[EXTERNAL_GW_INFO])}
spec[EXTERNAL_GW_INFO].pop('external_fixed_ips', None)
spec = {EXTERNAL_GW_INFO: copy.deepcopy(router[EXTERNAL_GW_INFO])}
if spec[EXTERNAL_GW_INFO]['external_fixed_ips']:
# Ensure ip addresses are not specified as they cannot be
# same as visible router's ip addresses.
for e_fixed_ip in spec[EXTERNAL_GW_INFO]['external_fixed_ips']:
e_fixed_ip.pop('ip_address', None)
#spec[EXTERNAL_GW_INFO].pop('external_fixed_ips', None)
spec[ha.ENABLED] = False
self._update_router_no_notify(
context, r_b_db.redundancy_router_id, {'router': spec})
@ -682,7 +687,7 @@ class HA_db_mixin(object):
return r_ha_g
def _get_fixed_ips_subnets(self, fixed_ips):
subnets = copy.copy(fixed_ips)
subnets = copy.deepcopy(fixed_ips)
for s in subnets:
s.pop('ip_address', None)
return subnets

View File

@ -44,7 +44,7 @@ from neutron.extensions import providernet as pr_net
from neutron_lib import exceptions as n_exc
from networking_cisco import backwards_compatibility as bc
from networking_cisco._i18n import _, _LE, _LI, _LW
from networking_cisco._i18n import _, _LE, _LI
from networking_cisco.plugins.cisco.common import cisco_constants
from networking_cisco.plugins.cisco.db.device_manager import hd_models
from networking_cisco.plugins.cisco.db.l3 import l3_models
@ -67,6 +67,7 @@ VM_CATEGORY = ciscohostingdevicemanager.VM_CATEGORY
L3_ROUTER_NAT = bc.constants.L3
HOSTING_DEVICE_ATTR = routerhostingdevice.HOSTING_DEVICE_ATTR
ROUTER_ROLE_GLOBAL = cisco_constants.ROUTER_ROLE_GLOBAL
ROUTER_ROLE_LOGICAL_GLOBAL = cisco_constants.ROUTER_ROLE_LOGICAL_GLOBAL
ROUTER_ROLE_HA_REDUNDANCY = cisco_constants.ROUTER_ROLE_HA_REDUNDANCY
DICT_EXTEND_FUNCTIONS = ['_extend_router_dict_routertype',
@ -1064,13 +1065,17 @@ class L3RouterApplianceDBMixin(extraroute_db.ExtraRoute_dbonly_mixin):
@lockutils.synchronized('routerbacklog', 'neutron-')
def _process_backlogged_routers(self):
self.ensure_global_router_cleanup()
e_context = n_context.get_admin_context()
for r_type, drv in self._router_drivers.items():
if drv is not None:
LOG.debug('Calling pre_backlog_processing for router type %s',
r_type)
drv.pre_backlog_processing(e_context)
if self._refresh_router_backlog:
self._sync_router_backlog()
if not self._backlogged_routers:
LOG.debug('No routers in backlog %s' % self._backlogged_routers)
return
e_context = n_context.get_admin_context()
scheduled_routers = []
LOG.info(_LI('Processing router (scheduling) backlog'))
# try to reschedule
@ -1111,50 +1116,11 @@ class L3RouterApplianceDBMixin(extraroute_db.ExtraRoute_dbonly_mixin):
for ni in self.get_notifiers(e_context, scheduled_routers):
if ni['notifier']:
ni['notifier'].routers_updated(e_context, ni['routers'])
def ensure_global_router_cleanup(self):
"""TODO: Function to be moved into router type driver.
This function should be moved into the router type driver.
This will be done when the router type driver api is revised.
"""
e_context = n_context.get_admin_context()
l3plugin = bc.get_plugin(L3_ROUTER_NAT)
filters = {routerrole.ROUTER_ROLE_ATTR: [ROUTER_ROLE_GLOBAL]}
global_routers = l3plugin.get_routers(e_context, filters=filters)
if not global_routers:
LOG.debug("There are no global routers")
return
for gr in global_routers:
filters = {
HOSTING_DEVICE_ATTR: [gr[HOSTING_DEVICE_ATTR]],
routerrole.ROUTER_ROLE_ATTR: [ROUTER_ROLE_HA_REDUNDANCY, None]
}
invert_filters = {'gw_port_id': [None]}
num_rtrs = l3plugin.get_routers_count_extended(
e_context, filters=filters, invert_filters=invert_filters)
LOG.debug("Global router %(name)s[%(id)s] with hosting_device "
"%(hd)s has %(num)d routers with gw_port set on that "
"device",
{'name': gr['name'], 'id': gr['id'],
'hd': gr[HOSTING_DEVICE_ATTR], 'num': num_rtrs, })
if num_rtrs == 0:
LOG.warning(_LW("Global router:%(name)s[id:%(id)s] is present "
"for hosting device:%(hd)s but there are no "
"tenant or redundancy routers with gateway set "
"on that hosting device. Proceeding to delete "
"global router."),
{'name': gr['name'], 'id': gr['id'],
'hd': gr[HOSTING_DEVICE_ATTR]})
try:
l3plugin.delete_router(
e_context, gr['id'], unschedule=False)
except (exc.ObjectDeletedError, l3.RouterNotFound) as e:
LOG.warning(e)
driver = self._get_router_type_driver(
e_context, gr[routertype.TYPE_ATTR])
driver._conditionally_remove_logical_global_router(
e_context, gr)
for r_type, drv in self._router_drivers.items():
if drv is not None:
LOG.debug('Calling post_backlog_processing for router type %s',
r_type)
drv.post_backlog_processing(e_context)
def _setup_backlog_handling(self):
LOG.debug('Activating periodic backlog processor')

View File

@ -18,12 +18,15 @@ from oslo_utils import excutils
from networking_cisco._i18n import _LE
from networking_cisco import backwards_compatibility as bc
from networking_cisco.plugins.cisco.common import cisco_constants
from networking_cisco.plugins.cisco.device_manager import config
import networking_cisco.plugins.cisco.device_manager.plugging_drivers as plug
LOG = logging.getLogger(__name__)
DEVICE_OWNER_ROUTER_GW = bc.constants.DEVICE_OWNER_ROUTER_GW
GLOBAL_ROUTER_ROLES = [cisco_constants.ROUTER_ROLE_GLOBAL,
cisco_constants.ROUTER_ROLE_LOGICAL_GLOBAL]
class HwVLANTrunkingPlugDriver(plug.PluginSidePluggingDriver):
@ -66,7 +69,7 @@ class HwVLANTrunkingPlugDriver(plug.PluginSidePluggingDriver):
def extend_hosting_port_info(self, context, port_db, hosting_device,
hosting_info):
hosting_info['segmentation_id'] = port_db.hosting_info.segmentation_id
is_external = (port_db.device_owner == DEVICE_OWNER_ROUTER_GW)
is_external = (port_db.networks.external is not None)
hosting_info['physical_interface'] = self._get_interface_info(
hosting_device['id'], port_db.network_id, is_external)

View File

@ -400,3 +400,27 @@ class L3RouterBaseDriver(object):
config agent drivers corresponding to this router type driver.
"""
return ""
def pre_backlog_processing(self, context):
"""Perform driver specific processing before backlog is processed.
:param context: admin neutron context
This function is invoked before the router plugin is processing the
backlog of unscheduled routers. It allows the router type driver to
perform any tasks that should be performed before the backlog is
processed.
"""
pass
def post_backlog_processing(self, context):
"""Perform driver specific processing after backlog is processed.
:param context: admin neutron context
This function is invoked after the router plugin has processed the
backlog of unscheduled routers. It allows the router type driver to
perform any tasks that should be performed after the backlog has been
processed.
"""
pass

View File

@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import uuidutils
@ -27,7 +25,7 @@ from neutron.extensions import l3
from neutron_lib import constants as l3_constants
from neutron_lib import exceptions as n_exc
from networking_cisco._i18n import _
from networking_cisco._i18n import _, _LW
from networking_cisco import backwards_compatibility as bc
from networking_cisco.plugins.cisco.common import cisco_constants
from networking_cisco.plugins.cisco.db.l3 import ha_db
@ -197,6 +195,48 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
group_id += EXT_HSRP_GRP_OFFSET
return group_id
def pre_backlog_processing(self, context):
filters = {routerrole.ROUTER_ROLE_ATTR: [ROUTER_ROLE_GLOBAL]}
global_routers = self._l3_plugin.get_routers(context, filters=filters)
if not global_routers:
LOG.debug("There are no global routers")
return
for gr in global_routers:
filters = {
HOSTING_DEVICE_ATTR: [gr[HOSTING_DEVICE_ATTR]],
routerrole.ROUTER_ROLE_ATTR: [ROUTER_ROLE_HA_REDUNDANCY, None]
}
invert_filters = {'gw_port_id': [None]}
num_rtrs = self._l3_plugin.get_routers_count_extended(
context, filters=filters, invert_filters=invert_filters)
LOG.debug("Global router %(name)s[%(id)s] with hosting_device "
"%(hd)s has %(num)d routers with gw_port set on that "
"device",
{'name': gr['name'], 'id': gr['id'],
'hd': gr[HOSTING_DEVICE_ATTR], 'num': num_rtrs, })
if num_rtrs == 0:
LOG.warning(
_LW("Global router:%(name)s[id:%(id)s] is present for "
"hosting device:%(hd)s but there are no tenant or "
"redundancy routers with gateway set on that hosting "
"device. Proceeding to delete global router."),
{'name': gr['name'], 'id': gr['id'],
'hd': gr[HOSTING_DEVICE_ATTR]})
self._delete_global_router(context, gr['id'])
filters = {
#TODO(bmelande): Filter on routertype of global router
#routertype.TYPE_ATTR: [routertype_id],
routerrole.ROUTER_ROLE_ATTR: [ROUTER_ROLE_LOGICAL_GLOBAL]}
log_global_routers = self._l3_plugin.get_routers(
context, filters=filters)
if log_global_routers:
log_global_router_id = log_global_routers[0]['id']
self._delete_global_router(context, log_global_router_id,
logical=True)
def post_backlog_processing(self, context):
pass
# ---------------- Create workflow functions -----------------
def _conditionally_add_global_router(self, context, tenant_router):
@ -238,7 +278,7 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
'device_id': [global_router['id']],
'device_owner': [port_type]}
connected_nets = {
p['network_id'] for p in
p['network_id']: p['fixed_ips'] for p in
self._core_plugin.get_ports(context, filters=filters)}
if ext_net_id in connected_nets:
# already connected to the external network so we're done
@ -255,7 +295,8 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
port_type=DEVICE_OWNER_GLOBAL_ROUTER_GW):
# When a global router is connected to an external network then a
# special type of gateway port is created on that network. Such a
# port is called auxiliary gateway ports. A (logical) global router
# port is called auxiliary gateway ports. It has an ip address on
# each subnet of the external network. A (logical) global router
# never has a traditional Neutron gateway port.
filters = {
'device_id': [tenant_router['id']],
@ -264,7 +305,7 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
# the CIDR of that port's subnet
gw_port = self._core_plugin.get_ports(context,
filters=filters)[0]
fixed_ips = self._get_fixed_ips_subnets(gw_port['fixed_ips'])
fixed_ips = self._get_fixed_ips_subnets(context, gw_port)
global_router_id = global_router['id']
with context.session.begin(subtransactions=True):
aux_gw_port = self._core_plugin.create_port(context, {
@ -352,10 +393,9 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
context.session.add(r_ha_s_db)
return logical_global_router
def _get_fixed_ips_subnets(self, fixed_ips):
subnets = copy.copy(fixed_ips)
for s in subnets:
s.pop('ip_address', None)
def _get_fixed_ips_subnets(self, context, gw_port):
nw = self._core_plugin.get_network(context, gw_port['network_id'])
subnets = [{'subnet_id': s} for s in nw['subnets']]
return subnets
def _provision_port_ha(self, context, ha_port, router, ha_binding_db=None):
@ -401,6 +441,10 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
hd_to_gr_dict = {r[HOSTING_DEVICE_ATTR]: r for r in global_routers}
if global_routers:
global_router_id = global_routers[0]['id']
if not tenant_router or not tenant_router[l3.EXTERNAL_GW_INFO]:
# let l3 plugin's periodic backlog processing take care of the
# clean up of the global router
return
ext_net_id = tenant_router[l3.EXTERNAL_GW_INFO]['network_id']
routertype_id = tenant_router[routertype.TYPE_ATTR]
hd_id = tenant_router[HOSTING_DEVICE_ATTR]
@ -444,7 +488,8 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
(num_rtrs == 0 and update_operation is True)):
# there are no tenant routers *on ext_net_id* that are serviced by
# this global router so it's aux gw port can be deleted
self._delete_auxiliary_gateway_port(context, router_id, ext_net_id)
self._delete_auxiliary_gateway_ports(context, router_id,
ext_net_id)
return True
return False
@ -463,8 +508,8 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
if num_global_rtrs == 0:
# there are no global routers *on ext_net_id* that are serviced by
# this logical global router so it's aux gw VIP port can be deleted
self._delete_auxiliary_gateway_port(context, log_global_router_id,
ext_net_id)
self._delete_auxiliary_gateway_ports(context, log_global_router_id,
ext_net_id)
filters[routerrole.ROUTER_ROLE_ATTR] = [ROUTER_ROLE_GLOBAL]
total_num_global_rtrs = self._l3_plugin.get_routers_count(
context, filters=filters)
@ -474,7 +519,7 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
self._delete_global_router(context, log_global_router_id, True)
return False
def _delete_auxiliary_gateway_port(
def _delete_auxiliary_gateway_ports(
self, context, router_id, net_id=None,
port_type=DEVICE_OWNER_GLOBAL_ROUTER_GW):
filters = {
@ -491,7 +536,7 @@ class ASR1kL3RouterDriver(drivers.L3RouterBaseDriver):
def _delete_global_router(self, context, global_router_id, logical=False):
# ensure we clean up any stale auxiliary gateway ports
self._delete_auxiliary_gateway_port(context, global_router_id)
self._delete_auxiliary_gateway_ports(context, global_router_id)
try:
if logical is True:
# We use parent class method as no special operations beyond

View File

@ -76,3 +76,9 @@ class NoopL3RouterDriver(drivers.L3RouterBaseDriver):
def delete_floatingip_postcommit(self, context, fip_context):
pass
def pre_backlog_processing(self, context):
pass
def post_backlog_processing(self, context):
pass

View File

@ -0,0 +1,172 @@
(neutron) net-list
+--------------------------------------+---------+-----------------------------------------------------+
| id | name | subnets |
+--------------------------------------+---------+-----------------------------------------------------+
| 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 | public | 7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41 172.16.6.32/27 |
| | | 05509041-00e0-45c3-bf38-c603911c1ea4 172.17.7.32/27 |
| 02232008-c78c-46b2-b712-678d85def46a | private | 54074049-aaf1-44d2-9843-99cdb10e3212 10.0.3.0/24 |
+--------------------------------------+---------+-----------------------------------------------------+
(neutron) subnet-list
+--------------------------------------+-----------------+----------------+------------------------------------------------+
| id | name | cidr | allocation_pools |
+--------------------------------------+-----------------+----------------+------------------------------------------------+
| 7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41 | public-subnet | 172.16.6.32/27 | {"start": "172.16.6.34", "end": "172.16.6.62"} |
| 54074049-aaf1-44d2-9843-99cdb10e3212 | private-subnet | 10.0.3.0/24 | {"start": "10.0.3.2", "end": "10.0.3.254"} |
| 05509041-00e0-45c3-bf38-c603911c1ea4 | public-subnet-2 | 172.17.7.32/27 | {"start": "172.17.7.34", "end": "172.17.7.62"} |
+--------------------------------------+-----------------+----------------+------------------------------------------------+
(neutron) router-list
+--------------------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | external_gateway_info |
+--------------------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 085eba49-7ec9-470a-ac37-e89606eba108 | router1_HA_backup_1 | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": |
| | | "172.16.6.45"}, {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"}]} |
| 25ecf24d-a3eb-426f-8871-22d7e78c5944 | Global-router-0000-000000000005 | null |
| 5dd41cc4-7cbd-444f-894b-589531d3686c | router1 | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": |
| | | "172.16.6.44"}, {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.34"}]} |
| 945d631c-0b37-4322-8dbe-c3759a3cac45 | Logical-Global-router | null |
| c5c5eb9e-4451-4936-9125-9a9634cb5d2e | Global-router-0000-000000000004 | null |
+--------------------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list router1
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 780a2d1a-6cae-4b2e-919e-bb5fb0ee0395 | | fa:16:3e:37:e3:d7 | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.44"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.34"} |
| 9747b0d0-9380-4674-8cd9-9bc0db62355c | | fa:16:3e:ae:75:c5 | {"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212", "ip_address": "10.0.3.1"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show router1
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:details | {"redundancy_routers": [{"priority": 97, "state": "STANDBY", "id": "085eba49-7ec9-470a-ac37-e89606eba108"}], "probe_connectivity": false, "priority": 100, "state": "ACTIVE", |
| | "redundancy_level": 1, "type": "HSRP"} |
| cisco_ha:enabled | True |
| description | |
| external_gateway_info | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.44"}, {"subnet_id": |
| | "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.34"}]} |
| id | 5dd41cc4-7cbd-444f-894b-589531d3686c |
| name | router1 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000005 |
| routerrole:role | |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | 840995fdaaf44ad4ab972f06fd6fbc13 |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list Global-router-0000-000000000005
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| e678299a-0fbb-43f1-915c-a1c48c676bc6 | | fa:16:3e:04:d1:66 | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.48"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.38"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show Global-router-0000-000000000005
+-------------------------------------------------+--------------------------------------+
| Field | Value |
+-------------------------------------------------+--------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | |
| id | 25ecf24d-a3eb-426f-8871-22d7e78c5944 |
| name | Global-router-0000-000000000005 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000005 |
| routerrole:role | Global |
| routertype-aware-scheduler:auto_schedule | False |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+--------------------------------------+
(neutron) router-show router1_HA_backup_1
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.45"}, {"subnet_id": |
| | "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"}]} |
| id | 085eba49-7ec9-470a-ac37-e89606eba108 |
| name | router1_HA_backup_1 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000004 |
| routerrole:role | HA-Redundancy |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list router1_HA_backup_1
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 121bf217-7224-435a-bb23-fdb9c79b35c1 | | fa:16:3e:33:26:8e | {"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212", "ip_address": "10.0.3.3"} |
| 53e1c49f-8bad-4dc3-8e19-2202ab08fe53 | | fa:16:3e:fe:b7:79 | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.45"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show router1_HA_backup_1
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.45"}, {"subnet_id": |
| | "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"}]} |
| id | 085eba49-7ec9-470a-ac37-e89606eba108 |
| name | router1_HA_backup_1 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000004 |
| routerrole:role | HA-Redundancy |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list Global-router-0000-000000000004
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 5931d51b-7806-4dd9-a024-2ed1c674782a | | fa:16:3e:40:96:dd | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.47"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.37"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show Global-router-0000-000000000004
+-------------------------------------------------+--------------------------------------+
| Field | Value |
+-------------------------------------------------+--------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | |
| id | c5c5eb9e-4451-4936-9125-9a9634cb5d2e |
| name | Global-router-0000-000000000004 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000004 |
| routerrole:role | Global |
| routertype-aware-scheduler:auto_schedule | False |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+--------------------------------------+
(mysql) select id,device_owner,device_id,network_id from ports;
+--------------------------------------+--------------------------+--------------------------------------+--------------------------------------+
| port_id | device_owner | device_id | network_id |
+--------------------------------------+--------------------------+--------------------------------------+--------------------------------------+
| 0b9c4564-9e42-4dfd-ab96-2cabee626aec | network:router_interface | 312cc5db-8749-46fe-82d9-d8492267902d | 02232008-c78c-46b2-b712-678d85def46a |
| 121bf217-7224-435a-bb23-fdb9c79b35c1 | network:router_interface | 085eba49-7ec9-470a-ac37-e89606eba108 | 02232008-c78c-46b2-b712-678d85def46a |
| 3fdf36c5-34a7-4aa3-8508-66b258377a68 | network:router_interface | 945d631c-0b37-4322-8dbe-c3759a3cac45 | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 53e1c49f-8bad-4dc3-8e19-2202ab08fe53 | network:router_gateway | 085eba49-7ec9-470a-ac37-e89606eba108 | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 5931d51b-7806-4dd9-a024-2ed1c674782a | network:router_interface | c5c5eb9e-4451-4936-9125-9a9634cb5d2e | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 780a2d1a-6cae-4b2e-919e-bb5fb0ee0395 | network:router_gateway | 5dd41cc4-7cbd-444f-894b-589531d3686c | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 9747b0d0-9380-4674-8cd9-9bc0db62355c | network:router_interface | 5dd41cc4-7cbd-444f-894b-589531d3686c | 02232008-c78c-46b2-b712-678d85def46a |
| e678299a-0fbb-43f1-915c-a1c48c676bc6 | network:router_interface | 25ecf24d-a3eb-426f-8871-22d7e78c5944 | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
+--------------------------------------+--------------------------+--------------------------------------+--------------------------------------+

View File

@ -0,0 +1,728 @@
[{"_interfaces": [{"address_scopes": {"4": null, "6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T11:27:27",
"description": null,
"device_id": "312cc5db-8749-46fe-82d9-d8492267902d",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "10.0.3.2",
"prefixlen": 24,
"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212"}],
"ha_info": {"group": "1064",
"ha_port": {"address_scopes": {"4": null,
"6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T11:27:26",
"description": "",
"device_id": "5dd41cc4-7cbd-444f-894b-589531d3686c",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "10.0.3.1",
"prefixlen": 24,
"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212"}],
"id": "9747b0d0-9380-4674-8cd9-9bc0db62355c",
"mac_address": "fa:16:3e:ae:75:c5",
"mt": 1450,
"name": "",
"network_id": "02232008-c78c-46b2-b712-678d85def46a",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "10.0.3.0/24",
"dns_nameservers": [],
"gateway_ip": "10.0.3.1",
"id": "54074049-aaf1-44d2-9843-99cdb10e3212",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "840995fdaaf44ad4ab972f06fd6fbc13",
"updated_at": "2017-02-28T11:27:26"},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"},
"hosting_info": {"hosting_mac": "fa:16:3e:82:59:fb",
"hosting_port_id": "0b9c4564-9e42-4dfd-ab96-2cabee626aec",
"hosting_port_name": "",
"physical_interface": "GigabitEthernet/1/0/4",
"segmentation_id": 1086},
"id": "0b9c4564-9e42-4dfd-ab96-2cabee626aec",
"mac_address": "fa:16:3e:82:59:fb",
"mt": 1450,
"name": "",
"network_id": "02232008-c78c-46b2-b712-678d85def46a",
"port_security_enabled": false,
"security_groups": [],
"status": "ACTIVE",
"subnets": [{"cidr": "10.0.3.0/24",
"dns_nameservers": [],
"gateway_ip": "10.0.3.1",
"id": "54074049-aaf1-44d2-9843-99cdb10e3212",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:25:56"}],
"admin_state_up": true,
"cisco_ha:details": {"priority": 100,
"probe_connectivity": false,
"redundancy_level": 1,
"redundancy_routers": [{"id": "085eba49-7ec9-470a-ac37-e89606eba108",
"priority": 97,
"state": "STANDBY"}],
"state": "ACTIVE",
"type": "HSRP"},
"cisco_ha:enabled": true,
"description": "",
"external_gateway_info": {"external_fixed_ips": [{"ip_address": "172.16.6.44",
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.34",
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838"},
"gw_port": {"address_scopes": {"4": null, "6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:15",
"description": "",
"device_id": "5dd41cc4-7cbd-444f-894b-589531d3686c",
"device_owner": "network:router_gateway",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.44",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.34",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"ha_info": {"group": "1064",
"ha_port": {"address_scopes": {"4": null,
"6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:15",
"description": "",
"device_id": "5dd41cc4-7cbd-444f-894b-589531d3686c",
"device_owner": "network:router_gateway",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.44",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.34",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"id": "780a2d1a-6cae-4b2e-919e-bb5fb0ee0395",
"mac_address": "fa:16:3e:37:e3:d7",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:15"},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"},
"hosting_info": {"hosting_mac": "fa:16:3e:37:e3:d7",
"hosting_port_id": "780a2d1a-6cae-4b2e-919e-bb5fb0ee0395",
"hosting_port_name": "",
"physical_interface": "GigabitEthernet/1/0/5",
"segmentation_id": 1056},
"id": "780a2d1a-6cae-4b2e-919e-bb5fb0ee0395",
"mac_address": "fa:16:3e:37:e3:d7",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:15"},
"gw_port_id": "780a2d1a-6cae-4b2e-919e-bb5fb0ee0395",
"hosting_device": {"admin_state_up": true,
"booting_time": 360,
"created_at": "2017-02-28 11:27:21",
"credentials": {"password": "cisco",
"user_name": "stack"},
"host_category": "Hardware",
"id": "00000000-0000-0000-0000-000000000005",
"management_ip_address": "10.0.100.7",
"name": "ASR1k template",
"protocol_port": 22,
"service_types": "router",
"status": "ACTIVE",
"template_id": "00000000-0000-0000-0000-000000000003",
"timeout": null},
"id": "5dd41cc4-7cbd-444f-894b-589531d3686c",
"name": "router1",
"router_type": {"cfg_agent_driver": "networking_cisco.plugins.cisco.cfg_agent.device_drivers.asr1k.asr1k_routing_driver.ASR1kRoutingDriver",
"cfg_agent_service_helper": "networking_cisco.plugins.cisco.cfg_agent.service_helpers.routing_svc_helper.RoutingServiceHelper",
"id": "00000000-0000-0000-0000-000000000003",
"name": "ASR1k_router"},
"routerhost:hosting_device": "00000000-0000-0000-0000-000000000005",
"routerrole:role": null,
"routertype-aware-scheduler:auto_schedule": true,
"routertype-aware-scheduler:share_hosting_device": true,
"routertype:id": "00000000-0000-0000-0000-000000000003",
"routes": [],
"share_host": true,
"status": "ACTIVE",
"tenant_id": "840995fdaaf44ad4ab972f06fd6fbc13"},
{"_interfaces": [{"address_scopes": {"4": null, "6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:18",
"description": null,
"device_id": "c5c5eb9e-4451-4936-9125-9a9634cb5d2e",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.47",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.37",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"ha_info": {"group": "1064",
"ha_port": {"address_scopes": {"4": null,
"6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:18",
"description": null,
"device_id": "945d631c-0b37-4322-8dbe-c3759a3cac45",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.46",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.36",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"id": "3fdf36c5-34a7-4aa3-8508-66b258377a68",
"mac_address": "fa:16:3e:00:d7:f2",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:18"},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"},
"hosting_info": {"hosting_mac": "fa:16:3e:40:96:dd",
"hosting_port_id": "5931d51b-7806-4dd9-a024-2ed1c674782a",
"hosting_port_name": "",
"physical_interface": "GigabitEthernet/1/0/2",
"segmentation_id": 1056},
"id": "5931d51b-7806-4dd9-a024-2ed1c674782a",
"mac_address": "fa:16:3e:40:96:dd",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:18"}],
"admin_state_up": true,
"cisco_ha:details": {"priority": 100,
"probe_connectivity": false,
"redundancy_level": 2,
"redundancy_routers": [{"id": "c5c5eb9e-4451-4936-9125-9a9634cb5d2e",
"priority": 100,
"state": "STANDBY"},
{"id": "25ecf24d-a3eb-426f-8871-22d7e78c5944",
"priority": 103,
"state": "STANDBY"}],
"state": "ACTIVE",
"type": "HSRP"},
"cisco_ha:enabled": true,
"description": null,
"external_gateway_info": null,
"gw_port_id": null,
"hosting_device": {"admin_state_up": true,
"booting_time": 360,
"created_at": "2017-02-28 11:27:21",
"credentials": {"password": "cisco",
"user_name": "stack"},
"host_category": "Hardware",
"id": "00000000-0000-0000-0000-000000000004",
"management_ip_address": "10.0.100.6",
"name": "ASR1k template",
"protocol_port": 22,
"service_types": "router",
"status": "ACTIVE",
"template_id": "00000000-0000-0000-0000-000000000003",
"timeout": null},
"id": "c5c5eb9e-4451-4936-9125-9a9634cb5d2e",
"name": "Global-router-0000-000000000004",
"router_type": {"cfg_agent_driver": "networking_cisco.plugins.cisco.cfg_agent.device_drivers.asr1k.asr1k_routing_driver.ASR1kRoutingDriver",
"cfg_agent_service_helper": "networking_cisco.plugins.cisco.cfg_agent.service_helpers.routing_svc_helper.RoutingServiceHelper",
"id": "00000000-0000-0000-0000-000000000003",
"name": "ASR1k_router"},
"routerhost:hosting_device": "00000000-0000-0000-0000-000000000004",
"routerrole:role": "Global",
"routertype-aware-scheduler:auto_schedule": false,
"routertype-aware-scheduler:share_hosting_device": true,
"routertype:id": "00000000-0000-0000-0000-000000000003",
"routes": [],
"share_host": true,
"status": "ACTIVE",
"tenant_id": ""},
{"_interfaces": [{"address_scopes": {"4": null, "6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T11:27:27",
"description": null,
"device_id": "085eba49-7ec9-470a-ac37-e89606eba108",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "10.0.3.3",
"prefixlen": 24,
"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212"}],
"ha_info": {"group": "1064",
"ha_port": {"address_scopes": {"4": null,
"6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T11:27:26",
"description": "",
"device_id": "5dd41cc4-7cbd-444f-894b-589531d3686c",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "10.0.3.1",
"prefixlen": 24,
"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212"}],
"id": "9747b0d0-9380-4674-8cd9-9bc0db62355c",
"mac_address": "fa:16:3e:ae:75:c5",
"mt": 1450,
"name": "",
"network_id": "02232008-c78c-46b2-b712-678d85def46a",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "10.0.3.0/24",
"dns_nameservers": [],
"gateway_ip": "10.0.3.1",
"id": "54074049-aaf1-44d2-9843-99cdb10e3212",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "840995fdaaf44ad4ab972f06fd6fbc13",
"updated_at": "2017-02-28T11:27:26"},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"},
"hosting_info": {"hosting_mac": "fa:16:3e:33:26:8e",
"hosting_port_id": "121bf217-7224-435a-bb23-fdb9c79b35c1",
"hosting_port_name": "",
"physical_interface": "GigabitEthernet/1/0/2",
"segmentation_id": 1086},
"id": "121bf217-7224-435a-bb23-fdb9c79b35c1",
"mac_address": "fa:16:3e:33:26:8e",
"mt": 1450,
"name": "",
"network_id": "02232008-c78c-46b2-b712-678d85def46a",
"port_security_enabled": false,
"security_groups": [],
"status": "ACTIVE",
"subnets": [{"cidr": "10.0.3.0/24",
"dns_nameservers": [],
"gateway_ip": "10.0.3.1",
"id": "54074049-aaf1-44d2-9843-99cdb10e3212",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:26:04"}],
"admin_state_up": true,
"cisco_ha:details": {"priority": 100,
"probe_connectivity": false,
"redundancy_level": 1,
"redundancy_routers": [{"id": "085eba49-7ec9-470a-ac37-e89606eba108",
"priority": 97,
"state": "STANDBY"}],
"state": "ACTIVE",
"type": "HSRP"},
"cisco_ha:enabled": true,
"description": "",
"external_gateway_info": {"external_fixed_ips": [{"ip_address": "172.16.6.45",
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.35",
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838"},
"gw_port": {"address_scopes": {"4": null, "6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:16",
"description": "",
"device_id": "085eba49-7ec9-470a-ac37-e89606eba108",
"device_owner": "network:router_gateway",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.45",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.35",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"ha_info": {"group": "1064",
"ha_port": {"address_scopes": {"4": null,
"6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:15",
"description": "",
"device_id": "5dd41cc4-7cbd-444f-894b-589531d3686c",
"device_owner": "network:router_gateway",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.44",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.34",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"id": "780a2d1a-6cae-4b2e-919e-bb5fb0ee0395",
"mac_address": "fa:16:3e:37:e3:d7",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:15"},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"},
"hosting_info": {"hosting_mac": "fa:16:3e:fe:b7:79",
"hosting_port_id": "53e1c49f-8bad-4dc3-8e19-2202ab08fe53",
"hosting_port_name": "",
"physical_interface": "GigabitEthernet/2/0/3",
"segmentation_id": 1056},
"id": "53e1c49f-8bad-4dc3-8e19-2202ab08fe53",
"mac_address": "fa:16:3e:fe:b7:79",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:16"},
"gw_port_id": "53e1c49f-8bad-4dc3-8e19-2202ab08fe53",
"hosting_device": {"admin_state_up": true,
"booting_time": 360,
"created_at": "2017-02-28 11:27:21",
"credentials": {"password": "cisco",
"user_name": "stack"},
"host_category": "Hardware",
"id": "00000000-0000-0000-0000-000000000004",
"management_ip_address": "10.0.100.6",
"name": "ASR1k template",
"protocol_port": 22,
"service_types": "router",
"status": "ACTIVE",
"template_id": "00000000-0000-0000-0000-000000000003",
"timeout": null},
"id": "085eba49-7ec9-470a-ac37-e89606eba108",
"name": "router1_HA_backup_1",
"router_type": {"cfg_agent_driver": "networking_cisco.plugins.cisco.cfg_agent.device_drivers.asr1k.asr1k_routing_driver.ASR1kRoutingDriver",
"cfg_agent_service_helper": "networking_cisco.plugins.cisco.cfg_agent.service_helpers.routing_svc_helper.RoutingServiceHelper",
"id": "00000000-0000-0000-0000-000000000003",
"name": "ASR1k_router"},
"routerhost:hosting_device": "00000000-0000-0000-0000-000000000004",
"routerrole:role": "HA-Redundancy",
"routertype-aware-scheduler:auto_schedule": true,
"routertype-aware-scheduler:share_hosting_device": true,
"routertype:id": "00000000-0000-0000-0000-000000000003",
"routes": [],
"share_host": true,
"status": "ACTIVE",
"tenant_id": ""},
{"_interfaces": [{"address_scopes": {"4": null, "6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:20",
"description": null,
"device_id": "25ecf24d-a3eb-426f-8871-22d7e78c5944",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.48",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.38",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"ha_info": {"group": "1064",
"ha_port": {"address_scopes": {"4": null,
"6": null},
"admin_state_up": true,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"created_at": "2017-02-28T12:52:18",
"description": null,
"device_id": "945d631c-0b37-4322-8dbe-c3759a3cac45",
"device_owner": "network:router_interface",
"dns_name": null,
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{"ip_address": "172.16.6.46",
"prefixlen": 27,
"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41"},
{"ip_address": "172.17.7.36",
"prefixlen": 27,
"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4"}],
"id": "3fdf36c5-34a7-4aa3-8508-66b258377a68",
"mac_address": "fa:16:3e:00:d7:f2",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:18"},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"},
"hosting_info": {"hosting_mac": "fa:16:3e:04:d1:66",
"hosting_port_id": "e678299a-0fbb-43f1-915c-a1c48c676bc6",
"hosting_port_name": "",
"physical_interface": "GigabitEthernet/1/0/4",
"segmentation_id": 1056},
"id": "e678299a-0fbb-43f1-915c-a1c48c676bc6",
"mac_address": "fa:16:3e:04:d1:66",
"mt": 1450,
"name": "",
"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838",
"port_security_enabled": false,
"security_groups": [],
"status": "DOWN",
"subnets": [{"cidr": "172.16.6.32/27",
"dns_nameservers": [],
"gateway_ip": "172.16.6.33",
"id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41",
"ipv6_ra_mode": null,
"subnetpool_id": null},
{"cidr": "172.17.7.32/27",
"dns_nameservers": [],
"gateway_ip": "172.17.7.33",
"id": "05509041-00e0-45c3-bf38-c603911c1ea4",
"ipv6_ra_mode": null,
"subnetpool_id": null}],
"tenant_id": "",
"updated_at": "2017-02-28T12:52:20"}],
"admin_state_up": true,
"cisco_ha:details": {"priority": 100,
"probe_connectivity": false,
"redundancy_level": 2,
"redundancy_routers": [{"id": "c5c5eb9e-4451-4936-9125-9a9634cb5d2e",
"priority": 100,
"state": "STANDBY"},
{"id": "25ecf24d-a3eb-426f-8871-22d7e78c5944",
"priority": 103,
"state": "STANDBY"}],
"state": "ACTIVE",
"type": "HSRP"},
"cisco_ha:enabled": true,
"description": null,
"external_gateway_info": null,
"gw_port_id": null,
"hosting_device": {"admin_state_up": true,
"booting_time": 360,
"created_at": "2017-02-28 11:27:21",
"credentials": {"password": "cisco",
"user_name": "stack"},
"host_category": "Hardware",
"id": "00000000-0000-0000-0000-000000000005",
"management_ip_address": "10.0.100.7",
"name": "ASR1k template",
"protocol_port": 22,
"service_types": "router",
"status": "ACTIVE",
"template_id": "00000000-0000-0000-0000-000000000003",
"timeout": null},
"id": "25ecf24d-a3eb-426f-8871-22d7e78c5944",
"name": "Global-router-0000-000000000005",
"router_type": {"cfg_agent_driver": "networking_cisco.plugins.cisco.cfg_agent.device_drivers.asr1k.asr1k_routing_driver.ASR1kRoutingDriver",
"cfg_agent_service_helper": "networking_cisco.plugins.cisco.cfg_agent.service_helpers.routing_svc_helper.RoutingServiceHelper",
"id": "00000000-0000-0000-0000-000000000003",
"name": "ASR1k_router"},
"routerhost:hosting_device": "00000000-0000-0000-0000-000000000005",
"routerrole:role": "Global",
"routertype-aware-scheduler:auto_schedule": false,
"routertype-aware-scheduler:share_hosting_device": true,
"routertype:id": "00000000-0000-0000-0000-000000000003",
"routes": [],
"share_host": true,
"status": "ACTIVE",
"tenant_id": ""}]

View File

@ -0,0 +1,61 @@
! Last configuration change at 08:58:07 UTC Fri Mar 03 2017 by stack
!
vrf definition Mgmt-intf
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
vrf definition nrouter-085eba
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
!
interface GigabitEthernet/1/0/2.1086
description OPENSTACK_NEUTRON_INTF
encapsulation dot1Q 1086
ip address 10.0.3.3 255.255.255.0
ip nat inside
standby 1064 ip 10.0.3.1
standby 1064 name neutron-hsrp-1064-1086
standby 1064 priority 97
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
vrf forwarding nrouter-085eba
!
interface GigabitEthernet/2/0/3.1056
description OPENSTACK_NEUTRON_EXTERNAL_INTF
encapsulation dot1Q 1056
ip address 172.16.6.47 255.255.255.224 secondary
ip address 172.17.7.37 255.255.255.224
ip nat outside
standby 1064 ip 172.16.6.46 secondary
standby 1064 ip 172.17.7.36
standby 1064 name neutron-hsrp-1064-1056
standby 1064 priority 100
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
!
interface GigabitEthernet0
ip address 10.0.100.6 255.255.255.0
negotiation auto
vrf forwarding Mgmt-intf
!
ip access-list standard neutron_acl_1086_121bf217
permit 10.0.3.0 0.0.0.255
!
ip nat inside source list neutron_acl_1086_121bf217 pool nrouter-085eba_nat_pool vrf nrouter-085eba overload
ip nat pool nrouter-085eba_nat_pool 172.16.6.44 172.16.6.44 netmask 255.255.255.224
ip nat pool nrouter-085eba_nat_pool 172.17.7.34 172.17.7.34 netmask 255.255.255.224
!
ip route vrf nrouter-085eba 0.0.0.0 0.0.0.0 GigabitEthernet/2/0/3.1056 172.16.6.33
ip route vrf nrouter-085eba 0.0.0.0 0.0.0.0 GigabitEthernet/2/0/3.1056 172.17.7.33
!

View File

@ -0,0 +1,61 @@
! Last configuration change at 08:58:07 UTC Fri Mar 03 2017 by stack
!
vrf definition Mgmt-intf
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
vrf definition nrouter-5dd41c
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
!
interface GigabitEthernet/1/0/4.1086
description OPENSTACK_NEUTRON_INTF
encapsulation dot1Q 1086
ip address 10.0.3.2 255.255.255.0
ip nat inside
standby 1064 ip 10.0.3.1
standby 1064 name neutron-hsrp-1064-1086
standby 1064 priority 100
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
vrf forwarding nrouter-5dd41c
!
interface GigabitEthernet/1/0/5.1056
description OPENSTACK_NEUTRON_EXTERNAL_INTF
encapsulation dot1Q 1056
ip address 172.16.6.48 255.255.255.224 secondary
ip address 172.17.7.38 255.255.255.224
ip nat outside
standby 1064 ip 172.16.6.46 secondary
standby 1064 ip 172.17.7.36
standby 1064 name neutron-hsrp-1064-1056
standby 1064 priority 103
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
!
interface GigabitEthernet0
ip address 10.0.100.7 255.255.255.0
negotiation auto
vrf forwarding Mgmt-intf
!
ip access-list standard neutron_acl_1086_0b9c4564
permit 10.0.3.0 0.0.0.255
!
ip nat inside source list neutron_acl_1086_0b9c4564 pool nrouter-5dd41c_nat_pool vrf nrouter-5dd41c overload
ip nat pool nrouter-5dd41c_nat_pool 172.16.6.44 172.16.6.44 netmask 255.255.255.224
ip nat pool nrouter-5dd41c_nat_pool 172.17.7.34 172.17.7.34 netmask 255.255.255.224
!
ip route vrf nrouter-5dd41c 0.0.0.0 0.0.0.0 GigabitEthernet/1/0/5.1056 172.16.6.33
ip route vrf nrouter-5dd41c 0.0.0.0 0.0.0.0 GigabitEthernet/1/0/5.1056 172.17.7.33
!

View File

@ -0,0 +1,254 @@
(neutron) net-list
+--------------------------------------+-----------+-----------------------------------------------------+
| id | name | subnets |
+--------------------------------------+-----------+-----------------------------------------------------+
| 02232008-c78c-46b2-b712-678d85def46a | private | 54074049-aaf1-44d2-9843-99cdb10e3212 10.0.3.0/24 |
| 7a382985-4c58-4912-beb3-84fcf7d7af77 | public-2 | 7459de26-e9e2-491a-b174-db9f4d7313b8 172.17.8.32/27 |
| 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 | public | 7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41 172.16.6.32/27 |
| | | 05509041-00e0-45c3-bf38-c603911c1ea4 172.17.7.32/27 |
| cd04cc62-1799-4727-8f54-a2b4ec1a8bd2 | private-2 | 1af47d42-149e-423f-883f-5369ab11a9a0 10.0.4.0/24 |
+--------------------------------------+-----------+-----------------------------------------------------+
(neutron) subnet-list
+--------------------------------------+------------------+----------------+------------------------------------------------+
| id | name | cidr | allocation_pools |
+--------------------------------------+------------------+----------------+------------------------------------------------+
| 7459de26-e9e2-491a-b174-db9f4d7313b8 | public-2-subnet | 172.17.8.32/27 | {"start": "172.17.8.34", "end": "172.17.8.62"} |
| 1af47d42-149e-423f-883f-5369ab11a9a0 | private-2-subnet | 10.0.4.0/24 | {"start": "10.0.4.2", "end": "10.0.4.254"} |
| 54074049-aaf1-44d2-9843-99cdb10e3212 | private-subnet | 10.0.3.0/24 | {"start": "10.0.3.2", "end": "10.0.3.254"} |
| 05509041-00e0-45c3-bf38-c603911c1ea4 | public-subnet-2 | 172.17.7.32/27 | {"start": "172.17.7.34", "end": "172.17.7.62"} |
| 7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41 | public-subnet | 172.16.6.32/27 | {"start": "172.16.6.34", "end": "172.16.6.62"} |
+--------------------------------------+------------------+----------------+------------------------------------------------+
(neutron) router-list
+--------------------------------------+---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | external_gateway_info |
+--------------------------------------+---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 085eba49-7ec9-470a-ac37-e89606eba108 | router1_HA_backup_1 | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": |
| | | "172.16.6.45"}, {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"}]} |
| 25ecf24d-a3eb-426f-8871-22d7e78c5944 | Global-router-0000-000000000005 | null |
| 5dd41cc4-7cbd-444f-894b-589531d3686c | routerOne | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": |
| | | "172.16.6.44"}, {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.34"}]} |
| 71810702-bcc0-4718-9f62-1f16609084d0 | router2_HA_backup_1 | {"network_id": "7a382985-4c58-4912-beb3-84fcf7d7af77", "external_fixed_ips": [{"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": |
| | | "172.17.8.37"}]} |
| 945d631c-0b37-4322-8dbe-c3759a3cac45 | Logical-Global-router | null |
| b1e18b85-75ef-49e2-9eda-a5ddce09d777 | router2 | {"network_id": "7a382985-4c58-4912-beb3-84fcf7d7af77", "external_fixed_ips": [{"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": |
| | | "172.17.8.36"}]} |
| c5c5eb9e-4451-4936-9125-9a9634cb5d2e | Global-router-0000-000000000004 | null |
+--------------------------------------+---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list router1
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 780a2d1a-6cae-4b2e-919e-bb5fb0ee0395 | | fa:16:3e:37:e3:d7 | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.44"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.34"} |
| 9747b0d0-9380-4674-8cd9-9bc0db62355c | | fa:16:3e:ae:75:c5 | {"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212", "ip_address": "10.0.3.1"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show router1
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:details | {"redundancy_routers": [{"priority": 97, "state": "STANDBY", "id": "085eba49-7ec9-470a-ac37-e89606eba108"}], "probe_connectivity": false, "priority": 100, "state": "ACTIVE", |
| | "redundancy_level": 1, "type": "HSRP"} |
| cisco_ha:enabled | True |
| description | |
| external_gateway_info | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.44"}, {"subnet_id": |
| | "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.34"}]} |
| id | 5dd41cc4-7cbd-444f-894b-589531d3686c |
| name | router1 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000005 |
| routerrole:role | |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | 840995fdaaf44ad4ab972f06fd6fbc13 |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list router2_HA_backup_1
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 050aee56-f6a8-496a-a1af-2c7a57ca93d1 | | fa:16:3e:58:cb:03 | {"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": "172.17.8.37"} |
| e626fe6a-ee02-4453-8b81-59ba5efe92f8 | | fa:16:3e:0e:51:cc | {"subnet_id": "1af47d42-149e-423f-883f-5369ab11a9a0", "ip_address": "10.0.4.3"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show router2_HA_backup_1
+-------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | {"network_id": "7a382985-4c58-4912-beb3-84fcf7d7af77", "external_fixed_ips": [{"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": "172.17.8.37"}]} |
| id | 71810702-bcc0-4718-9f62-1f16609084d0 |
| name | router2_HA_backup_1 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000005 |
| routerrole:role | HA-Redundancy |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list Global-router-0000-000000000005
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 2a66a97a-3b53-4847-88b5-4fdeba6d42c7 | | fa:16:3e:c0:28:2b | {"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": "172.17.8.39"} |
| e678299a-0fbb-43f1-915c-a1c48c676bc6 | | fa:16:3e:04:d1:66 | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.48"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.38"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show Global-router-0000-000000000005
+-------------------------------------------------+--------------------------------------+
| Field | Value |
+-------------------------------------------------+--------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | |
| id | 25ecf24d-a3eb-426f-8871-22d7e78c5944 |
| name | Global-router-0000-000000000005 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000005 |
| routerrole:role | Global |
| routertype-aware-scheduler:auto_schedule | False |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+--------------------------------------+
(neutron) router-port-list router1_HA_backup_1
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 121bf217-7224-435a-bb23-fdb9c79b35c1 | | fa:16:3e:33:26:8e | {"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212", "ip_address": "10.0.3.3"} |
| 53e1c49f-8bad-4dc3-8e19-2202ab08fe53 | | fa:16:3e:fe:b7:79 | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.45"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show router1_HA_backup_1
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | {"network_id": "9d81f2da-eb8b-4c61-b247-ca3fe85a7838", "external_fixed_ips": [{"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.45"}, {"subnet_id": |
| | "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.35"}]} |
| id | 085eba49-7ec9-470a-ac37-e89606eba108 |
| name | router1_HA_backup_1 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000004 |
| routerrole:role | HA-Redundancy |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list router2
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 3582f930-df68-421d-b62e-e7dbcc424deb | | fa:16:3e:ee:95:e4 | {"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": "172.17.8.36"} |
| 8f6ec549-a879-4893-8cac-fab3911c8e45 | | fa:16:3e:07:76:1c | {"subnet_id": "1af47d42-149e-423f-883f-5369ab11a9a0", "ip_address": "10.0.4.1"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show router2
+-------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | True |
| cisco_ha:details | {"redundancy_routers": [{"priority": 97, "state": "STANDBY", "id": "71810702-bcc0-4718-9f62-1f16609084d0"}], "probe_connectivity": false, "priority": 100, "state": "ACTIVE", |
| | "redundancy_level": 1, "type": "HSRP"} |
| cisco_ha:enabled | True |
| description | |
| external_gateway_info | {"network_id": "7a382985-4c58-4912-beb3-84fcf7d7af77", "external_fixed_ips": [{"subnet_id": "7459de26-e9e2-491a-b174-db9f4d7313b8", "ip_address": "172.17.8.36"}]} |
| id | b1e18b85-75ef-49e2-9eda-a5ddce09d777 |
| name | router2 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000004 |
| routerrole:role | |
| routertype-aware-scheduler:auto_schedule | True |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | 840995fdaaf44ad4ab972f06fd6fbc13 |
+-------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
(neutron) router-port-list Global-router-0000-000000000004
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| id | name | mac_address | fixed_ips |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
| 5931d51b-7806-4dd9-a024-2ed1c674782a | | fa:16:3e:40:96:dd | {"subnet_id": "7b3f7882-867e-4e6c-a9b3-a8f6ce3abd41", "ip_address": "172.16.6.47"} |
| | | | {"subnet_id": "05509041-00e0-45c3-bf38-c603911c1ea4", "ip_address": "172.17.7.37"} |
+--------------------------------------+------+-------------------+------------------------------------------------------------------------------------+
(neutron) router-show Global-router-0000-000000000004
+-------------------------------------------------+--------------------------------------+
| Field | Value |
+-------------------------------------------------+--------------------------------------+
| admin_state_up | True |
| cisco_ha:enabled | False |
| description | |
| external_gateway_info | |
| id | c5c5eb9e-4451-4936-9125-9a9634cb5d2e |
| name | Global-router-0000-000000000004 |
| routerhost:hosting_device | 00000000-0000-0000-0000-000000000004 |
| routerrole:role | Global |
| routertype-aware-scheduler:auto_schedule | False |
| routertype-aware-scheduler:share_hosting_device | True |
| routertype:id | 00000000-0000-0000-0000-000000000003 |
| routes | |
| status | ACTIVE |
| tenant_id | |
+-------------------------------------------------+--------------------------------------+
mysql> select id,device_owner,device_id,network_id from ports;
+--------------------------------------+--------------------------+--------------------------------------+--------------------------------------+
| id | device_owner | device_id | network_id |
+--------------------------------------+--------------------------+--------------------------------------+--------------------------------------+
| 050aee56-f6a8-496a-a1af-2c7a57ca93d1 | network:router_gateway | 71810702-bcc0-4718-9f62-1f16609084d0 | 7a382985-4c58-4912-beb3-84fcf7d7af77 |
| 0b9c4564-9e42-4dfd-ab96-2cabee626aec | network:router_interface | 312cc5db-8749-46fe-82d9-d8492267902d | 02232008-c78c-46b2-b712-678d85def46a |
| 121bf217-7224-435a-bb23-fdb9c79b35c1 | network:router_interface | 085eba49-7ec9-470a-ac37-e89606eba108 | 02232008-c78c-46b2-b712-678d85def46a |
| 2a66a97a-3b53-4847-88b5-4fdeba6d42c7 | network:router_interface | 25ecf24d-a3eb-426f-8871-22d7e78c5944 | 7a382985-4c58-4912-beb3-84fcf7d7af77 |
| 3582f930-df68-421d-b62e-e7dbcc424deb | network:router_gateway | b1e18b85-75ef-49e2-9eda-a5ddce09d777 | 7a382985-4c58-4912-beb3-84fcf7d7af77 |
| 3ad3a3d6-1533-4572-8e13-c655f8f7a701 | network:router_interface | 945d631c-0b37-4322-8dbe-c3759a3cac45 | 7a382985-4c58-4912-beb3-84fcf7d7af77 |
| 3fdf36c5-34a7-4aa3-8508-66b258377a68 | network:router_interface | 945d631c-0b37-4322-8dbe-c3759a3cac45 | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 53e1c49f-8bad-4dc3-8e19-2202ab08fe53 | network:router_gateway | 085eba49-7ec9-470a-ac37-e89606eba108 | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 5931d51b-7806-4dd9-a024-2ed1c674782a | network:router_interface | c5c5eb9e-4451-4936-9125-9a9634cb5d2e | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 780a2d1a-6cae-4b2e-919e-bb5fb0ee0395 | network:router_gateway | 5dd41cc4-7cbd-444f-894b-589531d3686c | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| 8850d162-03ee-4b63-8d5a-632ef2e538d9 | network:router_interface | 125973e6-42dd-4e9a-8eed-38cb21b8b30f | cd04cc62-1799-4727-8f54-a2b4ec1a8bd2 |
| 8f6ec549-a879-4893-8cac-fab3911c8e45 | network:router_interface | b1e18b85-75ef-49e2-9eda-a5ddce09d777 | cd04cc62-1799-4727-8f54-a2b4ec1a8bd2 |
| 9747b0d0-9380-4674-8cd9-9bc0db62355c | network:router_interface | 5dd41cc4-7cbd-444f-894b-589531d3686c | 02232008-c78c-46b2-b712-678d85def46a |
| e626fe6a-ee02-4453-8b81-59ba5efe92f8 | network:router_interface | 71810702-bcc0-4718-9f62-1f16609084d0 | cd04cc62-1799-4727-8f54-a2b4ec1a8bd2 |
| e678299a-0fbb-43f1-915c-a1c48c676bc6 | network:router_interface | 25ecf24d-a3eb-426f-8871-22d7e78c5944 | 9d81f2da-eb8b-4c61-b247-ca3fe85a7838 |
| f06164a0-8d91-4a7e-bcde-ab9a7887c978 | | | 02232008-c78c-46b2-b712-678d85def46a |
| fe89f2e3-a07a-4ae9-ad9b-b5090ddac1d1 | network:router_interface | c5c5eb9e-4451-4936-9125-9a9634cb5d2e | 7a382985-4c58-4912-beb3-84fcf7d7af77 |
+--------------------------------------+--------------------------+--------------------------------------+--------------------------------------+
17 rows in set (0.00 sec)
(neutron) port-show private-port-1
+-----------------------+---------------------------------------------------------------------------------+
| Field | Value |
+-----------------------+---------------------------------------------------------------------------------+
| admin_state_up | True |
| allowed_address_pairs | |
| binding:host_id | |
| binding:profile | {} |
| binding:vif_details | {} |
| binding:vif_type | unbound |
| binding:vnic_type | normal |
| created_at | 2017-03-07T12:08:30 |
| description | |
| device_id | |
| device_owner | |
| extra_dhcp_opts | |
| fixed_ips | {"subnet_id": "54074049-aaf1-44d2-9843-99cdb10e3212", "ip_address": "10.0.3.4"} |
| id | f06164a0-8d91-4a7e-bcde-ab9a7887c978 |
| mac_address | fa:16:3e:7b:45:2b |
| name | private-port-1 |
| network_id | 02232008-c78c-46b2-b712-678d85def46a |
| port_security_enabled | True |
| security_groups | f52fa760-8849-4612-a592-3714166c20c3 |
| status | DOWN |
| tenant_id | 840995fdaaf44ad4ab972f06fd6fbc13 |
| updated_at | 2017-03-07T13:01:55 |
+-----------------------+---------------------------------------------------------------------------------+

View File

@ -0,0 +1,111 @@
! Last configuration change at 13:03:29 UTC Tue Mar 07 2017 by stack
!
hostname ASR-1002X-10_0_100_6
!
boot-start-marker
boot system flash bootflash:/asr1002x-simulated.03.16.00.S-ext.SPA.bin
boot-end-marker
!
vrf definition Mgmt-intf
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
vrf definition nrouter-085eba
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
vrf definition nrouter-b1e18b
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
!
interface GigabitEthernet/1/0/2.1050
description OPENSTACK_NEUTRON_INTF
encapsulation dot1Q 1050
ip address 10.0.4.2 255.255.255.0
ip nat inside
standby 1064 ip 10.0.4.1
standby 1064 name neutron-hsrp-1064-1050
standby 1064 priority 100
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
vrf forwarding nrouter-b1e18b
!
interface GigabitEthernet/1/0/2.1086
description OPENSTACK_NEUTRON_INTF
encapsulation dot1Q 1086
ip address 10.0.3.3 255.255.255.0
ip nat inside
standby 1064 ip 10.0.3.1
standby 1064 name neutron-hsrp-1064-1086
standby 1064 priority 97
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
vrf forwarding nrouter-085eba
!
interface GigabitEthernet/2/0/3.1018
description OPENSTACK_NEUTRON_EXTERNAL_INTF
encapsulation dot1Q 1018
ip address 172.17.8.40 255.255.255.224
ip nat outside
standby 1064 ip 172.17.8.38
standby 1064 name neutron-hsrp-1064-1018
standby 1064 priority 100
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
!
interface GigabitEthernet/2/0/3.1056
description OPENSTACK_NEUTRON_EXTERNAL_INTF
encapsulation dot1Q 1056
ip address 172.16.6.47 255.255.255.224 secondary
ip address 172.17.7.37 255.255.255.224
ip nat outside
standby 1064 ip 172.16.6.46 secondary
standby 1064 ip 172.17.7.36
standby 1064 name neutron-hsrp-1064-1056
standby 1064 priority 100
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
!
interface GigabitEthernet0
ip address 10.0.100.6 255.255.255.0
negotiation auto
vrf forwarding Mgmt-intf
!
ip access-list standard neutron_acl_1050_8850d162
permit 10.0.4.0 0.0.0.255
ip access-list standard neutron_acl_1086_121bf217
permit 10.0.3.0 0.0.0.255
!
ip nat inside source list neutron_acl_1050_8850d162 pool nrouter-b1e18b_nat_pool vrf nrouter-b1e18b overload
ip nat inside source list neutron_acl_1086_121bf217 pool nrouter-085eba_nat_pool vrf nrouter-085eba overload
ip nat pool nrouter-085eba_nat_pool 172.16.6.44 172.16.6.44 netmask 255.255.255.224
ip nat pool nrouter-085eba_nat_pool 172.17.7.34 172.17.7.34 netmask 255.255.255.224
ip nat pool nrouter-b1e18b_nat_pool 172.17.8.36 172.17.8.36 netmask 255.255.255.224
!
ip route vrf Mgmt - intf 0.0.0.0 0.0.0.0 10.0.100.1
ip route vrf nrouter-085eba 0.0.0.0 0.0.0.0 GigabitEthernet/2/0/3.1056 172.16.6.33
ip route vrf nrouter-085eba 0.0.0.0 0.0.0.0 GigabitEthernet/2/0/3.1056 172.17.7.33
ip route vrf nrouter-b1e18b 0.0.0.0 0.0.0.0 GigabitEthernet/2/0/3.1018 172.17.8.33
!
ip ssh source - interface GigabitEthernet0
ip ssh version 2
!
ip tftp source - interface GigabitEthernet0
!

View File

@ -0,0 +1,111 @@
! Last configuration change at 13:03:29 UTC Tue Mar 07 2017 by stack
!
hostname ASR-1002X-10_0_100_7
!
boot-start-marker
boot system flash bootflash:/asr1002x-simulated.03.16.00.S-ext.SPA.bin
boot-end-marker
!
vrf definition Mgmt-intf
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
vrf definition nrouter-5dd41c
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
vrf definition nrouter-718107
!
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
!
interface GigabitEthernet/1/0/4.1050
description OPENSTACK_NEUTRON_INTF
encapsulation dot1Q 1050
ip address 10.0.4.3 255.255.255.0
ip nat inside
standby 1064 ip 10.0.4.1
standby 1064 name neutron-hsrp-1064-1050
standby 1064 priority 97
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
vrf forwarding nrouter-718107
!
interface GigabitEthernet/1/0/4.1086
description OPENSTACK_NEUTRON_INTF
encapsulation dot1Q 1086
ip address 10.0.3.2 255.255.255.0
ip nat inside
standby 1064 ip 10.0.3.1
standby 1064 name neutron-hsrp-1064-1086
standby 1064 priority 100
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
vrf forwarding nrouter-5dd41c
!
interface GigabitEthernet/1/0/5.1018
description OPENSTACK_NEUTRON_EXTERNAL_INTF
encapsulation dot1Q 1018
ip address 172.17.8.39 255.255.255.224
ip nat outside
standby 1064 ip 172.17.8.38
standby 1064 name neutron-hsrp-1064-1018
standby 1064 priority 103
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
!
interface GigabitEthernet/1/0/5.1056
description OPENSTACK_NEUTRON_EXTERNAL_INTF
encapsulation dot1Q 1056
ip address 172.16.6.48 255.255.255.224 secondary
ip address 172.17.7.38 255.255.255.224
ip nat outside
standby 1064 ip 172.16.6.46 secondary
standby 1064 ip 172.17.7.36
standby 1064 name neutron-hsrp-1064-1056
standby 1064 priority 103
standby 1064 timers 1 3
standby delay minimum 30 reload 60
standby version 2
!
interface GigabitEthernet0
ip address 10.0.100.7 255.255.255.0
negotiation auto
vrf forwarding Mgmt-intf
!
ip access-list standard neutron_acl_1050_e626fe6a
permit 10.0.4.0 0.0.0.255
ip access-list standard neutron_acl_1086_0b9c4564
permit 10.0.3.0 0.0.0.255
!
ip nat inside source list neutron_acl_1050_e626fe6a pool nrouter-718107_nat_pool vrf nrouter-718107 overload
ip nat inside source list neutron_acl_1086_0b9c4564 pool nrouter-5dd41c_nat_pool vrf nrouter-5dd41c overload
ip nat pool nrouter-5dd41c_nat_pool 172.16.6.44 172.16.6.44 netmask 255.255.255.224
ip nat pool nrouter-5dd41c_nat_pool 172.17.7.34 172.17.7.34 netmask 255.255.255.224
ip nat pool nrouter-718107_nat_pool 172.17.8.36 172.17.8.36 netmask 255.255.255.224
!
ip route vrf Mgmt - intf 0.0.0.0 0.0.0.0 10.0.100.1
ip route vrf nrouter-5dd41c 0.0.0.0 0.0.0.0 GigabitEthernet/1/0/5.1056 172.16.6.33
ip route vrf nrouter-5dd41c 0.0.0.0 0.0.0.0 GigabitEthernet/1/0/5.1056 172.17.7.33
ip route vrf nrouter-718107 0.0.0.0 0.0.0.0 GigabitEthernet/1/0/5.1018 172.17.8.33
!
ip ssh source - interface GigabitEthernet0
ip ssh version 2
!
ip tftp source - interface GigabitEthernet0
!

View File

@ -12,16 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import mock
from neutron.tests import base
from oslo_config import cfg
from oslo_serialization import jsonutils
from networking_cisco.plugins.cisco.cfg_agent.device_drivers.asr1k import (
asr1k_cfg_syncer)
from networking_cisco.plugins.cisco.cfg_agent.device_drivers.asr1k import (
asr1k_routing_driver as driver)
from networking_cisco.plugins.cisco.common.htparser import HTParser
@ -1261,6 +1262,93 @@ NEUTRON_DB = [
"tenant_id": "ecf8697e8dc04fef8be7c7f9c3594de9"
},
{
"_interfaces": [
{
"admin_state_up": True,
"allowed_address_pairs": [],
"binding:host_id": "asr1k-k7-controller-1-R2",
"binding:profile": {},
"binding:vif_details": {
"ovs_hybrid_plug": True,
"port_filter": True
},
"binding:vif_type": "ovs",
"binding:vnic_type": "normal",
"device_id": "213fd355-78c3-44cc-bd6e-492b9ade2602",
"device_owner": "network:router_interface",
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [
{
"ip_address": "172.16.0.105",
"prefixlen": 16,
"subnet_id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b"
}
],
"ha_info": {
"group": "1064",
"ha_port": {
"admin_state_up": True,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"device_id": "a2617b46-78ef-49ba-95b5-0f3ff90f1f91",
"device_owner": "network:router_interface",
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [{
"ip_address": "172.16.0.104",
"prefixlen": 16,
"subnet_id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b"
}],
"id": "b768491c-4b76-492f-a0ee-56bc50867a07",
"mac_address": "fa:16:3e:77:ae:bb",
"name": "",
"network_id": "7a38a5fd-3ad9-4952-ab08-4def22407269",
"security_groups": [],
"status": "DOWN",
"subnets": [
{
"cidr": "172.16.0.0/16",
"gateway_ip": "172.16.0.1",
"id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b",
"ipv6_ra_mode": None
}
],
"tenant_id": ""
},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"
},
"hosting_info": {
"hosting_mac": "fa:16:3e:97:ec:f2",
"hosting_port_id": "527b7bc0-d6ba-4d07-932a-60e96da86173",
"hosting_port_name": "",
"physical_interface": "Port-channel10",
"segmentation_id": 3000
},
"id": "527b7bc0-d6ba-4d07-932a-60e96da86173",
"mac_address": "fa:16:3e:97:ec:f2",
"name": "",
"network_id": "7a38a5fd-3ad9-4952-ab08-4def22407269",
"security_groups": [],
"status": "ACTIVE",
"subnets": [
{
"cidr": "172.16.0.0/16",
"gateway_ip": "172.16.0.1",
"id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b",
"ipv6_ra_mode": None
}
],
"tenant_id": ""
}
],
"admin_state_up": True,
"cisco_ha:details": {
"priority": 100,
@ -1291,94 +1379,7 @@ NEUTRON_DB = [
],
"network_id": "7a38a5fd-3ad9-4952-ab08-4def22407269"
},
"gw_port": {
"admin_state_up": True,
"allowed_address_pairs": [],
"binding:host_id": "asr1k-k7-controller-1-R2",
"binding:profile": {},
"binding:vif_details": {
"ovs_hybrid_plug": True,
"port_filter": True
},
"binding:vif_type": "ovs",
"binding:vnic_type": "normal",
"device_id": "213fd355-78c3-44cc-bd6e-492b9ade2602",
"device_owner": "network:router_gateway",
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [
{
"ip_address": "172.16.0.105",
"prefixlen": 16,
"subnet_id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b"
}
],
"ha_info": {
"group": "1064",
"ha_port": {
"admin_state_up": True,
"allowed_address_pairs": [],
"binding:host_id": "",
"binding:profile": {},
"binding:vif_details": {},
"binding:vif_type": "unbound",
"binding:vnic_type": "normal",
"device_id": "a2617b46-78ef-49ba-95b5-0f3ff90f1f91",
"device_owner": "network:router_gateway",
"extra_dhcp_opts": [],
"extra_subnets": [],
"fixed_ips": [
{
"ip_address": "172.16.0.104",
"prefixlen": 16,
"subnet_id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b"
}
],
"id": "b768491c-4b76-492f-a0ee-56bc50867a07",
"mac_address": "fa:16:3e:77:ae:bb",
"name": "",
"network_id": "7a38a5fd-3ad9-4952-ab08-4def22407269",
"security_groups": [],
"status": "DOWN",
"subnets": [
{
"cidr": "172.16.0.0/16",
"gateway_ip": "172.16.0.1",
"id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b",
"ipv6_ra_mode": None
}
],
"tenant_id": ""
},
"other_config": "",
"timers_config": "",
"tracking_config": "",
"type": "HSRP"
},
"hosting_info": {
"hosting_mac": "fa:16:3e:97:ec:f2",
"hosting_port_id": "527b7bc0-d6ba-4d07-932a-60e96da86173",
"hosting_port_name": "",
"physical_interface": "Port-channel10",
"segmentation_id": 3000
},
"id": "527b7bc0-d6ba-4d07-932a-60e96da86173",
"mac_address": "fa:16:3e:97:ec:f2",
"name": "",
"network_id": "7a38a5fd-3ad9-4952-ab08-4def22407269",
"security_groups": [],
"status": "ACTIVE",
"subnets": [
{
"cidr": "172.16.0.0/16",
"gateway_ip": "172.16.0.1",
"id": "8f9c885d-a2ad-4fff-8127-2d4b3af6015b",
"ipv6_ra_mode": None
}
],
"tenant_id": ""
},
"gw_port_id": "527b7bc0-d6ba-4d07-932a-60e96da86173",
"gw_port_id": None,
"hosting_device": {
"admin_state_up": True,
"booting_time": 360,
@ -1432,9 +1433,8 @@ class ASR1kCfgSyncer(base.BaseTestCase):
self.hosting_device_info = {
'id': '00000000-0000-0000-0000-000000000003'}
self.driver = mock.Mock()
self.config_syncer = asr1k_cfg_syncer.ConfigSyncer(self.router_db_info,
self.driver,
self.hosting_device_info)
self.config_syncer = asr1k_cfg_syncer.ConfigSyncer(
self.router_db_info, self.driver, self.hosting_device_info)
def test_delete_invalid_cfg_empty_routers_list(self):
"""
@ -1655,3 +1655,51 @@ class ASR1kCfgSyncer(base.BaseTestCase):
parsed_cfg)
self.assertEqual([], invalid_cfg)
def _test_clean_router_multi_ext_net(self, routers_dict_filename,
running_cfg_filename, hd_id,
expected_invalid_cfg=None):
if expected_invalid_cfg is None:
expected_invalid_cfg = []
path = os.path.dirname(os.path.abspath(__file__)) + '/'
with open(path + routers_dict_filename) as routers_dict_file:
r_dict_txt = routers_dict_file.read()
routers_dict = jsonutils.loads(r_dict_txt)
with open(path + running_cfg_filename) as running_config_file:
running_cfg = running_config_file.read()
hosting_device_info = {'id': hd_id}
config_syncer = asr1k_cfg_syncer.ConfigSyncer(
routers_dict, self.driver, hosting_device_info)
config_syncer.get_running_config = mock.Mock(
return_value=running_cfg)
invalid_cfg = config_syncer.delete_invalid_cfg()
self.assertEqual(expected_invalid_cfg, invalid_cfg)
def test_clean_router_with_two_subnet_gw(self):
self._test_clean_router_multi_ext_net(
'json/1/router_dicts_multi_subnets_ext_net.json',
'json/1/running_cfg_0005_multi_subnets_ext_net.txt',
'00000000-0000-0000-0000-000000000005')
def test_clean_ha_backup_router_with_two_subnet_gw(self):
self._test_clean_router_multi_ext_net(
'json/1/router_dicts_multi_subnets_ext_net.json',
'json/1/running_cfg_0004_multi_subnets_ext_net.txt',
'00000000-0000-0000-0000-000000000004')
def test_clean_routers_with_two_subnet_gw_and_single_subnet_gw(self):
self._test_clean_router_multi_ext_net(
'json/2/router_dicts_multi_subnets_ext_net_and_'
'single_subnet_ext_net.json',
'json/2/running_cfg_0005_multi_subnets_ext_net_and_'
'single_subnet_ext_net.txt',
'00000000-0000-0000-0000-000000000005')
def test_clean_ha_backup_routers_with_two_subnet_gw_and_single_subnet_gw(
self):
self._test_clean_router_multi_ext_net(
'json/2/router_dicts_multi_subnets_ext_net_and_'
'single_subnet_ext_net.json',
'json/2/running_cfg_0004_multi_subnets_ext_net_and_'
'single_subnet_ext_net.txt',
'00000000-0000-0000-0000-000000000004')

View File

@ -76,21 +76,25 @@ class ASR1kRoutingDriver(base.BaseTestCase):
self.ex_gw_cidr = '20.0.0.30/24'
self.ex_gw_ip_mask = '255.255.255.0'
self.ex_gw_ha_group = 1500
sn_id = _uuid()
self.ex_gw_ha_info = {'group': self.ex_gw_ha_group,
'ha_port': {
'fixed_ips': [{
'subnet_id': sn_id,
'ip_address': self.ex_gw_ip_vip,
'prefixlen': self.ex_gw_prefixlen}]}}
self.ex_gw_gateway_ip = '20.0.0.1'
self.vlan_ext = 317
self.phy_infc = 'GigabitEthernet0/0/0'
self.ex_gw_port = {'id': _uuid(),
'network_id': _uuid(),
'ip_info': {'subnet_id': sn_id,
'is_primary': True,
'ip_cidr': self.ex_gw_cidr},
'fixed_ips': [{'ip_address': self.ex_gw_ip,
'prefixlen': self.ex_gw_prefixlen,
'subnet_id': _uuid()}],
'subnets': [{'cidr': self.ex_gw_cidr,
'subnet_id': sn_id}],
'subnets': [{'id': sn_id, 'cidr': self.ex_gw_cidr,
'gateway_ip': self.ex_gw_gateway_ip}],
'device_owner': bc.constants.DEVICE_OWNER_ROUTER_GW,
'mac_address': 'ca:fe:de:ad:be:ef',
@ -109,21 +113,25 @@ class ASR1kRoutingDriver(base.BaseTestCase):
self.gw_ip_vip = '10.0.3.1'
self.gw_ip_mask = '255.255.255.0'
self.gw_ha_group = 1621
sn_id = _uuid()
self.gw_ha_info = {'group': self.gw_ha_group,
'ha_port': {
'fixed_ips': [{
'subnet_id': sn_id,
'ip_address': self.gw_ip_vip,
'prefixlen': self.gw_prefixlen}]}}
self.port = {'id': PORT_ID,
'ip_cidr': self.gw_ip_cidr,
'fixed_ips': [{'ip_address': self.gw_ip}],
'subnets': [{'cidr': self.gw_ip_cidr,
'ip_info': {'subnet_id': sn_id,
'is_primary': True,
'ip_cidr': self.gw_ip_cidr},
'fixed_ips': [{'ip_address': self.gw_ip,
'subnet_id': sn_id}],
'subnets': [{'id': sn_id, 'cidr': self.gw_ip_cidr,
'gateway_ip': self.gw_ip}],
'hosting_info': {
'physical_interface': self.phy_infc,
'segmentation_id': self.vlan_int},
HA_INFO: self.gw_ha_info
}
HA_INFO: self.gw_ha_info}
int_ports = [self.port]
self.floating_ip = '20.0.0.35'
self.fixed_ip = '10.0.3.5'
@ -165,8 +173,7 @@ class ASR1kRoutingDriver(base.BaseTestCase):
'state': 'ACTIVE',
'type': 'HSRP'}
self.global_router[ha.DETAILS] = self.cisco_ha_details_global
self.global_router['gw_port'][HA_INFO]['ha_port']['fixed_ips'][0][
'ip_address'] = self.ex_gw_ip_vip
self.global_router['gw_port'] = None
self.ri_global = routing_svc_helper.RouterInfo(
FAKE_ID, self.global_router)
self.ri_global.internal_ports = int_ports
@ -246,6 +253,20 @@ class ASR1kRoutingDriver(base.BaseTestCase):
self.assert_edit_run_cfg(
snippets.SET_INTC_ASR_HSRP_EXTERNAL, cfg_args_hsrp)
def test_internal_network_added_global_router_secondary_subnet(self):
self.port['ip_info']['is_primary'] = False
self.global_router[bc.constants.INTERFACE_KEY][0]['ip_info'][
'is_primary'] = False
self.driver.internal_network_added(self.ri_global, self.port)
sub_interface = self.phy_infc + '.' + str(self.vlan_int)
cfg_args_sub = (sub_interface, self.gw_ip, self.gw_ip_mask)
self.assert_edit_run_cfg(
snippets.SET_SUBINTERFACE_SECONDARY_IP, cfg_args_sub)
cfg_args_hsrp = (sub_interface, self.gw_ha_group, self.gw_ip_vip)
self.assert_edit_run_cfg(
snippets.SET_INTC_ASR_SECONDARY_HSRP_EXTERNAL, cfg_args_hsrp)
def test_internal_network_added_global_router_with_multi_region(self):
cfg.CONF.set_override('enable_multi_region', True, 'multi_region')
is_multi_region_enabled = cfg.CONF.multi_region.enable_multi_region
@ -265,6 +286,25 @@ class ASR1kRoutingDriver(base.BaseTestCase):
self.assert_edit_run_cfg(
snippets.SET_INTC_ASR_HSRP_EXTERNAL, cfg_args_hsrp)
def test_internal_network_added_global_router_with_multi_region_sec_sn(
self):
cfg.CONF.set_override('enable_multi_region', True, 'multi_region')
is_multi_region_enabled = cfg.CONF.multi_region.enable_multi_region
self.assertEqual(True, is_multi_region_enabled)
self.port['ip_info']['is_primary'] = False
self.global_router[bc.constants.INTERFACE_KEY][0]['ip_info'][
'is_primary'] = False
self.driver.internal_network_added(self.ri_global, self.port)
sub_interface = self.phy_infc + '.' + str(self.vlan_int)
cfg_args_sub = (sub_interface, self.gw_ip, self.gw_ip_mask)
self.assert_edit_run_cfg(
snippets.SET_SUBINTERFACE_SECONDARY_IP, cfg_args_sub)
cfg_args_hsrp = (sub_interface, self.gw_ha_group, self.gw_ip_vip)
self.assert_edit_run_cfg(
snippets.SET_INTC_ASR_SECONDARY_HSRP_EXTERNAL, cfg_args_hsrp)
def _make_test_router_non_ha(self):
self.ri.router[ha.ENABLED] = False
del self.ri.router[ha.DETAILS]

View File

@ -37,25 +37,43 @@ HOST = 'myhost'
FAKE_ID = _uuid()
def prepare_router_data(enable_snat=None, num_internal_ports=1):
def prepare_router_data(enable_snat=None, num_internal_ports=1,
num_subnets=1, is_global=False):
router_id = _uuid()
ext_fixed_ips = []
ext_subnets = []
sn_ids = sorted([_uuid() for i in range(num_subnets)])
for i in range(num_subnets):
sn_id = sn_ids[i]
ext_fixed_ips.append({'ip_address': '19.4.%s.4' % i,
'subnet_id': sn_id})
ext_subnets.append({'id': sn_id, 'cidr': '19.4.%s.0/24' % i,
'gateway_ip': '19.4.%s.1' % i})
ex_gw_port = {'id': _uuid(),
'network_id': _uuid(),
'admin_state_up': True,
'fixed_ips': [{'ip_address': '19.4.4.4',
'subnet_id': _uuid()}],
'subnets': [{'cidr': '19.4.4.0/24',
'gateway_ip': '19.4.4.1'}]}
'fixed_ips': ext_fixed_ips,
'subnets': ext_subnets}
int_ports = []
for i in range(num_internal_ports):
num_internal_subnets = 1 if is_global is False else num_subnets
for j in range(num_internal_ports):
k = 35 + j
int_fixed_ips = []
int_subnets = []
sn_ids = sorted([_uuid() for i in range(num_internal_subnets)])
for i in range(num_internal_subnets):
sn_id = sn_ids[i]
int_fixed_ips.append({'ip_address': '%s.4.%s.4' % (k, i),
'subnet_id': sn_id})
int_subnets.append({'id': sn_id, 'cidr': '%s.4.%s.0/24' % (k, i),
'gateway_ip': '%s.4.%s.1' % (k, i)})
int_ports.append({'id': _uuid(),
'network_id': _uuid(),
'admin_state_up': True,
'fixed_ips': [{'ip_address': '35.4.%s.4' % i,
'subnet_id': _uuid()}],
'fixed_ips': int_fixed_ips,
'mac_address': 'ca:fe:de:ad:be:ef',
'subnets': [{'cidr': '35.4.%s.0/24' % i,
'gateway_ip': '35.4.%s.1' % i}]})
'subnets': int_subnets})
hosting_device = {'id': _uuid(),
"name": "CSR1kv_template",
"booting_time": 300,
@ -72,10 +90,14 @@ def prepare_router_data(enable_snat=None, num_internal_ports=1):
'admin_state_up': True,
bc.constants.INTERFACE_KEY: int_ports,
'routes': [],
'gw_port': ex_gw_port,
'hosting_device': hosting_device,
'router_type': '',
routerrole.ROUTER_ROLE_ATTR: None}
'router_type': ''}
if is_global is True:
router['gw_port'] = None
router[routerrole.ROUTER_ROLE_ATTR] = c_constants.ROUTER_ROLE_GLOBAL
else:
router['gw_port'] = ex_gw_port
router[routerrole.ROUTER_ROLE_ATTR] = None
if enable_snat is not None:
router['enable_snat'] = enable_snat
return router, int_ports
@ -126,12 +148,13 @@ class TestBasicRoutingOperations(base.BaseTestCase):
self.conf = cfg.ConfigOpts()
self.conf.register_opts(bc.core_opts)
self.conf.register_opts(cfg_agent.OPTS, "cfg_agent")
sn_id = _uuid()
self.ex_gw_port = {'id': _uuid(),
'network_id': _uuid(),
'admin_state_up': True,
'fixed_ips': [{'ip_address': '19.4.4.4',
'subnet_id': _uuid()}],
'subnets': [{'cidr': '19.4.4.0/24',
'subnet_id': sn_id}],
'subnets': [{'id': sn_id, 'cidr': '19.4.4.0/24',
'gateway_ip': '19.4.4.1'}]}
self.hosting_device = {'id': "100",
'name': "CSR1kv_template",
@ -221,6 +244,27 @@ class TestBasicRoutingOperations(base.BaseTestCase):
self.assertRaises(SessionCloseError,
self.routing_helper._process_router, ri)
def test_process_router_throw_no_ip_address_on_subnet_error(self):
router, ports = prepare_router_data()
# change subnet_id to something that does not exist
router['gw_port']['subnets'][0]['id'] = 'fake_uuid'
ri = routing_svc_helper.RouterInfo(router['id'], router)
self.assertRaises(routing_svc_helper.IPAddressMissingException,
self.routing_helper._process_router, ri)
def _test_process_router_throw_multiple_ipv4_subnets_error(self):
router, ports = prepare_router_data(num_subnets=2, is_global=True)
# make router a regular one which triggers the error condition
router[routerrole.ROUTER_ROLE_ATTR] = None
ri = routing_svc_helper.RouterInfo(router['id'], router)
return ri, router
def test_process_router_throw_multiple_ipv4_subnets_error(self):
ri, router = (
self._test_process_router_throw_multiple_ipv4_subnets_error())
self.assertRaises(routing_svc_helper.MultipleIPv4SubnetsException,
self.routing_helper._process_router, ri)
def _test_router_admin_port_state(self, router, ri, ex_gw_port):
# change the router admin_state_up to false
router['admin_state_up'] = False
@ -252,9 +296,30 @@ class TestBasicRoutingOperations(base.BaseTestCase):
self.assertFalse(self.routing_helper._disable_router_interface.called)
self._reset_mocks()
def test_process_router(self, test_admin_state=True):
router, ports = prepare_router_data()
#Setup mock for call to proceess floating ips
# msn means that the router has an external gateway with multiple subnets
def _test_process_msn_router(self, num_ext_subnets=3,
test_admin_state=True):
def _verify_ip_info(the_mock):
self.assertEqual(num_ext_subnets, len(the_mock.ip_infos))
self.assertTrue(the_mock.ip_infos[0]['is_primary'])
self.assertEqual('19.4.0.4/24', the_mock.ip_infos[0]['ip_cidr'])
for i in range(1, num_ext_subnets):
self.assertFalse(the_mock.ip_infos[i]['is_primary'])
self.assertEqual('19.4.%s.4/24' % i,
the_mock.ip_infos[i]['ip_cidr'])
# need these helpers to verify that ip_info is correct
def _ext_gw_added(ri, ex_gw_port):
self.routing_helper._external_gateway_added.ip_infos.append(
copy.deepcopy(ex_gw_port['ip_info']))
def _ext_gw_removed(ri, ex_gw_port):
self.routing_helper._external_gateway_removed.ip_infos.append(
copy.deepcopy(ex_gw_port['ip_info']))
router, ports = prepare_router_data(num_subnets=num_ext_subnets)
# Setup mock for call to process floating ips
self.routing_helper._process_router_floating_ips = mock.Mock()
fake_floatingips1 = {'floatingips': [
{'id': _uuid(),
@ -262,17 +327,18 @@ class TestBasicRoutingOperations(base.BaseTestCase):
'fixed_ip_address': '7.7.7.7',
'port_id': _uuid()}]}
ri = routing_svc_helper.RouterInfo(router['id'], router=router)
self.routing_helper._external_gateway_added.ip_infos = []
self.routing_helper._external_gateway_added.side_effect = _ext_gw_added
# Process with initial values
self.routing_helper._process_router(ri)
ex_gw_port = ri.router.get('gw_port')
# Assert that process_floating_ips, internal_network & external network
# added were all called with the right params
self.routing_helper._process_router_floating_ips.assert_called_with(
ri, ex_gw_port)
self.routing_helper._internal_network_added.assert_called_with(
(self.routing_helper._process_router_floating_ips
.assert_called_once_with(ri, ex_gw_port))
self.routing_helper._internal_network_added.assert_called_once_with(
ri, ports[0], ex_gw_port)
self.routing_helper._external_gateway_added.assert_called_with(
ri, ex_gw_port)
_verify_ip_info(self.routing_helper._external_gateway_added)
self._reset_mocks()
# remap floating IP to a new fixed ip
fake_floatingips2 = copy.deepcopy(fake_floatingips1)
@ -283,8 +349,8 @@ class TestBasicRoutingOperations(base.BaseTestCase):
# was only called.
self.routing_helper._process_router(ri)
ex_gw_port = ri.router.get('gw_port')
self.routing_helper._process_router_floating_ips.assert_called_with(
ri, ex_gw_port)
(self.routing_helper._process_router_floating_ips
.assert_called_once_with(ri, ex_gw_port))
self.assertFalse(self.routing_helper._internal_network_added.called)
self.assertFalse(self.routing_helper._external_gateway_added.called)
self._reset_mocks()
@ -294,8 +360,8 @@ class TestBasicRoutingOperations(base.BaseTestCase):
# process_floating_ips and external_network remove was called
self.routing_helper._process_router(ri)
ex_gw_port = ri.router.get('gw_port')
self.routing_helper._process_router_floating_ips.assert_called_with(
ri, ex_gw_port)
(self.routing_helper._process_router_floating_ips
.assert_called_once_with(ri, ex_gw_port))
self.assertFalse(self.routing_helper._internal_network_added.called)
self.assertFalse(self.routing_helper._external_gateway_added.called)
self._reset_mocks()
@ -310,18 +376,79 @@ class TestBasicRoutingOperations(base.BaseTestCase):
ri.router = router
# Keep a copy of the ex_gw_port before its gone after processing.
ex_gw_port = ri.ex_gw_port
self.routing_helper._external_gateway_removed.ip_infos = []
self.routing_helper._external_gateway_removed.side_effect = (
_ext_gw_removed)
# Process router and verify that internal and external network removed
# were called and floating_ips_process was called
self.routing_helper._process_router(ri)
self.assertFalse(self.routing_helper.
_process_router_floating_ips.called)
self.assertFalse(self.routing_helper._external_gateway_added.called)
self.assertTrue(self.routing_helper._internal_network_removed.called)
self.assertTrue(self.routing_helper._external_gateway_removed.called)
self.routing_helper._internal_network_removed.assert_called_with(
self.routing_helper._internal_network_removed.assert_called_once_with(
ri, ports[0], ex_gw_port)
self.routing_helper._external_gateway_removed.assert_called_with(
ri, ex_gw_port)
_verify_ip_info(self.routing_helper._external_gateway_removed)
def test_process_router(self, test_admin_state=True):
self._test_process_msn_router(num_ext_subnets=1,
test_admin_state=test_admin_state)
def test_process_msn_router(self):
self._test_process_msn_router()
def _test_process_global_msn_router(self, num_ext_subnets=3):
def _verify_ip_info(the_mock):
self.assertEqual(num_ext_subnets, len(the_mock.ip_infos))
self.assertTrue(the_mock.ip_infos[0]['is_primary'])
self.assertEqual('35.4.0.4/24', the_mock.ip_infos[0]['ip_cidr'])
for i in range(1, num_ext_subnets):
self.assertFalse(the_mock.ip_infos[i]['is_primary'])
self.assertEqual('35.4.%s.4/24' % i,
the_mock.ip_infos[i]['ip_cidr'])
# need these helpers to verify that ip_info is correct
def _int_nw_added(ri, port, ex_gw_port):
self.assertIsNone(ex_gw_port)
self.routing_helper._internal_network_added.ip_infos.append(
copy.deepcopy(port['ip_info']))
router, ports = prepare_router_data(num_subnets=num_ext_subnets,
is_global=True)
# Setup mock for call to process floating ips
self.routing_helper._process_router_floating_ips = mock.Mock()
ri = routing_svc_helper.RouterInfo(router['id'], router=router)
self.routing_helper._internal_network_added.ip_infos = []
self.routing_helper._internal_network_added.side_effect = _int_nw_added
# Process with initial values
self.routing_helper._process_router(ri)
self.assertFalse(self.routing_helper.
_process_router_floating_ips.called)
self.assertFalse(self.routing_helper._external_gateway_added.called)
_verify_ip_info(self.routing_helper._internal_network_added)
self._reset_mocks()
# now no ports so state is torn down
del router[bc.constants.INTERFACE_KEY]
# Update router_info object
ri.router = router
# Process router and verify that internal and external network removed
# were called and floating_ips_process was called
self.routing_helper._process_router(ri)
self.assertFalse(self.routing_helper.
_process_router_floating_ips.called)
self.assertFalse(self.routing_helper._external_gateway_added.called)
self.assertFalse(self.routing_helper._external_gateway_removed.called)
self.assertFalse(self.routing_helper._internal_network_added.called)
self.routing_helper._internal_network_removed.assert_called_once_with(
ri, ports[0], None)
def test_process_global_router(self):
self._test_process_global_msn_router(num_ext_subnets=1,)
def test_process_global_msn_router(self):
self._test_process_global_msn_router()
def test_routing_table_update(self):
router = self.router

View File

@ -80,10 +80,20 @@ class TestBasicRoutingOperationsAci(helper.TestBasicRoutingOperations):
self.driver = self._mock_driver_and_hosting_device(
self.routing_helper)
def test_process_router_throw_multiple_ipv4_subnets_error(self):
ri, router = (
self._test_process_router_throw_multiple_ipv4_subnets_error())
router['gw_port'] = {'id': ''}
self.assertRaises(svc_helper.MultipleIPv4SubnetsException,
self.routing_helper._process_router, ri)
def test_process_router(self):
super(TestBasicRoutingOperationsAci,
self).test_process_router(test_admin_state=False)
def test_process_msn_router(self):
self._test_process_msn_router(test_admin_state=False)
def test_process_router_2_rids_1_vrf(self):
driver = self._mock_driver_and_hosting_device(self.routing_helper)
router1, ports = helper.prepare_router_data()

View File

@ -146,6 +146,7 @@ class TestHwVLANTrunkingPlugDriver(
fake_port_db_obj.hosting_info = mock.MagicMock()
fake_port_db_obj.hosting_info.segmentation_id = 50
fake_port_db_obj.device_owner = bc.constants.DEVICE_OWNER_ROUTER_INTF
fake_port_db_obj.networks.external = None
hosting_device = {'id': '00000000-0000-0000-0000-000000000002'}
tenant_id = 'tenant_uuid1'
ctx = context.Context('', tenant_id, is_admin=True)
@ -162,6 +163,7 @@ class TestHwVLANTrunkingPlugDriver(
fake_port_db_obj.hosting_info = mock.MagicMock()
fake_port_db_obj.hosting_info.segmentation_id = 40
fake_port_db_obj.device_owner = bc.constants.DEVICE_OWNER_ROUTER_GW
fake_port_db_obj.networks.external = {'external': True}
hosting_device = {'id': '00000000-0000-0000-0000-000000000002'}
tenant_id = 'tenant_uuid1'
ctx = context.Context('', tenant_id, is_admin=True)

View File

@ -63,6 +63,9 @@ class Asr1kRouterTypeDriverTestCase(
router_type = 'Nexus_ToR_Neutron_router'
def _verify_global_router(self, role, hd_id, ext_net_ids):
# The 'ext_net_ids' argument is a dict where key is ext_net_id and
# value is a list of subnet_ids that the global router should be
# connected to
if role == ROUTER_ROLE_LOGICAL_GLOBAL or hd_id is None:
q_p = '%s=%s' % (ROUTER_ROLE_ATTR, role)
else:
@ -85,10 +88,18 @@ class Asr1kRouterTypeDriverTestCase(
DEVICE_OWNER_GLOBAL_ROUTER_GW)
aux_gw_ports = self._list('ports', query_params=q_p)['ports']
self.assertEqual(len(ext_net_ids), len(aux_gw_ports))
ids = copy.copy(ext_net_ids)
ids = copy.deepcopy(ext_net_ids)
# check that there are ports on each external network
for aux_gw_port in aux_gw_ports:
self.assertIn(aux_gw_port['network_id'], ids)
ids.remove(aux_gw_port['network_id'])
self.assertEqual(len(aux_gw_port['fixed_ips']),
len(ids[aux_gw_port['network_id']]))
# check that port has ip on correct subnets
for ips in aux_gw_port['fixed_ips']:
self.assertIn(ips['subnet_id'],
ids[aux_gw_port['network_id']])
ids[aux_gw_port['network_id']].remove(ips['subnet_id'])
ids.pop(aux_gw_port['network_id'])
return router['id']
def _verify_routers(self, router_ids, ext_net_ids, hd_id=None,
@ -134,16 +145,21 @@ class Asr1kRouterTypeDriverTestCase(
self.network(tenant_id=tenant_id_2) as n_external_2:
ext_net_1_id = n_external_1['network']['id']
self._set_net_external(ext_net_1_id)
self._create_subnet(self.fmt, ext_net_1_id, cidr='10.0.1.0/24',
tenant_id=tenant_id_1)
sn_1 = self._make_subnet(
self.fmt, n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_net_ids = {ext_net_1_id: [sn_1['id']]}
ext_gw_1 = {'network_id': ext_net_1_id}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
self._create_subnet(self.fmt, ext_net_2_id, cidr='10.0.2.0/24',
tenant_id=tenant_id_2)
sn_2 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_2['id']]
else:
ext_net_2_id = ext_net_1_id
ext_gw_1 = {'network_id': ext_net_1_id}
ext_gw_2_subnets = [sn_1['id']]
ext_gw_2 = {'network_id': ext_net_2_id}
with self.router(
tenant_id=tenant_id_1, external_gateway_info=ext_gw_1,
@ -153,14 +169,14 @@ class Asr1kRouterTypeDriverTestCase(
r1_after = self._show('routers', r1['id'])['router']
hd_id = r1_after[HOSTING_DEVICE_ATTR]
# should have one global router now
self._verify_routers({r1['id']}, {ext_net_1_id}, hd_id)
self._verify_routers({r1['id']}, ext_net_ids, hd_id)
with self.router(
tenant_id=tenant_id_2, external_gateway_info=ext_gw_1,
set_context=set_context) as router2:
r2 = router2['router']
self.l3_plugin._process_backlogged_routers()
# should still have only one global router
self._verify_routers({r1['id'], r2['id']}, {ext_net_1_id},
self._verify_routers({r1['id'], r2['id']}, ext_net_ids,
hd_id)
with self.router(name='router2', tenant_id=tenant_id_2,
external_gateway_info=ext_gw_2,
@ -169,9 +185,9 @@ class Asr1kRouterTypeDriverTestCase(
self.l3_plugin._process_backlogged_routers()
# should still have only one global router but now with
# one extra auxiliary gateway port
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
self._verify_routers(
{r1['id'], r2['id'], r3['id']},
{ext_net_1_id, ext_net_2_id}, hd_id)
{r1['id'], r2['id'], r3['id']}, ext_net_ids, hd_id)
# single tenant and single external network
def test_create_gateway_router(self):
@ -202,12 +218,89 @@ class Asr1kRouterTypeDriverTestCase(
self._test_create_gateway_router(True, same_tenant=False,
same_ext_net=False)
# msn - multiple subnets (on a single neutron external network)
def _test_create_msn_gateway_router(self, set_context=False,
same_tenant=True, same_ext_net=True):
tenant_id_1 = _uuid()
tenant_id_2 = tenant_id_1 if same_tenant is True else _uuid()
with self.network(tenant_id=tenant_id_1) as msn_n_external_1,\
self.network(tenant_id=tenant_id_2) as n_external_2:
msn_ext_net_1_id = msn_n_external_1['network']['id']
self._set_net_external(msn_ext_net_1_id)
sn_1 = self._make_subnet(
self.fmt, msn_n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
sn_2 = self._make_subnet(
self.fmt, msn_n_external_1, '20.0.1.1', cidr='20.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_gw_1_subnets = [sn_1['id'], sn_2['id']]
ext_net_ids = {msn_ext_net_1_id: ext_gw_1_subnets}
ext_gw_1 = {
'network_id': msn_ext_net_1_id,
'external_fixed_ips': [{'subnet_id': sid}
for sid in ext_gw_1_subnets]}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
sn_3 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_3['id']]
ext_gw_2 = {'network_id': ext_net_2_id,
'external_fixed_ips': [{'subnet_id': sn_3['id']}]}
else:
ext_net_2_id = msn_ext_net_1_id
ext_gw_2_subnets = ext_gw_1_subnets
ext_gw_2 = ext_gw_1
with self.router(
tenant_id=tenant_id_1, external_gateway_info=ext_gw_1,
set_context=set_context) as router1:
r1 = router1['router']
self.l3_plugin._process_backlogged_routers()
r1_after = self._show('routers', r1['id'])['router']
hd_id = r1_after[HOSTING_DEVICE_ATTR]
# should have one global router now
self._verify_routers({r1['id']}, ext_net_ids, hd_id)
with self.router(
tenant_id=tenant_id_2, external_gateway_info=ext_gw_1,
set_context=set_context) as router2:
r2 = router2['router']
self.l3_plugin._process_backlogged_routers()
# should still have only one global router
self._verify_routers({r1['id'], r2['id']}, ext_net_ids,
hd_id)
with self.router(name='router2', tenant_id=tenant_id_2,
external_gateway_info=ext_gw_2,
set_context=set_context) as router3:
r3 = router3['router']
self.l3_plugin._process_backlogged_routers()
# should still have only one global router but now with
# one extra auxiliary gateway port
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
self._verify_routers(
{r1['id'], r2['id'], r3['id']},
ext_net_ids, hd_id)
# single tenant and single external network with two subnets
def test_create_msn_gateway_router(self):
self._test_create_msn_gateway_router()
def test_create_msn_gateway_router_dt(self):
self._test_create_msn_gateway_router(same_tenant=False)
def test_create_msn_gateway_router_den(self):
self._test_create_msn_gateway_router(same_ext_net=False)
def test_create_msn_gateway_router_dt_den(self):
self._test_create_msn_gateway_router(same_tenant=False,
same_ext_net=False)
def _test_create_router_adds_no_global_router(self, set_context=False):
with self.router(set_context=set_context) as router:
r = router['router']
self.l3_plugin._process_backlogged_routers()
# should have no global routers
self._verify_routers({r['id']}, set(), None)
self._verify_routers({r['id']}, {}, None)
def test_create_router_adds_no_global_router(self):
self._test_create_router_adds_no_global_router()
@ -222,8 +315,10 @@ class Asr1kRouterTypeDriverTestCase(
with self.network(tenant_id=tenant_id_1) as n_external_1:
ext_net_1_id = n_external_1['network']['id']
self._set_net_external(ext_net_1_id)
self._create_subnet(self.fmt, ext_net_1_id, cidr='10.0.1.0/24',
tenant_id=tenant_id_1)
sn_1 = self._make_subnet(
self.fmt, n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_net_ids = {ext_net_1_id: [sn_1['id']]}
ext_gw_1 = {'network_id': ext_net_1_id}
with self.router(
tenant_id=tenant_id_1, external_gateway_info=ext_gw_1,
@ -238,8 +333,7 @@ class Asr1kRouterTypeDriverTestCase(
# backlog processing will trigger one routers_updated
# notification containing r1 and r2
self.l3_plugin._process_backlogged_routers()
self._verify_routers({r1['id'], r2['id']}, {ext_net_1_id},
hd_id)
self._verify_routers({r1['id'], r2['id']}, ext_net_ids, hd_id)
def test_create_router_adds_no_aux_gw_port_to_global_router(self):
self._test_create_router_adds_no_aux_gw_port_to_global_router()
@ -265,16 +359,21 @@ class Asr1kRouterTypeDriverTestCase(
self.network(tenant_id=tenant_id_2) as n_external_2:
ext_net_1_id = n_external_1['network']['id']
self._set_net_external(ext_net_1_id)
self._create_subnet(self.fmt, ext_net_1_id, cidr='10.0.1.0/24',
tenant_id=tenant_id_1)
sn_1 = self._make_subnet(
self.fmt, n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_net_ids = {ext_net_1_id: [sn_1['id']]}
ext_gw_1 = {'network_id': ext_net_1_id}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
self._create_subnet(self.fmt, ext_net_2_id, cidr='10.0.2.0/24',
tenant_id=tenant_id_2)
sn_2 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_2['id']]
else:
ext_net_2_id = ext_net_1_id
ext_gw_1 = {'network_id': ext_net_1_id}
ext_gw_2_subnets = [sn_1['id']]
ext_gw_2 = {'network_id': ext_net_2_id}
with self.router(tenant_id=tenant_id_1,
set_context=set_context) as router1, \
@ -287,7 +386,6 @@ class Asr1kRouterTypeDriverTestCase(
self.l3_plugin._process_backlogged_routers()
# should have no global router yet
r_ids = {r1['id'], r2['id']}
ext_net_ids = {ext_net_1_id}
self._verify_routers(r_ids, ext_net_ids)
r_spec = {'router': {l3.EXTERNAL_GW_INFO: ext_gw_1}}
r1_after = self._update('routers', r1['id'], r_spec)['router']
@ -298,7 +396,7 @@ class Asr1kRouterTypeDriverTestCase(
self._update('routers', r2['id'], r_spec)['router']
# should still have only one global router but now with
# one extra auxiliary gateway port
ext_net_ids = {ext_net_1_id, ext_net_2_id}
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
self._verify_routers(r_ids, ext_net_ids, hd_id, [1, 3])
def test_update_router_set_gateway(self):
@ -327,6 +425,90 @@ class Asr1kRouterTypeDriverTestCase(
self._test_update_router_set_gateway(True, same_tenant=False,
same_ext_net=False)
def _test_update_router_set_msn_gateway(
self, set_context=False, same_tenant=True, same_ext_net=True):
tenant_id_1 = _uuid()
tenant_id_2 = tenant_id_1 if same_tenant is True else _uuid()
with self.network(tenant_id=tenant_id_1) as msn_n_external_1, \
self.network(tenant_id=tenant_id_2) as n_external_2:
msn_ext_net_1_id = msn_n_external_1['network']['id']
self._set_net_external(msn_ext_net_1_id)
sn_1 = self._make_subnet(
self.fmt, msn_n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
sn_2 = self._make_subnet(
self.fmt, msn_n_external_1, '20.0.1.1', cidr='20.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_net_ids = {msn_ext_net_1_id: [sn_1['id'], sn_2['id']]}
ext_gw_1 = {
'network_id': msn_ext_net_1_id,
'external_fixed_ips': [{'subnet_id': sn_1['id']}]}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
sn_3 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_3['id']]
ext_gw_2 = {'network_id': ext_net_2_id,
'external_fixed_ips': [{'subnet_id': sn_3['id']}]}
else:
ext_net_2_id = msn_ext_net_1_id
ext_gw_2_subnets = ext_net_ids[msn_ext_net_1_id]
ext_gw_2 = ext_gw_1
with self.router(tenant_id=tenant_id_1,
set_context=set_context) as router1, \
self.router(name='router2', tenant_id=tenant_id_2,
set_context=set_context) as router2:
r1 = router1['router']
r2 = router2['router']
# backlog processing will trigger one routers_updated
# notification containing r1 and r2
self.l3_plugin._process_backlogged_routers()
# should have no global router yet
r_ids = {r1['id'], r2['id']}
self._verify_routers(r_ids, ext_net_ids)
r_spec = {'router': {l3.EXTERNAL_GW_INFO: ext_gw_1}}
r1_after = self._update('routers', r1['id'], r_spec)['router']
res_ips = r1_after[l3.EXTERNAL_GW_INFO]['external_fixed_ips']
self.assertEqual(1, len(res_ips))
self.assertEqual(sn_1['id'], res_ips[0]['subnet_id'])
hd_id = r1_after[HOSTING_DEVICE_ATTR]
# should now have one global router
self._verify_routers(r_ids, ext_net_ids, hd_id, [1])
ext_gw_1_2 = {'network_id': msn_ext_net_1_id,
'external_fixed_ips': [{'subnet_id': sn_1['id']},
{'subnet_id': sn_2['id']}]}
r_spec = {'router': {l3.EXTERNAL_GW_INFO: ext_gw_1_2}}
r1_final = self._update('routers', r1['id'], r_spec)['router']
res_ips = r1_final[l3.EXTERNAL_GW_INFO]['external_fixed_ips']
self.assertEqual(2, len(res_ips))
self.assertIn(res_ips[0]['subnet_id'],
ext_net_ids[msn_ext_net_1_id])
self.assertIn(res_ips[1]['subnet_id'],
ext_net_ids[msn_ext_net_1_id])
# should now have one global router
self._verify_routers(r_ids, ext_net_ids, hd_id, [1])
r_spec = {'router': {l3.EXTERNAL_GW_INFO: ext_gw_2}}
self._update('routers', r2['id'], r_spec)['router']
# should still have only one global router but now with
# one extra auxiliary gateway port
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
self._verify_routers(r_ids, ext_net_ids, hd_id, [1, 3])
def test_update_router_set_msn_gateway(self):
self._test_update_router_set_msn_gateway()
def test_update_router_set_msn_gateway_dt(self):
self._test_update_router_set_msn_gateway(same_tenant=False)
def test_update_router_set_msn_gateway_den(self):
self._test_update_router_set_msn_gateway(same_ext_net=False)
def test_update_router_set_msn_gateway_dt_den(self):
self._test_update_router_set_msn_gateway(same_tenant=False,
same_ext_net=False)
def _test_router_update_unset_gw_or_delete(
self, set_context=False, same_tenant=True, same_ext_net=True,
update_operation=True):
@ -336,16 +518,22 @@ class Asr1kRouterTypeDriverTestCase(
self.network(tenant_id=tenant_id_1) as n_external_2:
ext_net_1_id = n_external_1['network']['id']
self._set_net_external(ext_net_1_id)
self._create_subnet(self.fmt, ext_net_1_id, cidr='10.0.1.0/24',
tenant_id=tenant_id_1)
sn_1 = self._make_subnet(
self.fmt, n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_net_ids = {ext_net_1_id: [sn_1['id']]}
ext_gw_1 = {'network_id': ext_net_1_id}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
self._create_subnet(self.fmt, ext_net_2_id, cidr='10.0.2.0/24',
tenant_id=tenant_id_2)
sn_2 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_2['id']]
else:
ext_net_2_id = ext_net_1_id
ext_gw_1 = {'network_id': ext_net_1_id}
ext_gw_2_subnets = [sn_1['id']]
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
ext_gw_2 = {'network_id': ext_net_2_id}
with self.router(tenant_id=tenant_id_1,
external_gateway_info=ext_gw_1,
@ -361,7 +549,6 @@ class Asr1kRouterTypeDriverTestCase(
r1_after = self._show('routers', r1['id'])['router']
hd_id = r1_after[HOSTING_DEVICE_ATTR]
r_ids = {r1['id'], r2['id']}
ext_net_ids = {ext_net_1_id, ext_net_2_id}
# should have one global router now
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
if update_operation is True:
@ -370,8 +557,9 @@ class Asr1kRouterTypeDriverTestCase(
else:
self._delete('routers', r1['id'])
r_ids = {r2['id']}
ext_net_ids = {ext_net_2_id}
# should still have one global router
if same_ext_net is False:
ext_net_ids.pop(ext_net_1_id)
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
if update_operation is True:
self._update('routers', r2['id'], r_spec)
@ -379,6 +567,7 @@ class Asr1kRouterTypeDriverTestCase(
self._delete('routers', r2['id'])
r_ids = {}
# should have no global router now
ext_net_ids.pop(ext_net_2_id, None)
self._verify_routers(r_ids, ext_net_ids)
def test_router_update_unset_gw(self):
@ -407,6 +596,88 @@ class Asr1kRouterTypeDriverTestCase(
self._test_router_update_unset_gw_or_delete(True, same_tenant=False,
same_ext_net=False)
def _test_router_update_unset_msn_gw(
self, set_context=False, same_tenant=True, same_ext_net=True):
tenant_id_1 = _uuid()
tenant_id_2 = tenant_id_1 if same_tenant is True else _uuid()
with self.network(tenant_id=tenant_id_1) as msn_n_external_1, \
self.network(tenant_id=tenant_id_1) as n_external_2:
msn_ext_net_1_id = msn_n_external_1['network']['id']
self._set_net_external(msn_ext_net_1_id)
sn_1 = self._make_subnet(
self.fmt, msn_n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
sn_2 = self._make_subnet(
self.fmt, msn_n_external_1, '20.0.1.1', cidr='20.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_gw_1_subnets = [sn_1['id'], sn_2['id']]
ext_net_ids = {msn_ext_net_1_id: ext_gw_1_subnets}
ext_gw_1 = {
'network_id': msn_ext_net_1_id,
'external_fixed_ips': [{'subnet_id': sid}
for sid in ext_gw_1_subnets]}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
sn_3 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_3['id']]
ext_gw_2 = {'network_id': ext_net_2_id,
'external_fixed_ips': [{'subnet_id': sn_3['id']}]}
else:
ext_net_2_id = msn_ext_net_1_id
ext_gw_2_subnets = ext_gw_1_subnets
ext_gw_2 = ext_gw_1
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
with self.router(tenant_id=tenant_id_1,
external_gateway_info=ext_gw_1,
set_context=set_context) as router1,\
self.router(name='router2', tenant_id=tenant_id_2,
external_gateway_info=ext_gw_2,
set_context=set_context) as router2:
r1 = router1['router']
r2 = router2['router']
# backlog processing will trigger one routers_updated
# notification containing r1 and r2
self.l3_plugin._process_backlogged_routers()
r1_after = self._show('routers', r1['id'])['router']
hd_id = r1_after[HOSTING_DEVICE_ATTR]
r_ids = {r1['id'], r2['id']}
# should have one global router now
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
ext_gw_1['external_fixed_ips'] = [{'subnet_id': sn_1['id']}]
r_spec = {'router': {l3.EXTERNAL_GW_INFO: ext_gw_1}}
r1_after_2 = self._update('routers', r1['id'],
r_spec)['router']
res_ips = r1_after_2[l3.EXTERNAL_GW_INFO]['external_fixed_ips']
self.assertEqual(1, len(res_ips))
self.assertEqual(sn_1['id'], res_ips[0]['subnet_id'])
# should still have one global router
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
r_spec = {'router': {l3.EXTERNAL_GW_INFO: None}}
self._update('routers', r1['id'], r_spec)
# should still have one global router
if same_ext_net is False:
ext_net_ids.pop(msn_ext_net_1_id)
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
self._update('routers', r2['id'], r_spec)
# should have no global router now
self._verify_routers(r_ids, ext_net_ids)
def test_router_update_unset_msn_gw(self):
self._test_router_update_unset_msn_gw()
def test_router_update_unset_msn_gw_dt(self):
self._test_router_update_unset_msn_gw(same_tenant=False)
def test_router_update_unset_msn_gw_den(self):
self._test_router_update_unset_msn_gw(same_ext_net=False)
def test_router_update_unset_msn_gw_dt_den(self):
self._test_router_update_unset_msn_gw(same_tenant=False,
same_ext_net=False)
def _test_delete_gateway_router(self, set_context=False, same_tenant=True,
same_ext_net=True):
self._test_router_update_unset_gw_or_delete(
@ -437,6 +708,80 @@ class Asr1kRouterTypeDriverTestCase(
self._test_delete_gateway_router(True, same_tenant=False,
same_ext_net=False)
def _test_delete_msn_gateway_router(self, set_context=False,
same_tenant=True, same_ext_net=True):
tenant_id_1 = _uuid()
tenant_id_2 = tenant_id_1 if same_tenant is True else _uuid()
with self.network(tenant_id=tenant_id_1) as msn_n_external_1, \
self.network(tenant_id=tenant_id_1) as n_external_2:
msn_ext_net_1_id = msn_n_external_1['network']['id']
self._set_net_external(msn_ext_net_1_id)
sn_1 = self._make_subnet(
self.fmt, msn_n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
sn_2 = self._make_subnet(
self.fmt, msn_n_external_1, '20.0.1.1', cidr='20.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_gw_1_subnets = [sn_1['id'], sn_2['id']]
ext_net_ids = {msn_ext_net_1_id: ext_gw_1_subnets}
ext_gw_1 = {
'network_id': msn_ext_net_1_id,
'external_fixed_ips': [{'subnet_id': sid}
for sid in ext_gw_1_subnets]}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
sn_3 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_3['id']]
ext_gw_2 = {'network_id': ext_net_2_id,
'external_fixed_ips': [{'subnet_id': sn_3['id']}]}
else:
ext_net_2_id = msn_ext_net_1_id
ext_gw_2_subnets = ext_gw_1_subnets
ext_gw_2 = ext_gw_1
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
with self.router(tenant_id=tenant_id_1,
external_gateway_info=ext_gw_1,
set_context=set_context) as router1,\
self.router(name='router2', tenant_id=tenant_id_2,
external_gateway_info=ext_gw_2,
set_context=set_context) as router2:
r1 = router1['router']
r2 = router2['router']
# backlog processing will trigger one routers_updated
# notification containing r1 and r2
self.l3_plugin._process_backlogged_routers()
r1_after = self._show('routers', r1['id'])['router']
hd_id = r1_after[HOSTING_DEVICE_ATTR]
r_ids = {r1['id'], r2['id']}
# should have one global router now
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
self._delete('routers', r1['id'])
r_ids = {r2['id']}
# should still have one global router
if same_ext_net is False:
ext_net_ids.pop(msn_ext_net_1_id)
self._verify_routers(r_ids, ext_net_ids, hd_id, [0, 1])
self._delete('routers', r2['id'])
r_ids = {}
# should have no global router now
self._verify_routers(r_ids, ext_net_ids)
def test_delete_msn_gateway_router(self):
self._test_delete_msn_gateway_router()
def test_delete_msn_gateway_router_dt(self):
self._test_delete_msn_gateway_router(same_tenant=False)
def test_delete_msn_gateway_router_den(self):
self._test_delete_msn_gateway_router(same_ext_net=False)
def test_delete_msn_gateway_router_dt_den(self):
self._test_delete_msn_gateway_router(same_tenant=False,
same_ext_net=False)
def _test_router_interface_add_refused_for_unsupported_topology(
self, num_expected_ports=2, set_context=False, same_tenant=True):
tenant_id_1 = _uuid()
@ -518,6 +863,9 @@ class Asr1kHARouterTypeDriverTestCase(
def _verify_routers(self, router_ids, ext_net_ids, hd_id=None,
call_indices=None):
# The 'ext_net_ids' argument is a dict where key is ext_net_id and
# value is a list of subnet_ids that the global router should be
# connected to
# tenant routers
q_p = '%s=None' % ROUTER_ROLE_ATTR
r_ids = {r['id'] for r in self._list(
@ -574,6 +922,9 @@ class L3CfgAgentAsr1kRouterTypeDriverTestCase(
super(L3CfgAgentAsr1kRouterTypeDriverTestCase, self).tearDown()
def _verify_global_router(self, role, hd_id, ext_net_ids):
# The 'ext_net_ids' argument is a dict where key is ext_net_id and
# value is a list of subnet_ids that the global router should be
# connected to
if hd_id is None:
q_p = '%s=%s' % (ROUTER_ROLE_ATTR, role)
else:
@ -593,10 +944,17 @@ class L3CfgAgentAsr1kRouterTypeDriverTestCase(
DEVICE_OWNER_GLOBAL_ROUTER_GW)
aux_gw_ports = self._list('ports', query_params=q_p)['ports']
self.assertEqual(len(ext_net_ids), len(aux_gw_ports))
ids = copy.copy(ext_net_ids)
ids = copy.deepcopy(ext_net_ids)
for aux_gw_port in aux_gw_ports:
self.assertIn(aux_gw_port['network_id'], ids)
ids.remove(aux_gw_port['network_id'])
self.assertEqual(len(aux_gw_port['fixed_ips']),
len(ids[aux_gw_port['network_id']]))
# check that port has ip on correct subnets
for ips in aux_gw_port['fixed_ips']:
self.assertIn(ips['subnet_id'],
ids[aux_gw_port['network_id']])
ids[aux_gw_port['network_id']].remove(ips['subnet_id'])
ids.pop(aux_gw_port['network_id'])
return router
def _verify_ha_settings(self, router, expected_ha):
@ -628,6 +986,9 @@ class L3CfgAgentAsr1kRouterTypeDriverTestCase(
ha_port['fixed_ips'][0]['ip_address'])
def _verify_sync_data(self, router, router_ids, ext_net_ids):
# The 'ext_net_ids' argument is a dict where key is ext_net_id and
# value is a list of subnet_ids that the global router should be
# connected to
hd_id = router[HOSTING_DEVICE_ATTR]
id_r_ha_backup = router[ha.DETAILS][ha.REDUNDANCY_ROUTERS][0]['id']
router_ha_backup = self._show('routers', id_r_ha_backup)['router']
@ -675,21 +1036,34 @@ class L3CfgAgentAsr1kRouterTypeDriverTestCase(
'allocated_vlan': 5})
tenant_id_1 = _uuid()
tenant_id_2 = tenant_id_1 if same_tenant is True else _uuid()
with self.network(tenant_id=tenant_id_1) as n_external_1, \
with self.network(tenant_id=tenant_id_1) as msn_n_external_1, \
self.network(tenant_id=tenant_id_1) as n_external_2:
ext_net_1_id = n_external_1['network']['id']
self._set_net_external(ext_net_1_id)
self._create_subnet(self.fmt, ext_net_1_id, cidr='10.0.1.0/24',
tenant_id=tenant_id_1)
msn_ext_net_1_id = msn_n_external_1['network']['id']
self._set_net_external(msn_ext_net_1_id)
sn_1 = self._make_subnet(
self.fmt, msn_n_external_1, '10.0.1.1', cidr='10.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
sn_2 = self._make_subnet(
self.fmt, msn_n_external_1, '20.0.1.1', cidr='20.0.1.0/24',
tenant_id=tenant_id_1)['subnet']
ext_net_ids = {msn_ext_net_1_id: [sn_1['id'], sn_2['id']]}
ext_gw_1 = {
'network_id': msn_ext_net_1_id,
'external_fixed_ips': [{'subnet_id': sn_1['id']}]}
if same_ext_net is False:
ext_net_2_id = n_external_2['network']['id']
self._set_net_external(ext_net_2_id)
self._create_subnet(self.fmt, ext_net_2_id, cidr='10.0.2.0/24',
tenant_id=tenant_id_2)
sn_3 = self._make_subnet(
self.fmt, n_external_2, '10.0.2.1', cidr='10.0.2.0/24',
tenant_id=tenant_id_2)['subnet']
ext_gw_2_subnets = [sn_3['id']]
ext_gw_2 = {'network_id': ext_net_2_id,
'external_fixed_ips': [{'subnet_id': sn_3['id']}]}
else:
ext_net_2_id = ext_net_1_id
ext_gw_1 = {'network_id': ext_net_1_id}
ext_gw_2 = {'network_id': ext_net_2_id}
ext_net_2_id = msn_ext_net_1_id
ext_gw_2_subnets = ext_net_ids[msn_ext_net_1_id]
ext_gw_2 = ext_gw_1
ext_net_ids[ext_net_2_id] = ext_gw_2_subnets
with self.router(tenant_id=tenant_id_1,
external_gateway_info=ext_gw_1,
set_context=set_context) as router1, \
@ -705,7 +1079,6 @@ class L3CfgAgentAsr1kRouterTypeDriverTestCase(
self.l3_plugin._process_backlogged_routers()
r1_after = self._show('routers', r1['id'])['router']
r_ids = [r1['id'], r2['id'], r3['id']]
ext_net_ids = {ext_net_1_id, ext_net_2_id}
self._verify_sync_data(r1_after, r_ids, ext_net_ids)
def test_l3_cfg_agent_query_global_router_info(self):