diff --git a/backend.py b/backend.py index c7789920..cd1ad6c3 100644 --- a/backend.py +++ b/backend.py @@ -1548,15 +1548,15 @@ def configureNetworking(mounts, admin_iface, admin_bridge, admin_config, hn_conf print >>mc, "NETMASK='%s'" % admin_config.netmask if admin_config.gateway: print >>mc, "GATEWAY='%s'" % admin_config.gateway - if manual_nameservers: - print >>mc, "DNS='%s'" % (','.join(nameservers),) - if domain: - print >>mc, "DOMAIN='%s'" % domain print >>mc, "MODEV6='%s'" % netinterface.NetInterface.getModeStr(admin_config.modev6) if admin_config.modev6 == netinterface.NetInterface.Static: print >>mc, "IPv6='%s'" % admin_config.ipv6addr if admin_config.ipv6_gateway: print >>mc, "IPv6_GATEWAY='%s'" % admin_config.ipv6_gateway + if manual_nameservers: + print >>mc, "DNS='%s'" % (','.join(nameservers),) + if domain: + print >>mc, "DOMAIN='%s'" % domain if admin_config.vlan: print >>mc, "VLAN='%d'" % admin_config.vlan mc.close() @@ -1598,12 +1598,18 @@ def configureNetworking(mounts, admin_iface, admin_bridge, admin_config, hn_conf # now we need to write /etc/sysconfig/network nfd = open("%s/etc/sysconfig/network" % mounts["root"], "w") nfd.write("NETWORKING=yes\n") - if admin_config.modev6: + ipv6 = admin_config.modev6 is not None + if ipv6: nfd.write("NETWORKING_IPV6=yes\n") util.runCmd2(['chroot', mounts['root'], 'systemctl', 'enable', 'ip6tables']) else: nfd.write("NETWORKING_IPV6=no\n") netutil.disable_ipv6_module(mounts["root"]) + + with open("%s/etc/sysctl.d/91-net-ipv6.conf" % mounts["root"], "w") as ipv6_conf: + for i in ['all', 'default']: + ipv6_conf.write('net.ipv6.conf.%s.disable_ipv6=%d\n' % (i, int(not ipv6))) + nfd.write("IPV6_AUTOCONF=no\n") nfd.write('NTPSERVERARGS="iburst prefer"\n') nfd.close() diff --git a/netinterface.py b/netinterface.py index d5c788db..59af509c 100644 --- a/netinterface.py +++ b/netinterface.py @@ -16,7 +16,7 @@ def getTextOrNone(nodelist): rc = rc + node.data return rc == "" and None or rc.strip().encode() -class NetInterface: +class NetInterface(object): """ Represents the configuration of a network interface. """ Static = 1 @@ -122,10 +122,18 @@ def valid(self): return False return self.mode or self.modev6 - def isStatic(self): - """ Returns true if a static interface configuration is represented. """ + def isStatic4(self): + """ Returns true if an IPv4 static interface configuration is represented. """ return self.mode == self.Static + def isStatic6(self): + """ Returns true if an IPv6 static interface configuration is represented. """ + return self.modev6 == self.Static + + def isDynamic(self): + """ Returns true if a dynamic interface configuration is represented. """ + return self.mode == self.DHCP or self.modev6 == self.DHCP or self.modev6 == self.Autoconf + def isVlan(self): return self.vlan is not None @@ -141,8 +149,7 @@ def writeRHStyleInterface(self, iface): """ Write a RedHat-style configuration entry for this interface to file object f using interface name iface. """ - assert self.modev6 is None - assert self.mode + assert self.modev6 or self.mode iface_vlan = self.getInterfaceName(iface) f = open('/etc/sysconfig/network-scripts/ifcfg-%s' % iface_vlan, 'w') @@ -151,7 +158,7 @@ def writeRHStyleInterface(self, iface): if self.mode == self.DHCP: f.write("BOOTPROTO=dhcp\n") f.write("PERSISTENT_DHCLIENT=1\n") - else: + elif self.mode == self.Static: # CA-11825: broadcast needs to be determined for non-standard networks bcast = self.getBroadcast() f.write("BOOTPROTO=none\n") @@ -161,20 +168,45 @@ def writeRHStyleInterface(self, iface): f.write("NETMASK=%s\n" % self.netmask) if self.gateway: f.write("GATEWAY=%s\n" % self.gateway) + + if self.modev6: + with open('/etc/sysconfig/network', 'w') as net_conf: + net_conf.write("NETWORKING_IPV6=yes\n") + f.write("IPV6INIT=yes\n") + f.write("IPV6_DEFROUTE=yes\n") + f.write("IPV6_DEFAULTDEV=%s\n" % iface_vlan) + + if self.modev6 == self.DHCP: + f.write("DHCPV6C=yes\n") + f.write("PERSISTENT_DHCLIENT_IPV6=yes\n") + f.write("IPV6_FORCE_ACCEPT_RA=yes\n") + f.write("IPV6_AUTOCONF=no\n") + elif self.modev6 == self.Static: + f.write("IPV6ADDR=%s\n" % self.ipv6addr) + if self.ipv6_gateway: + f.write("IPV6_DEFAULTGW=%s\n" % (self.ipv6_gateway)) + f.write("IPV6_AUTOCONF=no\n") + elif self.modev6 == self.Autoconf: + f.write("IPV6_AUTOCONF=yes\n") + if self.vlan: f.write("VLAN=yes\n") f.close() def waitUntilUp(self, iface): - if not self.isStatic(): - return True - if not self.gateway: - return True + iface_name = self.getInterfaceName(iface) + if self.isStatic4() and self.gateway and util.runCmd2( + ['/usr/sbin/arping', '-f', '-w', '120', '-I', iface_name, self.gateway] + ): + return False + + if self.isStatic6() and self.ipv6_gateway and util.runCmd2( + ['/usr/sbin/ndisc6', '-1', '-w', '120', self.ipv6_gateway, iface_name] + ): + return False - rc = util.runCmd2(['/usr/sbin/arping', '-f', '-w', '120', '-I', - self.getInterfaceName(iface), self.gateway]) - return rc == 0 + return True @staticmethod def getModeStr(mode): @@ -185,3 +217,22 @@ def getModeStr(mode): if mode == NetInterface.Autoconf: return 'autoconf' return 'none' + +class NetInterfaceV6(NetInterface): + def __init__(self, mode, hwaddr, ipaddr=None, netmask=None, gateway=None, dns=None, domain=None, vlan=None): + super(NetInterfaceV6, self).__init__(None, hwaddr, None, None, None, None, None, vlan) + + ipv6addr = None + if mode == self.Static: + assert ipaddr + assert netmask + + ipv6addr = ipaddr + "/" + netmask + if dns == '': + dns = None + elif isinstance(dns, str): + dns = [ dns ] + self.dns = dns + self.domain = domain + + self.addIPv6(mode, ipv6addr=ipv6addr, ipv6gw=gateway) diff --git a/netutil.py b/netutil.py index f266695c..bcb4f3e8 100644 --- a/netutil.py +++ b/netutil.py @@ -4,12 +4,12 @@ import diskutil import util import re +import socket import subprocess import time import errno from xcp import logger from xcp.net.biosdevname import all_devices_all_names -from socket import inet_ntoa from struct import pack class NIC: @@ -73,7 +73,7 @@ def writeResolverFile(configuration, filename): for iface in configuration: settings = configuration[iface] - if settings.isStatic() and settings.dns: + if (not settings.isDynamic()) and settings.dns: if settings.dns: for server in settings.dns: outfile.write("nameserver %s\n" % server) @@ -118,7 +118,11 @@ def interfaceUp(interface): if rc != 0: return False inets = filter(lambda x: x.startswith(" inet "), out.split("\n")) - return len(inets) == 1 + if len(inets) == 1: + return True + + inet6s = filter(lambda x: x.startswith(" inet6 "), out.split("\n")) + return len(inet6s) > 1 # Not just the fe80:: address # work out if a link is up: def linkUp(interface): @@ -206,16 +210,21 @@ def valid_vlan(vlan): return False return True -def valid_ip_addr(addr): - if not re.match('^\d+\.\d+\.\d+\.\d+$', addr): - return False - els = addr.split('.') - if len(els) != 4: +def valid_ip_address_family(addr, family): + try: + socket.inet_pton(family, addr) + return True + except socket.error: return False - for el in els: - if int(el) > 255: - return False - return True + +def valid_ipv4_addr(addr): + return valid_ip_address_family(addr, socket.AF_INET) + +def valid_ipv6_addr(addr): + return valid_ip_address_family(addr, socket.AF_INET6) + +def valid_ip_addr(addr): + return valid_ipv4_addr(addr) or valid_ipv6_addr(addr) def network(ipaddr, netmask): ip = map(int,ipaddr.split('.',3)) @@ -227,7 +236,7 @@ def prefix2netmask(mask): bits = 0 for i in xrange(32-mask, 32): bits |= (1 << i) - return inet_ntoa(pack('>I', bits)) + return socket.inet_ntoa(pack('>I', bits)) class NetDevices: def __init__(self): diff --git a/tui/installer/screens.py b/tui/installer/screens.py index de98a353..3334bb15 100644 --- a/tui/installer/screens.py +++ b/tui/installer/screens.py @@ -896,7 +896,7 @@ def ns_callback((enabled, )): for entry in [ns1_entry, ns2_entry, ns3_entry]: entry.setFlags(FLAG_DISABLED, enabled) - hide_rb = answers['net-admin-configuration'].isStatic() + hide_rb = not answers['net-admin-configuration'].isDynamic() # HOSTNAME: hn_title = Textbox(len("Hostname Configuration"), 1, "Hostname Configuration") @@ -1026,7 +1026,7 @@ def nsvalue(answers, id): answers['manual-nameservers'][1].append(ns2_entry.value()) if ns3_entry.value() != '': answers['manual-nameservers'][1].append(ns3_entry.value()) - if 'net-admin-configuration' in answers and answers['net-admin-configuration'].isStatic(): + if 'net-admin-configuration' in answers and not answers['net-admin-configuration'].isDynamic(): answers['net-admin-configuration'].dns = answers['manual-nameservers'][1] else: answers['manual-nameservers'] = (False, None) @@ -1109,7 +1109,7 @@ def get_time_configuration_method(answers): default = None if "ntp-config-method" in answers: default = selectDefault(answers['ntp-config-method'], entries) - if answers['net-admin-configuration'].isStatic(): + if not answers['net-admin-configuration'].isDynamic(): default = ENTRY_DEFAULT_NTP (button, entry) = ListboxChoiceWindow( diff --git a/tui/network.py b/tui/network.py index faf87dc9..126974ee 100644 --- a/tui/network.py +++ b/tui/network.py @@ -9,128 +9,215 @@ from netinterface import * import version import os +import time +import socket from snack import * def get_iface_configuration(nic, txt=None, defaults=None, include_dns=False): - - def use_vlan_cb_change(): - vlan_field.setFlags(FLAG_DISABLED, vlan_cb.value()) - - def dhcp_change(): - for x in [ ip_field, gateway_field, subnet_field, dns_field ]: - x.setFlags(FLAG_DISABLED, not dhcp_rb.selected()) - - gf = GridFormHelp(tui.screen, 'Networking', 'ifconfig', 1, 8) - if txt is None: - txt = "Configuration for %s (%s)" % (nic.name, nic.hwaddr) - text = TextboxReflowed(45, txt) - b = [("Ok", "ok"), ("Back", "back")] - buttons = ButtonBar(tui.screen, b) - - ip_field = Entry(16) - subnet_field = Entry(16) - gateway_field = Entry(16) - dns_field = Entry(16) - vlan_field = Entry(16) - - if defaults and defaults.isStatic(): - # static configuration defined previously - dhcp_rb = SingleRadioButton("Automatic configuration (DHCP)", None, 0) - dhcp_rb.setCallback(dhcp_change, ()) - static_rb = SingleRadioButton("Static configuration:", dhcp_rb, 1) - static_rb.setCallback(dhcp_change, ()) - if defaults.ipaddr: - ip_field.set(defaults.ipaddr) - if defaults.netmask: - subnet_field.set(defaults.netmask) - if defaults.gateway: - gateway_field.set(defaults.gateway) - if defaults.dns: - dns_field.set(defaults.dns[0]) - else: - dhcp_rb = SingleRadioButton("Automatic configuration (DHCP)", None, 1) + def choose_primary_address_type(nic): + gf = GridFormHelp(tui.screen, 'Networking', 'Address type', 1, 8) + txt = "Choose an address type for %s (%s)" % (nic.name, nic.hwaddr) + text = TextboxReflowed(45, txt) + + b = [("Ok", "ok"), ("Back", "back")] + buttons = ButtonBar(tui.screen, b) + + # IPv4 by default + ipv4_rb = SingleRadioButton("IPv4", None, 1) + ipv6_rb = SingleRadioButton("IPv6", ipv4_rb, 0) + dual_rb = SingleRadioButton("Dual stack (IPv4 primary)", ipv6_rb, 0) + + gf.add(text, 0, 0, padding=(0, 0, 0, 1)) + gf.add(ipv4_rb, 0, 2, anchorLeft=True) + gf.add(ipv6_rb, 0, 3, anchorLeft=True) + gf.add(dual_rb, 0, 4, anchorLeft=True) + gf.add(buttons, 0, 5, growx=1) + + loop = True + direction = LEFT_BACKWARDS + address_type = None + while loop: + result = gf.run() + if buttons.buttonPressed(result) == 'back': + loop = False + elif buttons.buttonPressed(result) == 'ok': + value = None + if ipv4_rb.selected(): + value = "ipv4" + elif ipv6_rb.selected(): + value = "ipv6" + elif dual_rb.selected(): + value = "dual" + loop = False + direction = RIGHT_FORWARDS + address_type = value + + tui.screen.popWindow() + return direction, address_type + + def get_ip_configuration(nic, txt, defaults, include_dns, iface_class): + def use_vlan_cb_change(): + vlan_field.setFlags(FLAG_DISABLED, vlan_cb.value()) + + def dhcp_change(): + for x in [ ip_field, gateway_field, subnet_field, dns_field ]: + x.setFlags(FLAG_DISABLED, static_rb.selected()) + + ipv6 = iface_class == NetInterfaceV6 + + gf = GridFormHelp(tui.screen, 'Networking', 'ifconfig', 1, 10) + if txt is None: + txt = "Configuration for %s (%s)" % (nic.name, nic.hwaddr) + text = TextboxReflowed(45, txt) + b = [("Ok", "ok"), ("Back", "back")] + buttons = ButtonBar(tui.screen, b) + + #TODO? Change size for IPv6? If so which size? + ip_field = Entry(16) + subnet_field = Entry(16) + gateway_field = Entry(16) + dns_field = Entry(16) + vlan_field = Entry(16) + + static = bool(defaults and (defaults.modev6 if ipv6 else defaults.mode) == NetInterface.Static) + dhcp_rb = SingleRadioButton("Automatic configuration (DHCP)", None, not static) dhcp_rb.setCallback(dhcp_change, ()) - static_rb = SingleRadioButton("Static configuration:", dhcp_rb, 0) + static_rb = SingleRadioButton("Static configuration:", dhcp_rb, static) static_rb.setCallback(dhcp_change, ()) - ip_field.setFlags(FLAG_DISABLED, False) - subnet_field.setFlags(FLAG_DISABLED, False) - gateway_field.setFlags(FLAG_DISABLED, False) - dns_field.setFlags(FLAG_DISABLED, False) - - vlan_cb = Checkbox("Use VLAN:", defaults.isVlan() if defaults else False) - vlan_cb.setCallback(use_vlan_cb_change, ()) - if defaults and defaults.isVlan(): - vlan_field.set(str(defaults.vlan)) - else: - vlan_field.setFlags(FLAG_DISABLED, False) - - ip_text = Textbox(15, 1, "IP Address:") - subnet_text = Textbox(15, 1, "Subnet mask:") - gateway_text = Textbox(15, 1, "Gateway:") - dns_text = Textbox(15, 1, "Nameserver:") - vlan_text = Textbox(15, 1, "VLAN (1-4094):") - - entry_grid = Grid(2, include_dns and 4 or 3) - entry_grid.setField(ip_text, 0, 0) - entry_grid.setField(ip_field, 1, 0) - entry_grid.setField(subnet_text, 0, 1) - entry_grid.setField(subnet_field, 1, 1) - entry_grid.setField(gateway_text, 0, 2) - entry_grid.setField(gateway_field, 1, 2) - if include_dns: - entry_grid.setField(dns_text, 0, 3) - entry_grid.setField(dns_field, 1, 3) - - vlan_grid = Grid(2, 1) - vlan_grid.setField(vlan_text, 0, 0) - vlan_grid.setField(vlan_field, 1, 0) - - gf.add(text, 0, 0, padding=(0, 0, 0, 1)) - gf.add(dhcp_rb, 0, 2, anchorLeft=True) - gf.add(static_rb, 0, 3, anchorLeft=True) - gf.add(entry_grid, 0, 4, padding=(0, 0, 0, 1)) - gf.add(vlan_cb, 0, 5, anchorLeft=True) - gf.add(vlan_grid, 0, 6, padding=(0, 0, 0, 1)) - gf.add(buttons, 0, 7, growx=1) - - loop = True - while loop: - result = gf.run() - - if buttons.buttonPressed(result) in ['ok', None]: - # validate input - msg = '' - if static_rb.selected(): - if not netutil.valid_ip_addr(ip_field.value()): - msg = 'IP Address' - elif not netutil.valid_ip_addr(subnet_field.value()): - msg = 'Subnet mask' - elif gateway_field.value() != '' and not netutil.valid_ip_addr(gateway_field.value()): - msg = 'Gateway' - elif dns_field.value() != '' and not netutil.valid_ip_addr(dns_field.value()): - msg = 'Nameserver' - if vlan_cb.selected(): - if not netutil.valid_vlan(vlan_field.value()): - msg = 'VLAN' - if msg != '': - tui.progress.OKDialog("Networking", "Invalid %s, please check the field and try again." % msg) + if ipv6: + autoconf_rb = SingleRadioButton("Automatic configuration (Autoconf)", static_rb, 0) + autoconf_rb.setCallback(dhcp_change, ()) + dhcp_change() + + if defaults: + if ipv6: + if defaults.ipv6addr: + ip6addr, netmask = defaults.ipv6addr.split("/") + ip_field.set(ip6addr) + subnet_field.set(netmask) + if defaults.ipv6_gateway: + gateway_field.set(defaults.ipv6_gateway) + else: + if defaults.ipaddr: + ip_field.set(defaults.ipaddr) + if defaults.netmask: + subnet_field.set(defaults.netmask) + if defaults.gateway: + gateway_field.set(defaults.gateway) + + if defaults.dns: + dns_field.set(defaults.dns[0]) + + vlan_cb = Checkbox("Use VLAN:", defaults.isVlan() if defaults else False) + vlan_cb.setCallback(use_vlan_cb_change, ()) + if defaults and defaults.isVlan(): + vlan_field.set(str(defaults.vlan)) + else: + vlan_field.setFlags(FLAG_DISABLED, False) + + ip_msg = "IPv6 Address" if ipv6 else "IP Address" + mask_msg = "CIDR (4-128)" if ipv6 else "Subnet mask" + ip_text = Textbox(15, 1, "%s:" % ip_msg) + subnet_text = Textbox(15, 1, "%s:" % mask_msg) + gateway_text = Textbox(15, 1, "Gateway:") + dns_text = Textbox(15, 1, "Nameserver:") + vlan_text = Textbox(15, 1, "VLAN (1-4094):") + + entry_grid = Grid(2, include_dns and 4 or 3) + entry_grid.setField(ip_text, 0, 0) + entry_grid.setField(ip_field, 1, 0) + entry_grid.setField(subnet_text, 0, 1) + entry_grid.setField(subnet_field, 1, 1) + entry_grid.setField(gateway_text, 0, 2) + entry_grid.setField(gateway_field, 1, 2) + if include_dns: + entry_grid.setField(dns_text, 0, 3) + entry_grid.setField(dns_field, 1, 3) + + vlan_grid = Grid(2, 1) + vlan_grid.setField(vlan_text, 0, 0) + vlan_grid.setField(vlan_field, 1, 0) + + gf.add(text, 0, 0, padding=(0, 0, 0, 1)) + gf.add(dhcp_rb, 0, 2, anchorLeft=True) + gf.add(static_rb, 0, 3, anchorLeft=True) + gf.add(entry_grid, 0, 4, padding=(0, 0, 0, 1)) + if ipv6: + gf.add(autoconf_rb, 0, 5, anchorLeft=True) + # One more line for IPv6 autoconf + gf.add(vlan_cb, 0, 5 + ipv6, anchorLeft=True) + gf.add(vlan_grid, 0, 6 + ipv6, padding=(0, 0, 0, 1)) + gf.add(buttons, 0, 7 + ipv6, growx=1) + + loop = True + ip_family = socket.AF_INET6 if ipv6 else socket.AF_INET + while loop: + result = gf.run() + + if buttons.buttonPressed(result) in ['ok', None]: + # validate input + msg = '' + if static_rb.selected(): + invalid_subnet = int(subnet_field.value()) > 128 or int(subnet_field.value()) < 4 if ipv6 else not netutil.valid_ipv4_addr(subnet_field.value()) + if not netutil.valid_ip_address_family(ip_field.value(), ip_family): + msg = ip_msg + elif invalid_subnet: + msg = mask_msg + elif gateway_field.value() != '' and not netutil.valid_ip_address_family(gateway_field.value(), ip_family): + msg = 'Gateway' + elif dns_field.value() != '' and not netutil.valid_ip_address_family(dns_field.value(), ip_family): + msg = 'Nameserver' + if vlan_cb.selected(): + if not netutil.valid_vlan(vlan_field.value()): + msg = 'VLAN' + if msg != '': + tui.progress.OKDialog("Networking", "Invalid %s, please check the field and try again." % msg) + else: + loop = False else: loop = False + + tui.screen.popWindow() + + if buttons.buttonPressed(result) == 'back': return LEFT_BACKWARDS, None + + vlan_value = int(vlan_field.value()) if vlan_cb.selected() else None + if dhcp_rb.selected(): + answers = iface_class(NetInterface.DHCP, nic.hwaddr, vlan=vlan_value) + elif ipv6 and autoconf_rb.selected(): + answers = iface_class(NetInterface.Autoconf, nic.hwaddr, vlan=vlan_value) else: - loop = False + answers = iface_class(NetInterface.Static, nic.hwaddr, ip_field.value(), + subnet_field.value(), gateway_field.value(), + dns_field.value(), vlan=vlan_value) - tui.screen.popWindow() + return RIGHT_FORWARDS, answers - if buttons.buttonPressed(result) == 'back': return LEFT_BACKWARDS, None + direction, address_type = choose_primary_address_type(nic) + if direction == LEFT_BACKWARDS: + return LEFT_BACKWARDS, None + + answers = None + if address_type in ["ipv4", "dual"]: + direction, answers = get_ip_configuration(nic, txt, defaults, include_dns, NetInterface) + if direction == LEFT_BACKWARDS: + return LEFT_BACKWARDS, None + + if address_type in ["ipv6", "dual"]: + direction, answers_ipv6 = get_ip_configuration(nic, txt, defaults, include_dns, NetInterfaceV6) + if direction == LEFT_BACKWARDS: + return LEFT_BACKWARDS, None + + if answers == None: + answers = answers_ipv6 + else: + answers.modev6 = answers_ipv6.modev6 + answers.ipv6addr = answers_ipv6.ipv6addr + answers.ipv6_gateway = answers_ipv6.ipv6_gateway + if answers_ipv6.dns != None: + answers.dns = answers_ipv6.dns if answers.dns == None else answers.dns + answers_ipv6.dns - vlan_value = int(vlan_field.value()) if vlan_cb.selected() else None - if bool(dhcp_rb.selected()): - answers = NetInterface(NetInterface.DHCP, nic.hwaddr, vlan=vlan_value) - else: - answers = NetInterface(NetInterface.Static, nic.hwaddr, ip_field.value(), - subnet_field.value(), gateway_field.value(), - dns_field.value(), vlan=vlan_value) return RIGHT_FORWARDS, answers def select_netif(text, conf, offer_existing=False, default=None): @@ -286,23 +373,37 @@ def specify_configuration(answers, txt, defaults): ifaceName = conf_dict['config'].getInterfaceName(conf_dict['interface']) netutil.ifdown(ifaceName) - # check that we have *some* network: - if netutil.ifup(ifaceName) != 0 or not netutil.interfaceUp(ifaceName): + def display_error(): tui.progress.clearModelessDialog() tui.progress.OKDialog("Networking", "The network still does not appear to be active. Please check your settings, and try again.") - direction = REPEAT_STEP - else: - if answers and type(answers) == dict: - # write out results - answers[interface_key] = conf_dict['interface'] - answers[config_key] = conf_dict['config'] - # update cache of manual configurations - manual_config = {} - all_dhcp = False - if 'runtime-iface-configuration' in answers: - manual_config = answers['runtime-iface-configuration'][1] - manual_config[conf_dict['interface']] = conf_dict['config'] - answers['runtime-iface-configuration'] = (all_dhcp, manual_config) - tui.progress.clearModelessDialog() + return REPEAT_STEP + + if netutil.ifup(ifaceName) != 0: + return display_error() + + # For Autoconf wait a bit for network setup + try_nb = 20 if conf_dict['config'].modev6 == NetInterface.Autoconf else 0 + while True: + if try_nb == 0 or netutil.interfaceUp(ifaceName): + break + try_nb -= 1 + time.sleep(0.1) + + # check that we have *some* network: + if not netutil.interfaceUp(ifaceName): + return display_error() + + if answers and type(answers) == dict: + # write out results + answers[interface_key] = conf_dict['interface'] + answers[config_key] = conf_dict['config'] + # update cache of manual configurations + manual_config = {} + all_dhcp = False + if 'runtime-iface-configuration' in answers: + manual_config = answers['runtime-iface-configuration'][1] + manual_config[conf_dict['interface']] = conf_dict['config'] + answers['runtime-iface-configuration'] = (all_dhcp, manual_config) + tui.progress.clearModelessDialog() return direction diff --git a/upgrade.py b/upgrade.py index 0672b577..f3b4c29a 100644 --- a/upgrade.py +++ b/upgrade.py @@ -448,6 +448,9 @@ def buildRestoreList(self): # NRPE service config self.restore_list += ['etc/nagios/nrpe.cfg', {'dir': 'etc/nrpe.d'}] + # Keep IPv6 enablement/disablement upon upgrades + self.restore_list += ['etc/sysctl.d/91-net-ipv6.conf'] + completeUpgradeArgs = ['mounts', 'installation-to-overwrite', 'primary-disk', 'backup-partnum', 'logs-partnum', 'net-admin-interface', 'net-admin-bridge', 'net-admin-configuration'] def completeUpgrade(self, mounts, prev_install, target_disk, backup_partnum, logs_partnum, admin_iface, admin_bridge, admin_config):