#
# network.py - network configuration install data
#
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
# 2008, 2009
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Author(s): Matt Wilson
# Erik Troan
# Mike Fulbright
# Brent Fox
# David Cantrell
#
import string
import shutil
import isys
import iutil
import socket
import struct
import os
import time
import dbus
import urlgrabber
from flags import flags
from simpleconfig import IfcfgFile
import anaconda_log
import gettext
_ = lambda x: gettext.ldgettext("anaconda", x)
import logging
log = logging.getLogger("anaconda")
sysconfigDir = "/etc/sysconfig"
netscriptsDir = "%s/network-scripts" % (sysconfigDir)
networkConfFile = "%s/network" % (sysconfigDir)
ipv6ConfFile = "/etc/modprobe.d/ipv6.conf"
ifcfgLogFile = "/tmp/ifcfg.log"
CONNECTION_TIMEOUT = 45
logger = logging.getLogger("ifcfg")
logger.setLevel(logging.DEBUG)
anaconda_log.logger.addFileHandler(ifcfgLogFile, logger, logging.DEBUG)
anaconda_log.logger.addFileHandler("/dev/tty3", logger, logging.DEBUG)
ifcfglog = logging.getLogger("ifcfg")
class IPError(Exception):
pass
class IPMissing(Exception):
pass
def sanityCheckHostname(hostname):
if len(hostname) < 1:
return None
if len(hostname) > 255:
return _("Hostname must be 255 or fewer characters in length.")
validStart = string.ascii_letters + string.digits
validAll = validStart + ".-"
if string.find(validStart, hostname[0]) == -1:
return _("Hostname must start with a valid character in the ranges "
"'a-z', 'A-Z', or '0-9'")
for i in range(1, len(hostname)):
if string.find(validAll, hostname[i]) == -1:
return _("Hostnames can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.'")
return None
# Try to determine what the hostname should be for this system
def getDefaultHostname(anaconda):
isys.resetResolv()
hn = None
# First address (we prefer ipv4) of last device (as it used to be) wins
for dev in getActiveNetDevs():
addrs = (isys.getIPAddresses(dev, version=4) +
isys.getIPAddresses(dev, version=6))
for ipaddr in addrs:
try:
hinfo = socket.gethostbyaddr(ipaddr)
except Exception as e:
log.debug("Exception caught trying to get host name of %s: %s" %
(ipaddr, e))
else:
if len(hinfo) == 3:
hn = hinfo[0]
break
if hn and hn != 'localhost' and hn != 'localhost.localdomain':
return hn
try:
hn = anaconda.id.network.hostname
except:
hn = None
if not hn or hn == '(none)' or hn == 'localhost' or hn == 'localhost.localdomain':
hn = socket.gethostname()
if not hn or hn == '(none)' or hn == 'localhost':
hn = 'localhost.localdomain'
return hn
# sanity check an IP string.
def sanityCheckIPString(ip_string):
if ip_string.strip() == "":
raise IPMissing, _("IP address is missing.")
if ip_string.find(':') == -1 and ip_string.find('.') > 0:
family = socket.AF_INET
errstr = _("IPv4 addresses must contain four numbers between 0 and 255, separated by periods.")
elif ip_string.find(':') > 0 and ip_string.find('.') == -1:
family = socket.AF_INET6
errstr = _("'%s' is not a valid IPv6 address.") % ip_string
else:
raise IPError, _("'%s' is an invalid IP address.") % ip_string
try:
socket.inet_pton(family, ip_string)
except socket.error:
raise IPError, errstr
def hasActiveNetDev():
try:
bus = dbus.SystemBus()
nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
props = dbus.Interface(nm, isys.DBUS_PROPS_IFACE)
state = props.Get(isys.NM_SERVICE, "State")
if int(state) == isys.NM_STATE_CONNECTED:
return True
else:
return False
except:
return False
# Return a list of device names (e.g., eth0) for all active devices.
# Returning a list here even though we will almost always have one
# device. NM uses lists throughout its D-Bus communication, so trying
# to follow suit here. Also, if this uses a list now, we can think
# about multihomed hosts during installation later.
def getActiveNetDevs():
active_devs = set()
bus = dbus.SystemBus()
nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
nm_props_iface = dbus.Interface(nm, isys.DBUS_PROPS_IFACE)
active_connections = nm_props_iface.Get(isys.NM_MANAGER_IFACE, "ActiveConnections")
for connection in active_connections:
active_connection = bus.get_object(isys.NM_SERVICE, connection)
active_connection_props_iface = dbus.Interface(active_connection, isys.DBUS_PROPS_IFACE)
devices = active_connection_props_iface.Get(isys.NM_ACTIVE_CONNECTION_IFACE, 'Devices')
for device_path in devices:
device = bus.get_object(isys.NM_SERVICE, device_path)
device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE)
interface_name = device_props_iface.Get(isys.NM_DEVICE_IFACE, 'Interface')
active_devs.add(interface_name)
ret = list(active_devs)
ret.sort()
return ret
def logIfcfgFile(path, message=""):
content = ""
if os.access(path, os.R_OK):
f = open(path, 'r')
content = f.read()
f.close()
ifcfglog.debug("%s%s:\n%s" % (message, path, content))
def logIfcfgFiles(message=""):
devprops = isys.getDeviceProperties(dev=None)
for device in devprops:
path = "%s/ifcfg-%s" % (netscriptsDir, device)
logIfcfgFile(path, message)
class NetworkDevice(IfcfgFile):
def __init__(self, dir, iface):
IfcfgFile.__init__(self, dir, iface)
if iface.startswith('ctc'):
self.info["TYPE"] = "CTC"
self.description = ""
self._dirty = False
def clear(self):
IfcfgFile.clear(self)
if self.iface.startswith('ctc'):
self.info["TYPE"] = "CTC"
def __str__(self):
s = ""
keys = self.info.keys()
keys.sort()
if ("DEVICE" in keys):
keys.remove("DEVICE")
keys.insert(0, "DEVICE")
if "KEY" in keys:
keys.remove("KEY")
if iutil.isS390() and ("HWADDR" in keys):
keys.remove("HWADDR")
# make sure we include autoneg in the ethtool line
if 'ETHTOOL_OPTS' in keys:
eopts = self.get('ETHTOOL_OPTS')
if "autoneg" not in eopts:
self.set(('ETHTOOL_OPTS', "autoneg off %s" % eopts))
for key in keys:
if self.info[key] is not None:
s = s + key + '="' + self.info[key] + '"\n'
return s
def loadIfcfgFile(self):
ifcfglog.debug("%s:\n%s" % (self.path, self.fileContent()))
ifcfglog.debug("NetworkDevice %s:\n%s" % (self.iface, self.__str__()))
ifcfglog.debug("loadIfcfgFile %s from %s" % (self.iface, self.path))
self.clear()
IfcfgFile.read(self)
self._dirty = False
ifcfglog.debug("NetworkDevice %s:\n%s" % (self.iface, self.__str__()))
def writeIfcfgFile(self):
# Write out the file only if there is a key whose
# value has been changed since last load of ifcfg file.
ifcfglog.debug("%s:\n%s" % (self.path, self.fileContent()))
ifcfglog.debug("NetworkDevice %s:\n%s" % (self.iface, self.__str__()))
ifcfglog.debug("writeIfcfgFile %s to %s%s" % (self.iface, self.path,
("" if self._dirty else " not needed")))
if self._dirty:
IfcfgFile.write(self)
self._dirty = False
def set(self, *args):
# If we are changing value of a key set _dirty flag
# informing that ifcfg file needs to be synced.
s = " ".join(["%s=%s" % key_val for key_val in args])
ifcfglog.debug("NetworkDevice %s set: %s" %
(self.iface, s))
for (key, data) in args:
if self.get(key) != data:
break
else:
return
IfcfgFile.set(self, *args)
self._dirty = True
def fileContent(self):
f = open(self.path, 'r')
content = f.read()
f.close()
return content
def usedByFCoE(self, anaconda):
import storage
for d in anaconda.id.storage.devices:
if (isinstance(d, storage.devices.FcoeDiskDevice) and
d.nic == self.iface):
return True
return False
def usedByRootOnISCSI(self, anaconda):
import storage
rootdev = anaconda.id.storage.rootDevice
for d in anaconda.id.storage.devices:
if (isinstance(d, storage.devices.iScsiDiskDevice) and
rootdev.dependsOn(d)):
if d.nic == "default" or ":" in d.nic:
if self.iface == ifaceForHostIP(d.host_address):
return True
elif d.nic == self.iface:
return True
return False
class Network:
def __init__(self):
self.hostname = socket.gethostname()
self.overrideDHCPhostname = False
self.update()
# We want wireless devices to be nm controlled by default
self.controlWireless()
# Set all devices to be controlled by NM by default.
# We can filter out storage devices only after
# we have device tree populated. So we do it before
# running nm-c-e and before writing ifcfg files to system.
self.setNMControlledDevices(self.netdevices.keys())
self.updateNMiBFTDevices()
def update(self):
ifcfglog.debug("Network.update() called")
self.netdevices = {}
self.ksdevice = None
# populate self.netdevices
devhash = isys.getDeviceProperties(dev=None)
for iface in devhash.keys():
device = NetworkDevice(netscriptsDir, iface)
if os.access(device.path, os.R_OK):
device.loadIfcfgFile()
else:
log.info("Network.update(): %s file not found" %
device.path)
continue
# TODORV - the last iface in loop wins, might be ok,
# not worthy of special juggling
if device.get('HOSTNAME'):
self.hostname = device.get('HOSTNAME')
device.description = isys.getNetDevDesc(iface)
self.netdevices[iface] = device
ksdevice = flags.cmdline.get('ksdevice', None)
if ksdevice:
bootif_mac = None
if ksdevice == 'bootif' and flags.cmdline.get("BOOTIF"):
bootif_mac = flags.cmdline.get("BOOTIF")[3:].replace("-", ":").upper()
# sort for ksdevice=link (to select the same device as in loader))
for dev in sorted(self.netdevices):
mac = self.netdevices[dev].get('HWADDR').upper()
if ksdevice == 'link' and isys.getLinkStatus(dev):
self.ksdevice = dev
break
elif ksdevice == 'bootif':
if bootif_mac == mac:
self.ksdevice = dev
break
elif ksdevice == dev:
self.ksdevice = dev
break
elif ':' in ksdevice:
if ksdevice.upper() == mac:
self.ksdevice = dev
break
def getDevice(self, device):
return self.netdevices[device]
def getKSDevice(self):
if self.ksdevice is None:
return None
try:
return self.netdevices[self.ksdevice]
except:
return None
def setHostname(self, hn):
self.hostname = hn
log.info("setting installation environment hostname to %s" % hn)
iutil.execWithRedirect("hostname", ["-v", hn ],
stdout="/dev/tty5", stderr="/dev/tty5")
def unsetDNS(self, devname):
"""Unset all DNS* ifcfg parameters."""
i = 1
dev = self.netdevices[devname]
while True:
if dev.get("DNS%d" % i):
dev.unset("DNS%d" %i)
else:
break
i += 1
def setDNS(self, ns, device):
dns = ns.split(',')
i = 1
for addr in dns:
addr = addr.strip()
dnslabel = "DNS%d" % (i,)
self.netdevices[device].set((dnslabel, addr))
i += 1
@property
def gateway(self):
"""GATEWAY - last device in list wins"""
for dev in reversed(self.netdevices.values()):
if dev.get('GATEWAY'):
return dev.get('GATEWAY')
return ""
@property
def ipv6_defaultgw(self):
"""IPV6_DEFAULTGW - last device in list wins"""
for dev in reversed(self.netdevices.values()):
if dev.get('IPV6_DEFAULTGW'):
return dev.get('IPV6_DEFAULTGW')
return ""
def setGateway(self, gw, device):
if ':' in gw:
self.netdevices[device].set(('IPV6_DEFAULTGW', gw))
else:
self.netdevices[device].set(('GATEWAY', gw))
def lookupHostname(self):
# can't look things up if they don't exist!
if not self.hostname or self.hostname == "localhost.localdomain":
return None
if not hasActiveNetDev():
log.warning("no network devices were available to look up host name")
return None
try:
(family, socktype, proto, canonname, sockaddr) = \
socket.getaddrinfo(self.hostname, None, socket.AF_INET)[0]
(ip, port) = sockaddr
except:
try:
(family, socktype, proto, canonname, sockaddr) = \
socket.getaddrinfo(self.hostname, None, socket.AF_INET6)[0]
(ip, port, flowinfo, scopeid) = sockaddr
except:
return None
return ip
# Note that the file is written-out only if there is a value
# that has changed.
def writeIfcfgFiles(self):
for device in self.netdevices.values():
device.writeIfcfgFile()
# devices == None => set for all
def setNMControlledDevices(self, devices=None):
for devname, device in self.netdevices.items():
if devices and devname not in devices:
device.set(('NM_CONTROLLED', 'no'))
else:
device.set(('NM_CONTROLLED', 'yes'))
# Because of possible race in loader devices activated by NM with iBFT
# connection might not have correct ifcfg file (BOOTPROTO=ibft) created.
# It is required for compatibility and supplying dracut ip=ibft option at
# the end of installation. Also handles case of multiple ibft devices
# (#831002).
def updateNMiBFTDevices(self):
bus = dbus.SystemBus()
nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
nm_props_iface = dbus.Interface(nm, isys.DBUS_PROPS_IFACE)
active_connections = nm_props_iface.Get(isys.NM_MANAGER_IFACE, "ActiveConnections")
# Look for active connections named with 'iBFT' prefix (created by NM)
for connection in active_connections:
active_connection = bus.get_object(isys.NM_SERVICE, connection)
active_connection_props_iface = dbus.Interface(active_connection, isys.DBUS_PROPS_IFACE)
setting_path = active_connection_props_iface.Get(isys.NM_ACTIVE_CONNECTION_IFACE, 'Connection')
setting = bus.get_object(isys.NM_SERVICE, setting_path)
settings = setting.get_dbus_method("GetSettings")()
try:
con_id = str(settings['connection']['id'])
except KeyError:
con_id = ''
if con_id.startswith('iBFT'):
# Find the device using active 'iBFT' connection
devices = active_connection_props_iface.Get(isys.NM_ACTIVE_CONNECTION_IFACE, 'Devices')
for device_path in devices:
device = bus.get_object(isys.NM_SERVICE, device_path)
device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE)
interface_name = device_props_iface.Get(isys.NM_DEVICE_IFACE, 'Interface')
# Update ifcfg of the device if needed
if interface_name in self.netdevices:
dev = self.netdevices[interface_name]
if dev.get('BOOTPROTO') != "ibft":
dev.set(('BOOTPROTO', "ibft"))
dev.set(('ONBOOT', "yes"))
dev.writeIfcfgFile()
# For vlan create the ifcfg
elif settings['connection']['type'] == "vlan":
buf = """
DEVICE=%s
UUID=%s
ONBOOT=yes
TYPE=Vlan
VLAN=yes
BOOTPROTO=ibft
""" % (interface_name, settings['connection']['uuid'])
ifcfgfile = "%s/ifcfg-%s" % (netscriptsDir, interface_name)
f = open(ifcfgfile, "w")
f.write(buf)
f.close()
device = NetworkDevice(netscriptsDir, interface_name)
device.loadIfcfgFile()
self.netdevices[interface_name] = device
# devices == None => set for all
def updateActiveDevices(self, devices=None):
for devname, device in self.netdevices.items():
if devices and devname not in devices:
device.set(('ONBOOT', 'no'))
else:
device.set(('ONBOOT', 'yes'))
def getOnbootControlledIfaces(self):
ifaces = []
for iface, device in self.netdevices.items():
if (device.get('ONBOOT') == "yes" and
device.get('NM_CONTROLLED') == "yes"):
ifaces.append(iface)
return ifaces
def controlWireless(self):
for devname, device in self.netdevices.items():
if isys.isWireless(devname):
device.set(('NM_CONTROLLED', 'yes'))
def writeKS(self, f):
devNames = self.netdevices.keys()
devNames.sort()
if len(devNames) == 0:
return
for devName in devNames:
dev = self.netdevices[devName]
line = "network"
# split vlanid from device
if dev.get("TYPE") == "Vlan":
(device, sep, vlanid) = dev.get("DEVICE").rpartition('.')
else:
device = dev.get("DEVICE")
# ipv4 and ipv6
if dev.get("ONBOOT"):
line += " --onboot %s" % dev.get("ONBOOT")
line += " --device %s" % device
if dev.get('MTU') and dev.get('MTU') != "0":
line += " --mtu=%s" % dev.get('MTU')
# ipv4
if not dev.get('BOOTPROTO'):
line += " --noipv4"
else:
if dev.get('BOOTPROTO').lower() == 'dhcp':
line += " --bootproto dhcp"
if dev.get('DHCPCLASS'):
line += " --dhcpclass %s" % dev.get('DHCPCLASS')
elif dev.get('IPADDR'):
line += " --bootproto static --ip %s" % dev.get('IPADDR')
netmask = dev.get('NETMASK')
prefix = dev.get('PREFIX')
if not netmask and prefix:
netmask = isys.prefix2netmask(int(prefix))
if netmask:
line += " --netmask %s" % netmask
# note that --gateway is common for ipv4 and ipv6
if dev.get('GATEWAY'):
line += " --gateway %s" % dev.get('GATEWAY')
# ipv6
if (not dev.get('IPV6INIT') or
dev.get('IPV6INIT') == "no"):
line += " --noipv6"
else:
if dev.get('IPV6_AUTOCONF') == "yes":
line += " --ipv6 auto"
else:
if dev.get('IPV6ADDR'):
line += " --ipv6 %s" % dev.get('IPV6ADDR')
if dev.get('IPV6_DEFAULTGW'):
line += " --ipv6gateway %s" % dev.get('IPV6_DEFAULTGW')
if dev.get('DHCPV6') == "yes":
line += " --ipv6 dhcp"
# ipv4 and ipv6
dnsline = ''
for key in dev.info.keys():
if key.upper().startswith('DNS'):
if dnsline == '':
dnsline = dev.get(key)
else:
dnsline += "," + dev.get(key)
if dnsline:
line += " --nameserver %s" % dnsline
if dev.get("ETHTOOL_OPTS"):
line += " --ethtool %s" % dev.get("ETHTOOL_OPTS")
# hostname
if (self.overrideDHCPhostname or
(dev.get('BOOTPROTO') and dev.get('BOOTPROTO').lower() != "dhcp")):
if (self.hostname and
self.hostname != "localhost.localdomain"):
line += " --hostname %s" % self.hostname
# vlanid
if dev.get("TYPE") == "Vlan":
line += " --vlanid %s" % vlanid
# bonding
if dev.get('TYPE') == "Bond":
slaves = [dname for dname, d in self.netdevices.items()
if d.get('MASTER') == devName]
line += " --bondslaves %s" % ",".join(slaves)
bondopts = dev.get('BONDING_OPTS').split()
separator = "," if all(',' not in opt for opt in bondopts) else ";"
line += " --bondopts %s" % separator.join(bondopts)
if dev.get("DOMAIN"):
line += " --domain %s" % dev.get("DOMAIN")
if dev.get("DEFROUTE") == "no":
line += " --nodefroute"
line += "\n"
f.write(line)
def _copyFileToPath(self, file, instPath='', overwrite=False):
if not os.path.isfile(file):
return False
destfile = os.path.join(instPath, file.lstrip('/'))
if (os.path.isfile(destfile) and not overwrite):
return False
if not os.path.isdir(os.path.dirname(destfile)):
iutil.mkdirChain(os.path.dirname(destfile))
shutil.copy(file, destfile)
return True
def copyConfigToPath(self, instPath=''):
if len(self.netdevices) == 0:
return
# /etc/sysconfig/network-scripts/ifcfg-DEVICE
# /etc/dhcp/dhclient-DEVICE.conf
# TODORV: do we really don't want overwrite on live cd?
for devName, device in self.netdevices.items():
self._copyFileToPath(device.path, instPath)
dhclientfile = os.path.join("/etc/dhcp/dhclient-%s.conf" % devName)
self._copyFileToPath(dhclientfile, instPath)
# /etc/sysconfig/network
self._copyFileToPath(networkConfFile, instPath,
overwrite=flags.livecdInstall)
# /etc/resolv.conf
self._copyFileToPath("/etc/resolv.conf", instPath,
overwrite=flags.livecdInstall)
# /etc/udev/rules.d/70-persistent-net.rules
self._copyFileToPath("/etc/udev/rules.d/70-persistent-net.rules",
instPath, overwrite=flags.livecdInstall)
self._copyFileToPath(ipv6ConfFile, instPath,
overwrite=flags.livecdInstall)
def disableNMForStorageDevices(self, anaconda, instPath=''):
for devName, device in self.netdevices.items():
if (device.usedByFCoE(anaconda) or
device.usedByRootOnISCSI(anaconda)):
devNames = [devName]
# for vlan configured in ibft turn off NM also for parent
if device.get("TYPE") == "Vlan" and device.get("BOOTPROTO") == "ibft":
devNames.append(devName.split(".")[0])
for name in devNames:
dev = NetworkDevice(instPath + netscriptsDir, name)
if os.access(dev.path, os.R_OK):
dev.loadIfcfgFile()
dev.set(('NM_CONTROLLED', 'no'))
dev.writeIfcfgFile()
log.info("network device %s used by storage will not be "
"controlled by NM" % device.path)
else:
log.warning("disableNMForStorageDevices: %s file not found" %
device.path)
def autostartFCoEDevices(self, anaconda, instPath=''):
for devName, device in self.netdevices.items():
if device.usedByFCoE(anaconda):
dev = NetworkDevice(instPath + netscriptsDir, devName)
if os.access(dev.path, os.R_OK):
dev.loadIfcfgFile()
dev.set(('ONBOOT', 'yes'))
dev.writeIfcfgFile()
log.debug("setting ONBOOT=yes for network device %s used by fcoe"
% device.path)
else:
log.warning("autoconnectFCoEDevices: %s file not found" %
device.path)
def enableBondingDevice(self, devName, instPath=''):
dev = NetworkDevice(instPath + netscriptsDir, devName)
self.netdevices[devName] = dev
dev.set(("DEVICE", devName))
dev.set(("TYPE", "Bond"))
dev.set(("NM_CONTROLLED", "yes"))
if not os.access(dev.path, os.R_OK):
f = open(dev.path, "w")
f.close()
dev.writeIfcfgFile()
return dev
def hasActiveIPoIBDevice(self):
active_devs = getActiveNetDevs()
for devName, device in self.netdevices.items():
if (devName in active_devs and
device.get('TYPE') == 'Infiniband'):
return True
return False
def hasVlanDevice(self):
return any(dev for dev in self.netdevices.values()
if dev.get('TYPE') == 'Vlan')
def hasBondDevice(self):
return any (dev for dev in self.netdevices.values()
if dev.get('TYPE') == 'Bond')
def write(self):
ifcfglog.debug("Network.write() called")
devices = self.netdevices.values()
if len(devices) == 0:
return
# /etc/sysconfig/network-scripts/ifcfg-*
for dev in devices:
device = dev.get('DEVICE')
bootproto = dev.get('BOOTPROTO').lower()
# write out the hostname as DHCP_HOSTNAME if given (#81613)
if (bootproto == 'dhcp' and self.hostname and
self.overrideDHCPhostname):
dev.set(('DHCP_HOSTNAME', self.hostname))
dev.writeIfcfgFile()
# XXX: is this necessary with NetworkManager?
# handle the keys* files if we have those
if dev.get("KEY"):
cfgfile = "%s/keys-%s" % (netscriptsDir, device,)
newkey = "%s/keys-%s.new" % (netscriptsDir, device,)
f = open(newkey, "w")
f.write("KEY=%s\n" % (dev.get('KEY'),))
f.close()
os.chmod(newkey, 0600)
destkey = "%s/keys-%s" % (netscriptsDir, device,)
shutil.move(newkey, destkey)
# /etc/sysconfig/network
newnetwork = "%s.new" % (networkConfFile)
f = open(newnetwork, "w")
f.write("NETWORKING=yes\n")
f.write("HOSTNAME=")
# use instclass hostname if set(kickstart) to override
if self.hostname:
f.write(self.hostname + "\n")
else:
f.write("localhost.localdomain\n")
if self.ipv6_defaultgw:
f.write("IPV6_DEFAULTGW=%s\n" % self.ipv6_defaultgw)
if self.hasBondDevice() or self.hasVlanDevice():
f.write("NM_BOND_VLAN_ENABLED=yes\n")
f.close()
shutil.move(newnetwork, networkConfFile)
# /etc/resolv.conf is managed by NM
# disable ipv6
if ('noipv6' in flags.cmdline
and not [dev for dev in devices
if dev.get('IPV6INIT') == "yes"]):
if os.path.exists(ipv6ConfFile):
log.debug('%s exists' % ipv6ConfFile)
else:
log.info('Disabling ipv6 on target system')
f = open(ipv6ConfFile, "w")
f.write("# Anaconda disabling ipv6\n")
f.write("options ipv6 disable=1\n")
f.close()
def waitForDevice(self, device, timeout=CONNECTION_TIMEOUT):
props = isys.getDeviceProperties(device)
i = 0
while not props and i < timeout:
props = isys.getDeviceProperties(device)
i += 1
time.sleep(1)
return bool(props)
def waitForDevicesActivation(self, devices):
waited_devs_props = {}
bus = dbus.SystemBus()
nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
device_paths = nm.get_dbus_method("GetDevices")()
for device_path in device_paths:
device = bus.get_object(isys.NM_SERVICE, device_path)
device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE)
iface = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface"))
if iface in devices:
waited_devs_props[iface] = device_props_iface
i = 0
reset_resolver = False
while True:
for dev, device_props_iface in waited_devs_props.items():
state = device_props_iface.Get(isys.NM_DEVICE_IFACE, "State")
if state == isys.NM_DEVICE_STATE_ACTIVATED:
waited_devs_props.pop(dev)
reset_resolver = True
if len(waited_devs_props) == 0 or i >= CONNECTION_TIMEOUT:
break
i += 1
time.sleep(1)
if reset_resolver:
isys.resetResolv()
return waited_devs_props.keys()
# write out current configuration state and wait for NetworkManager
# to bring the device up, watch NM state and return to the caller
# once we have a state
def waitForConnection(self):
bus = dbus.SystemBus()
nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
props = dbus.Interface(nm, isys.DBUS_PROPS_IFACE)
i = 0
while i < CONNECTION_TIMEOUT:
state = props.Get(isys.NM_SERVICE, "State")
if int(state) == isys.NM_STATE_CONNECTED:
isys.resetResolv()
return True
i += 1
time.sleep(1)
state = props.Get(isys.NM_SERVICE, "State")
if int(state) == isys.NM_STATE_CONNECTED:
isys.resetResolv()
return True
return False
# write out current configuration state and wait for NetworkManager
# to bring the device up, watch NM state and return to the caller
# once we have a state
def bringUp(self):
self.write()
return self.waitForConnection()
def disconnectDevice(self, devname):
bus = dbus.SystemBus()
nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
device_paths = nm.get_dbus_method("GetDevices")()
for device_path in device_paths:
device = bus.get_object(isys.NM_SERVICE, device_path)
device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE)
iface = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface"))
if iface == devname:
try:
device.get_dbus_method("Disconnect")()
except dbus.DBusException as e:
log.debug("disconnectDevice %s: %s" % (devname, e))
return False
return True
return False
# get a kernel cmdline string for dracut needed for access to host host
def dracutSetupArgs(self, networkStorageDevice):
netargs=set()
if networkStorageDevice.nic == "default" or ":" in networkStorageDevice.nic:
nic = ifaceForHostIP(networkStorageDevice.host_address)
if not nic:
return ""
else:
nic = networkStorageDevice.nic
if nic not in self.netdevices.keys():
log.error('Unknown network interface: %s' % nic)
return ""
dev = self.netdevices[nic]
if dev.get('BOOTPROTO') == 'ibft':
netargs.add("ip=ibft")
elif networkStorageDevice.host_address:
if self.hostname:
hostname = self.hostname
else:
hostname = ""
# if using ipv6
if ':' in networkStorageDevice.host_address:
if dev.get('DHCPV6C') == "yes":
# XXX combination with autoconf not yet clear,
# support for dhcpv6 is not yet implemented in NM/ifcfg-rh
netargs.add("ip=%s:dhcp6" % nic)
elif dev.get('IPV6_AUTOCONF') == "yes":
netargs.add("ip=%s:auto6" % nic)
elif dev.get('IPV6ADDR'):
ipaddr = "[%s]" % dev.get('IPV6ADDR')
if dev.get('IPV6_DEFAULTGW'):
gateway = "[%s]" % dev.get('IPV6_DEFAULTGW')
else:
gateway = ""
netargs.add("ip=%s::%s:%s:%s:%s:none" % (ipaddr, gateway,
dev.get('PREFIX'), hostname, nic))
else:
if dev.get('bootproto').lower() == 'dhcp':
netargs.add("ip=%s:dhcp" % nic)
else:
if dev.get('GATEWAY'):
gateway = dev.get('GATEWAY')
else:
gateway = ""
netmask = dev.get('netmask')
prefix = dev.get('prefix')
if not netmask and prefix:
netmask = isys.prefix2netmask(int(prefix))
netargs.add("ip=%s::%s:%s:%s:%s:none" % (dev.get('ipaddr'),
gateway, netmask, hostname, nic))
# ifname= prevents dracut from renaming the devices configured with ip=ibft
# to ibftX on installed system
hwaddr = dev.get("HWADDR")
if hwaddr:
netargs.add("ifname=%s:%s" % (nic, hwaddr.lower()))
# For vlan devices configured in ibft we need to bind name of the parent
if dev.get('BOOTPROTO') == 'ibft' and dev.get("TYPE") == "Vlan":
parent_nic = nic.split(".")[0]
parent_dev = self.netdevices[parent_nic]
parent_hwaddr = parent_dev.get("HWADDR")
netargs.add("ifname=%s:%s" % (parent_nic, parent_hwaddr.lower()))
nettype = dev.get("NETTYPE")
subchannels = dev.get("SUBCHANNELS")
if iutil.isS390() and nettype and subchannels:
znet = "rd_ZNET=%s,%s" % (nettype, subchannels)
options = dev.get("OPTIONS").strip("'\"")
if options:
options = filter(lambda x: x != '', options.split(' '))
znet += ",%s" % (','.join(options))
netargs.add(znet)
return netargs
def ifaceForHostIP(host):
route = iutil.execWithCapture("ip", [ "route", "get", "to", host ])
if not route:
log.error("Could not get interface for route to %s" % host)
return ""
routeInfo = route.split()
if routeInfo[0] != host or len(routeInfo) < 5 or \
"dev" not in routeInfo or routeInfo.index("dev") > 3:
log.error('Unexpected "ip route get to %s" reply: %s' %
(host, routeInfo))
return ""
return routeInfo[routeInfo.index("dev") + 1]
def saveExceptionEnableNetwork(intf):
if not hasActiveNetDev():
if intf.messageWindow(_("Warning"),
_("You do not have an active network connection. This is "
"required by some exception saving methods. Would you "
"like to configure your network now?"),
type = "yesno"):
if not intf.enableNetwork():
intf.messageWindow(_("No Network Available"),
_("Remote exception saving methods will not work."))
else:
urlgrabber.grabber.reset_curl_obj()