aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Sneddon <dsneddon@redhat.com>2016-01-17 13:04:40 -0800
committerDan Sneddon <dsneddon@redhat.com>2016-03-11 10:24:42 -0800
commit3b4a27a3ccb861cf2899ea1fae6c1cc160b38fd7 (patch)
treeafc7597421745e81465d5af03aa6aeabaac09b52
parent63659fe4a60dfb18bbc8cc835d6d1c4fe7317a60 (diff)
Add ability to set IPv6 routes in os-net-config templates
This change adds the ability to write IPv6 routes to the system NIC configuration. In the ifcfg provider, IPv6 routes must be written to network-scripts/route6-<interface> rather than route-interface. This patch checks the next hop, and if it is an IPv6 address (assumed because of the presence of ":"), then the route will be written to route6-<interface>. This patch includes tests to confirm proper operation. Change-Id: I3563800c774a6082a896c7508f5a92e25418fe63
-rw-r--r--os_net_config/impl_ifcfg.py76
-rw-r--r--os_net_config/tests/test_impl_ifcfg.py36
2 files changed, 96 insertions, 16 deletions
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py
index c4d6d93..27b8579 100644
--- a/os_net_config/impl_ifcfg.py
+++ b/os_net_config/impl_ifcfg.py
@@ -43,6 +43,10 @@ def route_config_path(name):
return "/etc/sysconfig/network-scripts/route-%s" % name
+def route6_config_path(name):
+ return "/etc/sysconfig/network-scripts/route6-%s" % name
+
+
def cleanup_pattern():
return "/etc/sysconfig/network-scripts/ifcfg-*"
@@ -55,6 +59,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
self.interface_data = {}
self.ivsinterface_data = {}
self.route_data = {}
+ self.route6_data = {}
self.bridge_data = {}
self.linuxbridge_data = {}
self.linuxbond_data = {}
@@ -221,16 +226,31 @@ class IfcfgNetConfig(os_net_config.NetConfig):
logger.info('adding custom route for interface: %s' % interface_name)
data = ""
first_line = ""
+ data6 = ""
+ first_line6 = ""
for route in routes:
- if route.default:
- first_line = "default via %s dev %s\n" % (route.next_hop,
- interface_name)
+ if ":" not in route.next_hop:
+ # Route is an IPv4 route
+ if route.default:
+ first_line = "default via %s dev %s\n" % (route.next_hop,
+ interface_name)
+ else:
+ data += "%s via %s dev %s\n" % (route.ip_netmask,
+ route.next_hop,
+ interface_name)
else:
- data += "%s via %s dev %s\n" % (route.ip_netmask,
- route.next_hop,
- interface_name)
+ # Route is an IPv6 route
+ if route.default:
+ first_line6 = "default via %s dev %s\n" % (route.next_hop,
+ interface_name)
+ else:
+ data6 += "%s via %s dev %s\n" % (route.ip_netmask,
+ route.next_hop,
+ interface_name)
self.route_data[interface_name] = first_line + data
+ self.route6_data[interface_name] = first_line6 + data6
logger.debug('route data: %s' % self.route_data[interface_name])
+ logger.debug('ipv6 route data: %s' % self.route6_data[interface_name])
def add_interface(self, interface):
"""Add an Interface object to the net config object.
@@ -379,18 +399,24 @@ class IfcfgNetConfig(os_net_config.NetConfig):
for interface_name, iface_data in self.interface_data.iteritems():
route_data = self.route_data.get(interface_name, '')
+ route6_data = self.route6_data.get(interface_name, '')
interface_path = self.root_dir + ifcfg_config_path(interface_name)
route_path = self.root_dir + route_config_path(interface_name)
+ route6_path = self.root_dir + route6_config_path(interface_name)
all_file_names.append(interface_path)
all_file_names.append(route_path)
if "IVS_BRIDGE" in iface_data:
ivs_uplinks.append(interface_name)
+ all_file_names.append(route6_path)
if (utils.diff(interface_path, iface_data) or
- utils.diff(route_path, route_data)):
+ utils.diff(route_path, route_data) or
+ utils.diff(route6_path, route6_data)):
restart_interfaces.append(interface_name)
restart_interfaces.extend(self.child_members(interface_name))
update_files[interface_path] = iface_data
update_files[route_path] = route_data
+ update_files[route6_path] = route6_data
+ else:
logger.info('No changes required for interface: %s' %
interface_name)
@@ -412,44 +438,62 @@ class IfcfgNetConfig(os_net_config.NetConfig):
for bridge_name, bridge_data in self.bridge_data.iteritems():
route_data = self.route_data.get(bridge_name, '')
+ route6_data = self.route6_data.get(bridge_name, '')
bridge_path = self.root_dir + bridge_config_path(bridge_name)
- bridge_route_path = self.root_dir + route_config_path(bridge_name)
+ br_route_path = self.root_dir + route_config_path(bridge_name)
+ br_route6_path = self.root_dir + route6_config_path(bridge_name)
all_file_names.append(bridge_path)
- all_file_names.append(bridge_route_path)
+ all_file_names.append(br_route_path)
+ all_file_names.append(br_route6_path)
if (utils.diff(bridge_path, bridge_data) or
- utils.diff(bridge_route_path, route_data)):
+ utils.diff(br_route_path, route_data) or
+ utils.diff(br_route6_path, route6_data)):
restart_bridges.append(bridge_name)
restart_interfaces.extend(self.child_members(bridge_name))
update_files[bridge_path] = bridge_data
- update_files[bridge_route_path] = route_data
+ update_files[br_route_path] = route_data
+ update_files[br_route6_path] = route6_data
+ else:
logger.info('No changes required for bridge: %s' % bridge_name)
for bridge_name, bridge_data in self.linuxbridge_data.iteritems():
route_data = self.route_data.get(bridge_name, '')
+ route6_data = self.route6_data.get(bridge_name, '')
bridge_path = self.root_dir + bridge_config_path(bridge_name)
- bridge_route_path = self.root_dir + route_config_path(bridge_name)
+ br_route_path = self.root_dir + route_config_path(bridge_name)
+ br_route6_path = self.root_dir + route6_config_path(bridge_name)
all_file_names.append(bridge_path)
- all_file_names.append(bridge_route_path)
+ all_file_names.append(br_route_path)
+ all_file_names.append(br_route6_path)
if (utils.diff(bridge_path, bridge_data) or
- utils.diff(bridge_route_path, route_data)):
+ utils.diff(br_route_path, route_data) or
+ utils.diff(br_route6_path, route6_data)):
restart_bridges.append(bridge_name)
restart_interfaces.extend(self.child_members(bridge_name))
update_files[bridge_path] = bridge_data
- update_files[bridge_route_path] = route_data
+ update_files[br_route_path] = route_data
+ update_files[br_route6_path] = route6_data
+ else:
logger.info('No changes required for bridge: %s' % bridge_name)
for bond_name, bond_data in self.linuxbond_data.iteritems():
route_data = self.route_data.get(bond_name, '')
+ route6_data = self.route6_data.get(bond_name, '')
bond_path = self.root_dir + bridge_config_path(bond_name)
bond_route_path = self.root_dir + route_config_path(bond_name)
+ bond_route6_path = self.root_dir + route6_config_path(bond_name)
all_file_names.append(bond_path)
all_file_names.append(bond_route_path)
+ all_file_names.append(bond_route6_path)
if (utils.diff(bond_path, bond_data) or
- utils.diff(bond_route_path, route_data)):
+ utils.diff(bond_route_path, route_data) or
+ utils.diff(bond_route6_path, route6_data)):
restart_interfaces.append(bond_name)
restart_interfaces.extend(self.child_members(bond_name))
update_files[bond_path] = bond_data
update_files[bond_route_path] = route_data
+ update_files[bond_route6_path] = route6_data
+ else:
logger.info('No changes required for linux bond: %s' %
bond_name)
diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py
index bf3ce7c..f92b0a6 100644
--- a/os_net_config/tests/test_impl_ifcfg.py
+++ b/os_net_config/tests/test_impl_ifcfg.py
@@ -39,6 +39,14 @@ IPADDR=192.168.1.2
NETMASK=255.255.255.0
"""
+_V4_V6_IFCFG = _BASE_IFCFG + """IPV6INIT=yes
+BOOTPROTO=static
+IPADDR=192.168.1.2
+NETMASK=255.255.255.0
+IPV6_AUTOCONF=no
+IPV6ADDR=2001:abc:a::/64
+"""
+
_IFCFG_VLAN = """# This file is autogenerated by os-net-config
DEVICE=em1.120
ONBOOT=yes
@@ -75,6 +83,11 @@ _ROUTES = """default via 192.168.1.1 dev em1
172.19.0.0/24 via 192.168.1.1 dev em1
"""
+_ROUTES_V6 = """default via 2001:db8::1 dev em1
+2001:db8:dead:beef:cafe::/56 via fd00:fd00:2000::1 dev em1
+"""
+
+
_OVS_INTERFACE = _BASE_IFCFG + """DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ctlplane
@@ -231,6 +244,9 @@ class TestIfcfgNetConfig(base.TestCase):
def get_route_config(self, name='em1'):
return self.provider.route_data.get(name, '')
+ def get_route6_config(self, name='em1'):
+ return self.provider.route6_data.get(name, '')
+
def test_add_base_interface(self):
interface = objects.Interface('em1')
self.provider.add_interface(interface)
@@ -304,6 +320,20 @@ class TestIfcfgNetConfig(base.TestCase):
self.assertEqual(_V4_IFCFG, self.get_interface_config())
self.assertEqual(_ROUTES, self.get_route_config())
+ def test_network_with_ipv6_routes(self):
+ route1 = objects.Route('192.168.1.1', default=True)
+ route2 = objects.Route('192.168.1.1', '172.19.0.0/24')
+ route3 = objects.Route('2001:db8::1', default=True)
+ route4 = objects.Route('fd00:fd00:2000::1',
+ '2001:db8:dead:beef:cafe::/56')
+ v4_addr = objects.Address('192.168.1.2/24')
+ v6_addr = objects.Address('2001:abc:a::/64')
+ interface = objects.Interface('em1', addresses=[v4_addr, v6_addr],
+ routes=[route1, route2, route3, route4])
+ self.provider.add_interface(interface)
+ self.assertEqual(_V4_V6_IFCFG, self.get_interface_config())
+ self.assertEqual(_ROUTES_V6, self.get_route6_config())
+
def test_network_ovs_bridge_with_dhcp(self):
interface = objects.Interface('em1')
bridge = objects.OvsBridge('br-ctlplane', use_dhcp=True,
@@ -518,6 +548,7 @@ class TestIfcfgNetConfigApply(base.TestCase):
super(TestIfcfgNetConfigApply, self).setUp()
self.temp_ifcfg_file = tempfile.NamedTemporaryFile()
self.temp_route_file = tempfile.NamedTemporaryFile()
+ self.temp_route6_file = tempfile.NamedTemporaryFile()
self.temp_bridge_file = tempfile.NamedTemporaryFile()
self.temp_cleanup_file = tempfile.NamedTemporaryFile(delete=False)
self.ifup_interface_names = []
@@ -531,6 +562,10 @@ class TestIfcfgNetConfigApply(base.TestCase):
return self.temp_route_file.name
self.stubs.Set(impl_ifcfg, 'route_config_path', test_routes_path)
+ def test_routes6_path(name):
+ return self.temp_route6_file.name
+ self.stubs.Set(impl_ifcfg, 'route6_config_path', test_routes6_path)
+
def test_bridge_path(name):
return self.temp_bridge_file.name
self.stubs.Set(impl_ifcfg, 'bridge_config_path', test_bridge_path)
@@ -552,6 +587,7 @@ class TestIfcfgNetConfigApply(base.TestCase):
def tearDown(self):
self.temp_ifcfg_file.close()
self.temp_route_file.close()
+ self.temp_route6_file.close()
self.temp_bridge_file.close()
if os.path.exists(self.temp_cleanup_file.name):
self.temp_cleanup_file.close()