The patchset contains fixes for network configuration:
Move from modifying ifcfg files to using NM dbus api (settings objects) where possible. [1/8, 2/8, 8/8] Stop writing /etc/sysconfig/network.[3/8] Fix disabling of ipv6. [4/8, 5/8] Don't crash on invalid network --device specification. [6/8] Make modifying ifcfg files more robust (don't crash on missing file, eg for WWAN devices). [7/8, 1/8]
Instead of r/w ifcfg files. We still need to modify ifcfg files directly in some cases, see: https://bugzilla.redhat.com/show_bug.cgi?id=893892#c36 --- pyanaconda/network.py | 80 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 26 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 1c67625..474fa33 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -465,41 +465,73 @@ def createMissingDefaultIfcfgs(): rv = False nm = get_NM_object(isys.NM_MANAGER_PATH) dev_paths = nm.GetDevices() - settings = get_NM_object(isys.NM_SETTINGS_PATH) for devpath in dev_paths: + + # for each ethernet device device = get_NM_object(devpath) device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE) devicetype = device_props_iface.Get(isys.NM_DEVICE_IFACE, "DeviceType") if devicetype != isys.NM_DEVICE_TYPE_ETHERNET: continue + # if there is no ifcfg file for the device interface = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface")) device_cfg = NetworkDevice(netscriptsDir, interface) if os.access(device_cfg.path, os.R_OK): continue + # check if there is a connection for the device (default autoconnection) hwaddr = device_props_iface.Get(isys.NM_DEVICE_WIRED_IFACE, "HwAddress") + con = get_NM_connection(hwaddr) + if con: + log.debug("network: dumping ifcfg file for default autoconnection on %s" % interface) + settings = con.GetSettings() + settings['connection']['id'] = interface + con.Update(settings) + else: + # if there is no connection, create default ifcfg + device_cfg.setDefaultConfig() + rv = True + + return rv + +def get_NM_connection(connection_spec, spec_type="hwaddr"): + + if spec_type == "iface": + nm = get_NM_object(isys.NM_MANAGER_PATH) + dev_paths = nm.GetDevices() + for devpath in dev_paths: + device = get_NM_object(devpath) + device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE) + interface = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface")) + if interface == connection_spec: + try: + connection_spec = str(device_props_iface.Get(isys.NM_DEVICE_WIRED_IFACE, "HwAddress")) + spec_type = "hwaddr" + except dbus.DBusException as e: + log.debug("get_NM_settings (interface %s) %s" % (interface, e)) + return None + break + + if spec_type == "hwaddr": + settings = get_NM_object(isys.NM_SETTINGS_PATH) con_paths = settings.ListConnections() for con_path in con_paths: con = get_NM_object(con_path) setting = con.GetSettings() + try: + con_hwaddr_bytearray = setting['802-3-ethernet']['mac-address'] + except KeyError: + log.debug("no mac-address setting found for %s" % con_path) + continue con_hwaddr = ":".join("%02X" % byte for byte in - setting['802-3-ethernet']['mac-address']) - # if so, write its configuration with name changed to iface - if con_hwaddr.upper() == hwaddr.upper(): - setting['connection']['id'] = interface - con.Update(setting) - rv = True - log.debug("network: dumped ifcfg file for default autoconnection on %s" % interface) - break - else: - # if there is no connection, create default ifcfg - device_cfg.setDefaultConfig() - rv = True - return rv + con_hwaddr_bytearray) + if con_hwaddr.upper() == connection_spec.upper(): + return con + + return None
def getDevices(): - # TODO: filter with existence of ifcfg file? return isys.getDeviceProperties().keys()
def waitForDevicesActivation(devices): @@ -1035,18 +1067,14 @@ def setOnboot(ksdata): log.error("Kickstart: The provided network interface %s does not exist" % devname) continue
- dev = NetworkDevice(netscriptsDir, devname) - try: - dev.loadIfcfgFile() - except IOError as e: - log.info("Can't load ifcfg file %s, %s" % (dev.path, e)) - continue - - if network_data.onboot: - dev.set (("ONBOOT", "yes")) + con = get_NM_connection(devname, spec_type="iface") + if con: + ifcfglog.debug("setting autoconnect (ONBOOT) of %s to %s" % (devname, network_data.onboot)) + settings = con.GetSettings() + settings['connection']['autoconnect'] = network_data.onboot + con.Update(settings) else: - dev.set (("ONBOOT", "no")) - dev.writeIfcfgFile() + log.debug("Can't find connection settings for %s" % devname)
def networkInitialize(ksdata):
Instead we dump settings from NM. --- pyanaconda/network.py | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 474fa33..8034965 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -286,29 +286,6 @@ class NetworkDevice(IfcfgFile):
return s
- # anaconda doesn't actually need this configuration, but if we don't write - # it to the installed system then 'ifup' doesn't work after install. - # FIXME: make 'ifup' use its own defaults! - def setDefaultConfig(self): - ifcfglog.debug("NetworkDevice %s: setDefaultConfig()" % self.iface) - self.set(("DEVICE", self.iface), - ("BOOTPROTO", "dhcp"), - ("ONBOOT", "no")) # for "security", or something - - try: - mac = open("/sys/class/net/%s/address" % self.iface).read().strip() - self.set(("HWADDR", mac.upper())) - except IOError as e: - ifcfglog.warning("HWADDR: %s" % str(e)) - - try: - uuid = open("/proc/sys/kernel/random/uuid").read().strip() - self.set(("UUID", uuid)) - except IOError as e: - ifcfglog.warning("UUID: %s" % str(e)) - - self.writeIfcfgFile() - def loadIfcfgFile(self): ifcfglog.debug("loadIfcfFile %s" % self.path)
@@ -489,8 +466,7 @@ def createMissingDefaultIfcfgs(): settings['connection']['id'] = interface con.Update(settings) else: - # if there is no connection, create default ifcfg - device_cfg.setDefaultConfig() + log.debug("network: no ifcfg file for %s" % interface) rv = True
return rv
We shouldn't set global GATEWAY, IPV6_DEFAULTGW. HOSTNAME went to /etc/hostname. Writing NETWORKING=yes unconditionally doesn't make sense. --- pyanaconda/network.py | 35 ----------------------------------- 1 file changed, 35 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 8034965..3c5779f 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -835,40 +835,6 @@ def write_hostname(rootpath, ksdata, overwrite=False):
return True
-def write_sysconfig_network(rootpath, ksdata, overwrite=False): - - cfgfile = os.path.normpath(rootpath + networkConfFile) - if (os.path.isfile(cfgfile) and not overwrite): - return False - - f = open(cfgfile, "w") - f.write("# Generated by anaconda\n") - f.write("NETWORKING=yes\n") - - gateway = ipv6_defaultgw = None - for iface in reversed(getDevices()): - if isys.isWirelessDevice(iface): - continue - dev = NetworkDevice(netscriptsDir, iface) - dev.loadIfcfgFile() - if dev.get('DEFROUTE') != "no": - continue - if dev.get('GATEWAY'): - gateway = dev.get('GATEWAY') - if dev.get('IPV6_DEFAULTGW'): - ipv6_defaultgw = dev.get('IPV6_DEFAULTGW') - if gateway and ipv6_defaultgw: - break - - if gateway: - f.write("GATEWAY=%s\n" % gateway) - - if ipv6_defaultgw: - f.write("IPV6_DEFAULTGW=%s\n" % ipv6_defaultgw) - f.close() - - return True - def disableIPV6(rootpath): cfgfile = os.path.normpath(rootpath + ipv6ConfFile) if ('noipv6' in flags.cmdline @@ -940,7 +906,6 @@ def usedByRootOnISCSI(iface, storage): def write_network_config(storage, ksdata, instClass, rootpath): write_hostname(rootpath, ksdata, overwrite=flags.livecdInstall) set_hostname(ksdata.network.hostname) - write_sysconfig_network(rootpath, ksdata, overwrite=flags.livecdInstall) disableIPV6(rootpath) if not flags.imageInstall: copyIfcfgFiles(rootpath)
--- pyanaconda/network.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 3c5779f..3c9ef43 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -52,7 +52,7 @@ sysconfigDir = "/etc/sysconfig" netscriptsDir = "%s/network-scripts" % (sysconfigDir) networkConfFile = "%s/network" % (sysconfigDir) hostnameFile = "/etc/hostname" -ipv6ConfFile = "/etc/modprobe.d/ipv6.conf" +ipv6ConfFile = "/etc/sysctl.d/anaconda.conf" ifcfgLogFile = "/tmp/ifcfg.log" CONNECTION_TIMEOUT = 45 DEFAULT_HOSTNAME = "localhost.localdomain" @@ -840,14 +840,12 @@ def disableIPV6(rootpath): if ('noipv6' in flags.cmdline and not any(get_ifcfg_value(dev, 'IPV6INIT') == "yes" for dev in getDevices())): - if os.path.exists(cfgfile): - log.warning('Not disabling ipv6, %s exists' % cfgfile) - else: - log.info('Disabling ipv6 on target system') - f = open(cfgfile, "w") - f.write("# Anaconda disabling ipv6\n") - f.write("options ipv6 disable=1\n") - f.close() + log.info('Disabling ipv6 on target system') + f = open(cfgfile, "a") + f.write("# Anaconda disabling ipv6 (noipv6 option)\n") + f.write("net.ipv6.conf.all.disable_ipv6=1\n") + f.write("net.ipv6.conf.default.disable_ipv6=1\n") + f.close()
def disableNMForStorageDevices(rootpath, storage): for devname in getDevices():
On Tue, 2013-01-29 at 13:10 +0100, Radek Vykydal wrote:
pyanaconda/network.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 3c5779f..3c9ef43 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -52,7 +52,7 @@ sysconfigDir = "/etc/sysconfig" netscriptsDir = "%s/network-scripts" % (sysconfigDir) networkConfFile = "%s/network" % (sysconfigDir) hostnameFile = "/etc/hostname" -ipv6ConfFile = "/etc/modprobe.d/ipv6.conf" +ipv6ConfFile = "/etc/sysctl.d/anaconda.conf" ifcfgLogFile = "/tmp/ifcfg.log" CONNECTION_TIMEOUT = 45 DEFAULT_HOSTNAME = "localhost.localdomain" @@ -840,14 +840,12 @@ def disableIPV6(rootpath): if ('noipv6' in flags.cmdline and not any(get_ifcfg_value(dev, 'IPV6INIT') == "yes" for dev in getDevices())):
if os.path.exists(cfgfile):
log.warning('Not disabling ipv6, %s exists' % cfgfile)
else:
log.info('Disabling ipv6 on target system')
f = open(cfgfile, "w")
f.write("# Anaconda disabling ipv6\n")
f.write("options ipv6 disable=1\n")
f.close()
log.info('Disabling ipv6 on target system')
f = open(cfgfile, "a")
f.write("# Anaconda disabling ipv6 (noipv6 option)\n")
f.write("net.ipv6.conf.all.disable_ipv6=1\n")
f.write("net.ipv6.conf.default.disable_ipv6=1\n")
f.close()
with open(cfgfile, "a") as f: ...
would be better. And should it really be opened for appending?
On 01/29/2013 02:50 PM, Vratislav Podzimek wrote:
On Tue, 2013-01-29 at 13:10 +0100, Radek Vykydal wrote:
pyanaconda/network.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 3c5779f..3c9ef43 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -52,7 +52,7 @@ sysconfigDir = "/etc/sysconfig" netscriptsDir = "%s/network-scripts" % (sysconfigDir) networkConfFile = "%s/network" % (sysconfigDir) hostnameFile = "/etc/hostname" -ipv6ConfFile = "/etc/modprobe.d/ipv6.conf" +ipv6ConfFile = "/etc/sysctl.d/anaconda.conf" ifcfgLogFile = "/tmp/ifcfg.log" CONNECTION_TIMEOUT = 45 DEFAULT_HOSTNAME = "localhost.localdomain" @@ -840,14 +840,12 @@ def disableIPV6(rootpath): if ('noipv6' in flags.cmdline and not any(get_ifcfg_value(dev, 'IPV6INIT') == "yes" for dev in getDevices())):
if os.path.exists(cfgfile):
log.warning('Not disabling ipv6, %s exists' % cfgfile)
else:
log.info('Disabling ipv6 on target system')
f = open(cfgfile, "w")
f.write("# Anaconda disabling ipv6\n")
f.write("options ipv6 disable=1\n")
f.close()
log.info('Disabling ipv6 on target system')
f = open(cfgfile, "a")
f.write("# Anaconda disabling ipv6 (noipv6 option)\n")
f.write("net.ipv6.conf.all.disable_ipv6=1\n")
f.write("net.ipv6.conf.default.disable_ipv6=1\n")
f.close()
with open(cfgfile, "a") as f: ...
would be better. And should it really be opened for appending?
Alright, I'll go with with.
As for the append mode, I am using it because I chose /etc/sysctl/anaconda.conf (anaconda's proper sysctl config file) thinking that another parts of anaconda may want to modify some configuration here too in the future.
In default case, use SLAAC auto configuration (NM's default IPV6_AUTOCONF=yes). --- dracut/parse-kickstart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dracut/parse-kickstart b/dracut/parse-kickstart index 7aeaecd..b88eba7 100755 --- a/dracut/parse-kickstart +++ b/dracut/parse-kickstart @@ -288,7 +288,7 @@ def ksnet_to_ifcfg(net, filename=None): # ipv6 settings if net.noipv6: ifcfg['IPV6INIT'] = "no" - elif net.ipv6: + else: ifcfg['IPV6INIT'] = "yes"
if net.ipv6 == 'dhcp':
We can get also org.freedesktop.DBus.Error.AccessDenied exception --- pyanaconda/isys/__init__.py | 12 ++++++------ pyanaconda/network.py | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/isys/__init__.py b/pyanaconda/isys/__init__.py index 7f4bcb4..998b401 100755 --- a/pyanaconda/isys/__init__.py +++ b/pyanaconda/isys/__init__.py @@ -146,21 +146,21 @@ def getDeviceProperties(dev=None): else: return None
-# Get the MAC address for a network device. def getMacAddress(dev): + """Return MAC address of device. "" if not found""" if dev == '' or dev is None: - return False + return ""
device_props_iface = getDeviceProperties(dev=dev) if device_props_iface is None: - return None + return ""
- device_macaddr = None + device_macaddr = "" try: device_macaddr = device_props_iface.Get(NM_DEVICE_WIRED_IFACE, "HwAddress").upper() except dbus.exceptions.DBusException as e: - if e.get_dbus_name() != 'org.freedesktop.DBus.Error.InvalidArgs': - raise + log.debug("getMacAddress %s: %s" % (dev, e)) + pass return device_macaddr
# Determine if a network device is a wireless device. diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 3c9ef43..0eba86a 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -995,6 +995,8 @@ def get_device_name(devspec): if isys.getMacAddress(d).lower() == devname.lower(): devname = d break + else: + return ""
return devname
@@ -1003,7 +1005,7 @@ def setOnboot(ksdata):
devname = get_device_name(network_data.device) if not devname: - log.error("Kickstart: The provided network interface %s does not exist" % devname) + log.error("Kickstart: The provided network interface %s does not exist" % network_data.device) continue
con = get_NM_connection(devname, spec_type="iface")
On Tue, 2013-01-29 at 13:10 +0100, Radek Vykydal wrote:
We can get also org.freedesktop.DBus.Error.AccessDenied exception
pyanaconda/isys/__init__.py | 12 ++++++------ pyanaconda/network.py | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/isys/__init__.py b/pyanaconda/isys/__init__.py index 7f4bcb4..998b401 100755 --- a/pyanaconda/isys/__init__.py +++ b/pyanaconda/isys/__init__.py @@ -146,21 +146,21 @@ def getDeviceProperties(dev=None): else: return None
-# Get the MAC address for a network device. def getMacAddress(dev):
- """Return MAC address of device. "" if not found""" if dev == '' or dev is None:
return False
return ""
device_props_iface = getDeviceProperties(dev=dev) if device_props_iface is None:
return None
return ""
- device_macaddr = None
- device_macaddr = "" try: device_macaddr = device_props_iface.Get(NM_DEVICE_WIRED_IFACE, "HwAddress").upper() except dbus.exceptions.DBusException as e:
if e.get_dbus_name() != 'org.freedesktop.DBus.Error.InvalidArgs':
raise
log.debug("getMacAddress %s: %s" % (dev, e))
pass
'pass' is not necessary, here. Some leftover? :)
On 01/29/2013 02:52 PM, Vratislav Podzimek wrote:
On Tue, 2013-01-29 at 13:10 +0100, Radek Vykydal wrote:
We can get also org.freedesktop.DBus.Error.AccessDenied exception
pyanaconda/isys/__init__.py | 12 ++++++------ pyanaconda/network.py | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/isys/__init__.py b/pyanaconda/isys/__init__.py index 7f4bcb4..998b401 100755 --- a/pyanaconda/isys/__init__.py +++ b/pyanaconda/isys/__init__.py @@ -146,21 +146,21 @@ def getDeviceProperties(dev=None): else: return None
-# Get the MAC address for a network device. def getMacAddress(dev):
- """Return MAC address of device. "" if not found""" if dev == '' or dev is None:
return False
return "" device_props_iface = getDeviceProperties(dev=dev) if device_props_iface is None:
return None
return ""
- device_macaddr = None
- device_macaddr = "" try: device_macaddr = device_props_iface.Get(NM_DEVICE_WIRED_IFACE, "HwAddress").upper() except dbus.exceptions.DBusException as e:
if e.get_dbus_name() != 'org.freedesktop.DBus.Error.InvalidArgs':
raise
log.debug("getMacAddress %s: %s" % (dev, e))
pass
'pass' is not necessary, here. Some leftover? :)
Yes, thanks.
Crashed for WWAN devices. --- pyanaconda/network.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 0eba86a..503132a 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -812,7 +812,11 @@ def get_ksdevice_name(ksspec=""): # note that NetworkDevice.get returns "" if key is not found def get_ifcfg_value(iface, key, root_path=""): dev = NetworkDevice(os.path.normpath(root_path + netscriptsDir), iface) - dev.loadIfcfgFile() + try: + dev.loadIfcfgFile() + except IOError as e: + log.debug("get_ifcfg_value %s %s: %s" % (iface, key, e)) + return "" return dev.get(key)
def set_hostname(hn):
--- pyanaconda/network.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 503132a..524ddb3 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -828,6 +828,19 @@ def set_hostname(hn): iutil.execWithRedirect("hostname", ["-v", hn ], stdout="/dev/tty5", stderr="/dev/tty5")
+def get_NM_settings_value(iface, key1, key2): + value = "" + con = get_NM_connection(iface, spec_type="iface") + if con: + settings = con.GetSettings() + try: + value = settings[key1][key2] + except KeyError: + log.debug("Can't find setting %s %s for %s" % (key1, key2, iface)) + else: + log.debug("Can't find connection settings for %s" % iface) + return value + def write_hostname(rootpath, ksdata, overwrite=False): cfgfile = os.path.normpath(rootpath + hostnameFile) if (os.path.isfile(cfgfile) and not overwrite): @@ -842,8 +855,8 @@ def write_hostname(rootpath, ksdata, overwrite=False): def disableIPV6(rootpath): cfgfile = os.path.normpath(rootpath + ipv6ConfFile) if ('noipv6' in flags.cmdline - and not any(get_ifcfg_value(dev, 'IPV6INIT') == "yes" - for dev in getDevices())): + and all(get_NM_settings_value(dev, "ipv6", "method") == "ignore" + for dev in getDevices())): log.info('Disabling ipv6 on target system') f = open(cfgfile, "a") f.write("# Anaconda disabling ipv6 (noipv6 option)\n")
Apart from the two minor comments these all look good to me.
anaconda-patches@lists.fedorahosted.org