IPv6 support for rhel distro
When the ubuntu networking info file has ipv6 addresses inside it we need to make sure that we parse that information out and place it (at least) in the rhel network configuration writing. In later patches the other distros that use this parsed network configuration will likely also need to be updated (ubuntu and debian already should function as expected with regard to ipv6 support).
This commit is contained in:
commit
a189df34f3
@ -114,6 +114,10 @@ def translate_network(settings):
|
||||
if 'iface' not in info:
|
||||
continue
|
||||
iface_details = info['iface'].split(None)
|
||||
# Check if current device *may* have an ipv6 IP
|
||||
use_ipv6 = False
|
||||
if 'inet6' in iface_details:
|
||||
use_ipv6 = True
|
||||
dev_name = None
|
||||
if len(iface_details) >= 1:
|
||||
dev = iface_details[0].strip().lower()
|
||||
@ -122,6 +126,7 @@ def translate_network(settings):
|
||||
if not dev_name:
|
||||
continue
|
||||
iface_info = {}
|
||||
iface_info['ipv6'] = {}
|
||||
if len(iface_details) >= 3:
|
||||
proto_type = iface_details[2].strip().lower()
|
||||
# Seems like this can be 'loopback' which we don't
|
||||
@ -129,35 +134,50 @@ def translate_network(settings):
|
||||
if proto_type in ['dhcp', 'static']:
|
||||
iface_info['bootproto'] = proto_type
|
||||
# These can just be copied over
|
||||
for k in ['netmask', 'address', 'gateway', 'broadcast']:
|
||||
if k in info:
|
||||
val = info[k].strip().lower()
|
||||
if val:
|
||||
iface_info[k] = val
|
||||
# Name server info provided??
|
||||
if 'dns-nameservers' in info:
|
||||
iface_info['dns-nameservers'] = info['dns-nameservers'].split()
|
||||
# Name server search info provided??
|
||||
if 'dns-search' in info:
|
||||
iface_info['dns-search'] = info['dns-search'].split()
|
||||
# Is any mac address spoofing going on??
|
||||
if 'hwaddress' in info:
|
||||
hw_info = info['hwaddress'].lower().strip()
|
||||
hw_split = hw_info.split(None, 1)
|
||||
if len(hw_split) == 2 and hw_split[0].startswith('ether'):
|
||||
hw_addr = hw_split[1]
|
||||
if hw_addr:
|
||||
iface_info['hwaddress'] = hw_addr
|
||||
real_ifaces[dev_name] = iface_info
|
||||
if use_ipv6:
|
||||
for k in ['address', 'gateway']:
|
||||
if k in info:
|
||||
val = info[k].strip().lower()
|
||||
if val:
|
||||
iface_info['ipv6'][k] = val
|
||||
else:
|
||||
for k in ['netmask', 'address', 'gateway', 'broadcast']:
|
||||
if k in info:
|
||||
val = info[k].strip().lower()
|
||||
if val:
|
||||
iface_info[k] = val
|
||||
# Name server info provided??
|
||||
if 'dns-nameservers' in info:
|
||||
iface_info['dns-nameservers'] = info['dns-nameservers'].split()
|
||||
# Name server search info provided??
|
||||
if 'dns-search' in info:
|
||||
iface_info['dns-search'] = info['dns-search'].split()
|
||||
# Is any mac address spoofing going on??
|
||||
if 'hwaddress' in info:
|
||||
hw_info = info['hwaddress'].lower().strip()
|
||||
hw_split = hw_info.split(None, 1)
|
||||
if len(hw_split) == 2 and hw_split[0].startswith('ether'):
|
||||
hw_addr = hw_split[1]
|
||||
if hw_addr:
|
||||
iface_info['hwaddress'] = hw_addr
|
||||
# If ipv6 is enabled, device will have multiple IPs, so we need to
|
||||
# update the dictionary instead of overwriting it...
|
||||
if dev_name in real_ifaces:
|
||||
real_ifaces[dev_name].update(iface_info)
|
||||
else:
|
||||
real_ifaces[dev_name] = iface_info
|
||||
# Check for those that should be started on boot via 'auto'
|
||||
for (cmd, args) in entries:
|
||||
args = args.split(None)
|
||||
if not args:
|
||||
continue
|
||||
dev_name = args[0].strip().lower()
|
||||
if cmd == 'auto':
|
||||
# Seems like auto can be like 'auto eth0 eth0:1' so just get the
|
||||
# first part out as the device name
|
||||
args = args.split(None)
|
||||
if not args:
|
||||
continue
|
||||
dev_name = args[0].strip().lower()
|
||||
if dev_name in real_ifaces:
|
||||
real_ifaces[dev_name]['auto'] = True
|
||||
if cmd == 'iface' and 'inet6' in args:
|
||||
real_ifaces[dev_name]['inet6'] = True
|
||||
return real_ifaces
|
||||
|
||||
|
@ -71,6 +71,7 @@ class Distro(distros.Distro):
|
||||
nameservers = []
|
||||
searchservers = []
|
||||
dev_names = entries.keys()
|
||||
use_ipv6 = False
|
||||
for (dev, info) in entries.iteritems():
|
||||
net_fn = self.network_script_tpl % (dev)
|
||||
net_cfg = {
|
||||
@ -83,6 +84,13 @@ class Distro(distros.Distro):
|
||||
'MACADDR': info.get('hwaddress'),
|
||||
'ONBOOT': _make_sysconfig_bool(info.get('auto')),
|
||||
}
|
||||
if info.get('inet6'):
|
||||
use_ipv6 = True
|
||||
net_cfg.update({
|
||||
'IPV6INIT': _make_sysconfig_bool(True),
|
||||
'IPV6ADDR': info.get('ipv6').get('address'),
|
||||
'IPV6_DEFAULTGW': info.get('ipv6').get('gateway'),
|
||||
})
|
||||
rhel_util.update_sysconfig_file(net_fn, net_cfg)
|
||||
if 'dns-nameservers' in info:
|
||||
nameservers.extend(info['dns-nameservers'])
|
||||
@ -95,6 +103,10 @@ class Distro(distros.Distro):
|
||||
net_cfg = {
|
||||
'NETWORKING': _make_sysconfig_bool(True),
|
||||
}
|
||||
# If IPv6 interface present, enable ipv6 networking
|
||||
if use_ipv6:
|
||||
net_cfg['NETWORKING_IPV6'] = _make_sysconfig_bool(True)
|
||||
net_cfg['IPV6_AUTOCONF'] = _make_sysconfig_bool(False)
|
||||
rhel_util.update_sysconfig_file(self.network_conf_fn, net_cfg)
|
||||
return dev_names
|
||||
|
||||
|
@ -72,6 +72,7 @@ def netdev_info(empty=""):
|
||||
"bcast:": "bcast", "broadcast": "bcast",
|
||||
"mask:": "mask", "netmask": "mask",
|
||||
"hwaddr": "hwaddr", "ether": "hwaddr",
|
||||
"scope": "scope",
|
||||
}
|
||||
for origfield, field in ifconfigfields.items():
|
||||
target = "%s%s" % (field, fieldpost)
|
||||
@ -96,7 +97,12 @@ def netdev_info(empty=""):
|
||||
|
||||
def route_info():
|
||||
(route_out, _err) = util.subp(["netstat", "-rn"])
|
||||
routes = []
|
||||
(route_out6, _err6) = util.subp(["netstat", "-A inet6", "-n"])
|
||||
|
||||
routes = {}
|
||||
routes['ipv4'] = []
|
||||
routes['ipv6'] = []
|
||||
|
||||
entries = route_out.splitlines()[1:]
|
||||
for line in entries:
|
||||
if not line:
|
||||
@ -132,7 +138,26 @@ def route_info():
|
||||
'iface': toks[7],
|
||||
}
|
||||
|
||||
routes.append(entry)
|
||||
routes['ipv4'].append(entry)
|
||||
|
||||
entries6 = route_out6.splitlines()[1:]
|
||||
for line in entries6:
|
||||
if not line:
|
||||
continue
|
||||
toks = line.split()
|
||||
|
||||
if (len(toks) < 6 or toks[0] == "Kernel" or
|
||||
toks[0] == "Proto" or toks[0] == "Active"):
|
||||
continue
|
||||
entry = {
|
||||
'proto': toks[0],
|
||||
'recv-q': toks[1],
|
||||
'send-q': toks[2],
|
||||
'local address': toks[3],
|
||||
'foreign address': toks[4],
|
||||
'state': toks[5],
|
||||
}
|
||||
routes['ipv6'].append(entry)
|
||||
return routes
|
||||
|
||||
|
||||
@ -156,10 +181,12 @@ def netdev_pformat():
|
||||
lines.append(util.center("Net device info failed", '!', 80))
|
||||
netdev = None
|
||||
if netdev is not None:
|
||||
fields = ['Device', 'Up', 'Address', 'Mask', 'Hw-Address']
|
||||
fields = ['Device', 'Up', 'Address', 'Mask', 'Scope', 'Hw-Address']
|
||||
tbl = PrettyTable(fields)
|
||||
for (dev, d) in netdev.iteritems():
|
||||
tbl.add_row([dev, d["up"], d["addr"], d["mask"], d["hwaddr"]])
|
||||
tbl.add_row([dev, d["up"], d["addr"], d["mask"], ".", d["hwaddr"]])
|
||||
if d["addr6"]:
|
||||
tbl.add_row([dev, d["up"], d["addr6"], ".", d["scope6"], d["hwaddr"]])
|
||||
netdev_s = tbl.get_string()
|
||||
max_len = len(max(netdev_s.splitlines(), key=len))
|
||||
header = util.center("Net device info", "+", max_len)
|
||||
@ -176,15 +203,30 @@ def route_pformat():
|
||||
util.logexc(LOG, "Route info failed: %s" % e)
|
||||
routes = None
|
||||
if routes is not None:
|
||||
fields = ['Route', 'Destination', 'Gateway',
|
||||
fields_v4 = ['Route', 'Destination', 'Gateway',
|
||||
'Genmask', 'Interface', 'Flags']
|
||||
tbl = PrettyTable(fields)
|
||||
for (n, r) in enumerate(routes):
|
||||
|
||||
if routes.get('ipv6') is not None:
|
||||
fields_v6 = ['Route', 'Proto', 'Recv-Q', 'Send-Q', 'Local Address',
|
||||
'Foreign Address', 'State']
|
||||
|
||||
tbl_v4 = PrettyTable(fields_v4)
|
||||
for (n, r) in enumerate(routes.get('ipv4')):
|
||||
route_id = str(n)
|
||||
tbl.add_row([route_id, r['destination'],
|
||||
tbl_v4.add_row([route_id, r['destination'],
|
||||
r['gateway'], r['genmask'],
|
||||
r['iface'], r['flags']])
|
||||
route_s = tbl.get_string()
|
||||
route_s = tbl_v4.get_string()
|
||||
if fields_v6:
|
||||
tbl_v6 = PrettyTable(fields_v6)
|
||||
for (n, r) in enumerate(routes.get('ipv6')):
|
||||
route_id = str(n)
|
||||
tbl_v6.add_row([route_id, r['proto'],
|
||||
r['recv-q'], r['send-q'],
|
||||
r['local address'], r['foreign address'],
|
||||
r['state']])
|
||||
route_s = route_s + tbl_v6.get_string()
|
||||
|
||||
max_len = len(max(route_s.splitlines(), key=len))
|
||||
header = util.center("Route info", "+", max_len)
|
||||
lines.extend([header, route_s])
|
||||
|
@ -30,6 +30,36 @@ auto eth1
|
||||
iface eth1 inet dhcp
|
||||
'''
|
||||
|
||||
BASE_NET_CFG_IPV6 = '''
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address 192.168.1.5
|
||||
netmask 255.255.255.0
|
||||
network 192.168.0.0
|
||||
broadcast 192.168.1.0
|
||||
gateway 192.168.1.254
|
||||
|
||||
iface eth0 inet6 static
|
||||
address 2607:f0d0:1002:0011::2
|
||||
netmask 64
|
||||
gateway 2607:f0d0:1002:0011::1
|
||||
|
||||
iface eth1 inet static
|
||||
address 192.168.1.6
|
||||
netmask 255.255.255.0
|
||||
network 192.168.0.0
|
||||
broadcast 192.168.1.0
|
||||
gateway 192.168.1.254
|
||||
|
||||
iface eth1 inet6 static
|
||||
address 2607:f0d0:1002:0011::3
|
||||
netmask 64
|
||||
gateway 2607:f0d0:1002:0011::1
|
||||
'''
|
||||
|
||||
|
||||
class WriteBuffer(object):
|
||||
def __init__(self):
|
||||
@ -174,6 +204,97 @@ NETWORKING=yes
|
||||
self.assertCfgEquals(expected_buf, str(write_buf))
|
||||
self.assertEquals(write_buf.mode, 0644)
|
||||
|
||||
def test_write_ipv6_rhel(self):
|
||||
rh_distro = self._get_distro('rhel')
|
||||
write_mock = self.mocker.replace(util.write_file,
|
||||
spec=False, passthrough=False)
|
||||
load_mock = self.mocker.replace(util.load_file,
|
||||
spec=False, passthrough=False)
|
||||
exists_mock = self.mocker.replace(os.path.isfile,
|
||||
spec=False, passthrough=False)
|
||||
|
||||
write_bufs = {}
|
||||
|
||||
def replace_write(filename, content, mode=0644, omode="wb"):
|
||||
buf = WriteBuffer()
|
||||
buf.mode = mode
|
||||
buf.omode = omode
|
||||
buf.write(content)
|
||||
write_bufs[filename] = buf
|
||||
|
||||
exists_mock(mocker.ARGS)
|
||||
self.mocker.count(0, None)
|
||||
self.mocker.result(False)
|
||||
|
||||
load_mock(mocker.ARGS)
|
||||
self.mocker.count(0, None)
|
||||
self.mocker.result('')
|
||||
|
||||
for _i in range(0, 3):
|
||||
write_mock(mocker.ARGS)
|
||||
self.mocker.call(replace_write)
|
||||
|
||||
write_mock(mocker.ARGS)
|
||||
self.mocker.call(replace_write)
|
||||
|
||||
self.mocker.replay()
|
||||
rh_distro.apply_network(BASE_NET_CFG_IPV6, False)
|
||||
|
||||
self.assertEquals(len(write_bufs), 4)
|
||||
self.assertIn('/etc/sysconfig/network-scripts/ifcfg-lo', write_bufs)
|
||||
write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-lo']
|
||||
expected_buf = '''
|
||||
DEVICE="lo"
|
||||
ONBOOT=yes
|
||||
'''
|
||||
self.assertCfgEquals(expected_buf, str(write_buf))
|
||||
self.assertEquals(write_buf.mode, 0644)
|
||||
|
||||
self.assertIn('/etc/sysconfig/network-scripts/ifcfg-eth0', write_bufs)
|
||||
write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-eth0']
|
||||
expected_buf = '''
|
||||
DEVICE="eth0"
|
||||
BOOTPROTO="static"
|
||||
NETMASK="255.255.255.0"
|
||||
IPADDR="192.168.1.5"
|
||||
ONBOOT=yes
|
||||
GATEWAY="192.168.1.254"
|
||||
BROADCAST="192.168.1.0"
|
||||
IPV6INIT=yes
|
||||
IPV6ADDR="2607:f0d0:1002:0011::2"
|
||||
IPV6_DEFAULTGW="2607:f0d0:1002:0011::1"
|
||||
'''
|
||||
self.assertCfgEquals(expected_buf, str(write_buf))
|
||||
self.assertEquals(write_buf.mode, 0644)
|
||||
self.assertIn('/etc/sysconfig/network-scripts/ifcfg-eth1', write_bufs)
|
||||
write_buf = write_bufs['/etc/sysconfig/network-scripts/ifcfg-eth1']
|
||||
expected_buf = '''
|
||||
DEVICE="eth1"
|
||||
BOOTPROTO="static"
|
||||
NETMASK="255.255.255.0"
|
||||
IPADDR="192.168.1.6"
|
||||
ONBOOT=no
|
||||
GATEWAY="192.168.1.254"
|
||||
BROADCAST="192.168.1.0"
|
||||
IPV6INIT=yes
|
||||
IPV6ADDR="2607:f0d0:1002:0011::3"
|
||||
IPV6_DEFAULTGW="2607:f0d0:1002:0011::1"
|
||||
'''
|
||||
self.assertCfgEquals(expected_buf, str(write_buf))
|
||||
self.assertEquals(write_buf.mode, 0644)
|
||||
|
||||
self.assertIn('/etc/sysconfig/network', write_bufs)
|
||||
write_buf = write_bufs['/etc/sysconfig/network']
|
||||
expected_buf = '''
|
||||
# Created by cloud-init v. 0.7
|
||||
NETWORKING=yes
|
||||
NETWORKING_IPV6=yes
|
||||
IPV6_AUTOCONF=no
|
||||
'''
|
||||
self.assertCfgEquals(expected_buf, str(write_buf))
|
||||
self.assertEquals(write_buf.mode, 0644)
|
||||
|
||||
|
||||
def test_simple_write_freebsd(self):
|
||||
fbsd_distro = self._get_distro('freebsd')
|
||||
util_mock = self.mocker.replace(util.write_file,
|
||||
|
Loading…
x
Reference in New Issue
Block a user