Package pyanaconda :: Module network
[hide private]
[frames] | no frames]

Source Code for Module pyanaconda.network

   1  # 
   2  # network.py - network configuration install data 
   3  # 
   4  # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007  Red Hat, Inc. 
   5  #               2008, 2009 
   6  # 
   7  # This program is free software; you can redistribute it and/or modify 
   8  # it under the terms of the GNU General Public License as published by 
   9  # the Free Software Foundation; either version 2 of the License, or 
  10  # (at your option) any later version. 
  11  # 
  12  # This program is distributed in the hope that it will be useful, 
  13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  # GNU General Public License for more details. 
  16  # 
  17  # You should have received a copy of the GNU General Public License 
  18  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  19  # 
  20  # Author(s): Matt Wilson <ewt@redhat.com> 
  21  #            Erik Troan <ewt@redhat.com> 
  22  #            Mike Fulbright <msf@redhat.com> 
  23  #            Brent Fox <bfox@redhat.com> 
  24  #            David Cantrell <dcantrell@redhat.com> 
  25  # 
  26   
  27  import string 
  28  import shutil 
  29  import isys 
  30  import iutil 
  31  import socket 
  32  import struct 
  33  import os 
  34  import time 
  35  import dbus 
  36  import tempfile 
  37  import simpleconfig 
  38  from flags import flags 
  39  from simpleconfig import IfcfgFile 
  40  from pyanaconda.constants import ROOT_PATH 
  41  import urlgrabber.grabber 
  42   
  43  import gettext 
  44  _ = lambda x: gettext.ldgettext("anaconda", x) 
  45   
  46  import logging 
  47  log = logging.getLogger("anaconda") 
  48   
  49  sysconfigDir = "/etc/sysconfig" 
  50  netscriptsDir = "%s/network-scripts" % (sysconfigDir) 
  51  networkConfFile = "%s/network" % (sysconfigDir) 
  52  ipv6ConfFile = "/etc/modprobe.d/ipv6.conf" 
  53  ifcfgLogFile = "/tmp/ifcfg.log" 
  54  CONNECTION_TIMEOUT = 45 
  55   
  56  # Setup special logging for ifcfg NM interface 
  57  from pyanaconda import anaconda_log 
  58  logger = logging.getLogger("ifcfg") 
  59  logger.setLevel(logging.DEBUG) 
  60  anaconda_log.logger.addFileHandler(ifcfgLogFile, logger, logging.DEBUG) 
  61  if os.access("/dev/tty3", os.W_OK): 
  62      anaconda_log.logger.addFileHandler("/dev/tty3", logger, 
  63                                         anaconda_log.DEFAULT_TTY_LEVEL, 
  64                                         anaconda_log.TTY_FORMAT, 
  65                                         autoLevel=True) 
  66  anaconda_log.logger.forwardToSyslog(logger) 
  67   
  68  ifcfglog = logging.getLogger("ifcfg") 
69 70 -class IPError(Exception):
71 pass
72
73 -class IPMissing(Exception):
74 pass
75
76 -def sanityCheckHostname(hostname):
77 if not hostname: 78 return None 79 80 if len(hostname) > 255: 81 return _("Hostname must be 255 or fewer characters in length.") 82 83 validStart = string.ascii_letters + string.digits 84 validAll = validStart + ".-" 85 86 if hostname[0] not in validStart: 87 return _("Hostname must start with a valid character in the ranges " 88 "'a-z', 'A-Z', or '0-9'") 89 90 for char in hostname[1:]: 91 if char not in validAll: 92 return _("Hostnames can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.'") 93 94 return None
95
96 # Try to determine what the hostname should be for this system 97 -def getDefaultHostname(anaconda):
98 resetResolver() 99 100 hn = None 101 102 # First address (we prefer ipv4) of last device (as it used to be) wins 103 for dev in getActiveNetDevs(): 104 addrs = (isys.getIPAddresses(dev, version=4) + 105 isys.getIPAddresses(dev, version=6)) 106 for ipaddr in addrs: 107 try: 108 hinfo = socket.gethostbyaddr(ipaddr) 109 except Exception as e: 110 log.debug("Exception caught trying to get host name of %s: %s" % 111 (ipaddr, e)) 112 else: 113 if len(hinfo) == 3: 114 hn = hinfo[0] 115 break 116 117 if hn and hn not in ('(none)', 'localhost', 'localhost.localdomain'): 118 return hn 119 120 try: 121 hn = anaconda.network.hostname 122 except: 123 hn = None 124 125 if not hn or hn in ('(none)', 'localhost', 'localhost.localdomain'): 126 hn = socket.gethostname() 127 128 if not hn or hn in ('(none)', 'localhost'): 129 hn = 'localhost.localdomain' 130 131 return hn
132
133 # sanity check an IP string. 134 -def sanityCheckIPString(ip_string):
135 if not ip_string.strip(): 136 raise IPMissing, _("IP address is missing.") 137 138 if '.' in ip_string[1:] and ':' not in ip_string: 139 family = socket.AF_INET 140 errstr = _("IPv4 addresses must contain four numbers between 0 and 255, separated by periods.") 141 elif ':' in ip_string[1:] and '.' not in ip_string: 142 family = socket.AF_INET6 143 errstr = _("'%s' is not a valid IPv6 address.") % ip_string 144 else: 145 raise IPError, _("'%s' is an invalid IP address.") % ip_string 146 147 try: 148 socket.inet_pton(family, ip_string) 149 except socket.error: 150 raise IPError, errstr
151
152 -def nmIsConnected(state):
153 return state in (isys.NM_STATE_CONNECTED_LOCAL, 154 isys.NM_STATE_CONNECTED_SITE, 155 isys.NM_STATE_CONNECTED_GLOBAL)
156
157 -def hasActiveNetDev():
158 try: 159 bus = dbus.SystemBus() 160 nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH) 161 props = dbus.Interface(nm, isys.DBUS_PROPS_IFACE) 162 state = props.Get(isys.NM_SERVICE, "State") 163 164 return nmIsConnected(state) 165 except: 166 return False
167
168 # Return a list of device names (e.g., eth0) for all active devices. 169 # Returning a list here even though we will almost always have one 170 # device. NM uses lists throughout its D-Bus communication, so trying 171 # to follow suit here. Also, if this uses a list now, we can think 172 # about multihomed hosts during installation later. 173 -def getActiveNetDevs():
174 active_devs = set() 175 176 bus = dbus.SystemBus() 177 nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH) 178 nm_props_iface = dbus.Interface(nm, isys.DBUS_PROPS_IFACE) 179 180 active_connections = nm_props_iface.Get(isys.NM_MANAGER_IFACE, "ActiveConnections") 181 182 for connection in active_connections: 183 active_connection = bus.get_object(isys.NM_SERVICE, connection) 184 active_connection_props_iface = dbus.Interface(active_connection, isys.DBUS_PROPS_IFACE) 185 devices = active_connection_props_iface.Get(isys.NM_ACTIVE_CONNECTION_IFACE, 'Devices') 186 187 for device_path in devices: 188 device = bus.get_object(isys.NM_SERVICE, device_path) 189 device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE) 190 191 interface_name = device_props_iface.Get(isys.NM_DEVICE_IFACE, 'Interface') 192 active_devs.add(interface_name) 193 194 ret = list(active_devs) 195 ret.sort() 196 return ret
197
198 -def logIfcfgFile(path, message=""):
199 content = "" 200 if os.access(path, os.R_OK): 201 f = open(path, 'r') 202 content = f.read() 203 f.close() 204 ifcfglog.debug("%s%s:\n%s" % (message, path, content))
205
206 -def logIfcfgFiles(message=""):
207 devprops = isys.getDeviceProperties(dev=None) 208 for device in devprops: 209 path = "%s/ifcfg-%s" % (netscriptsDir, device) 210 logIfcfgFile(path, message)
211
212 -class NetworkDevice(IfcfgFile):
213
214 - def __init__(self, dir, iface):
215 IfcfgFile.__init__(self, dir, iface) 216 self.description = "" 217 if iface.startswith('ctc'): 218 self.info["TYPE"] = "CTC" 219 self.wepkey = "" 220 self._dirty = False
221
222 - def clear(self):
223 IfcfgFile.clear(self) 224 if self.iface.startswith('ctc'): 225 self.info["TYPE"] = "CTC" 226 self.wepkey = ""
227
228 - def __str__(self):
229 s = "" 230 keys = self.info.keys() 231 if iutil.isS390() and ("HWADDR" in keys): 232 keys.remove("HWADDR") 233 # make sure we include autoneg in the ethtool line 234 if 'ETHTOOL_OPTS' in keys: 235 eopts = self.get('ETHTOOL_OPTS') 236 if "autoneg" not in eopts: 237 self.set(('ETHTOOL_OPTS', "autoneg off %s" % eopts)) 238 239 for key in keys: 240 if self.info[key] is not None: 241 s = s + key + '="' + self.info[key] + '"\n' 242 243 return s
244 245
246 - def loadIfcfgFile(self):
247 ifcfglog.debug("%s:\n%s" % (self.path, self.fileContent())) 248 ifcfglog.debug("NetworkDevice %s:\n%s" % (self.iface, self.__str__())) 249 ifcfglog.debug("loadIfcfgFile %s from %s" % (self.iface, self.path)) 250 251 self.clear() 252 IfcfgFile.read(self) 253 self._dirty = False 254 255 ifcfglog.debug("NetworkDevice %s:\n%s" % (self.iface, self.__str__()))
256
257 - def writeIfcfgFile(self):
258 # Write out the file only if there is a key whose 259 # value has been changed since last load of ifcfg file. 260 ifcfglog.debug("%s:\n%s" % (self.path, self.fileContent())) 261 ifcfglog.debug("NetworkDevice %s:\n%s" % (self.iface, self.__str__())) 262 ifcfglog.debug("writeIfcfgFile %s to %s%s" % (self.iface, self.path, 263 ("" if self._dirty else " not needed"))) 264 265 if self._dirty: 266 IfcfgFile.write(self) 267 self._dirty = False
268 269 # We can't read the file right now racing with ifcfg-rh update 270 #ifcfglog.debug("%s:\n%s" % (device.path, device.fileContent())) 271
272 - def set(self, *args):
273 # If we are changing value of a key set _dirty flag 274 # informing that ifcfg file needs to be synced. 275 s = " ".join(["%s=%s" % key_val for key_val in args]) 276 ifcfglog.debug("NetworkDevice %s set: %s" % 277 (self.iface, s)) 278 for (key, data) in args: 279 if self.get(key) != data: 280 break 281 else: 282 return 283 IfcfgFile.set(self, *args) 284 self._dirty = True
285 286 @property
287 - def keyfilePath(self):
288 return os.path.join(self.dir, "keys-%s" % self.iface)
289
290 - def writeWepkeyFile(self, dir=None, overwrite=True):
291 if not self.wepkey: 292 return False 293 if not dir: 294 keyfile = self.keyfilePath 295 else: 296 keyfile = os.path.join(dir, os.path.basename(self.keyfilePath)) 297 298 if not overwrite and os.path.isfile(keyfile): 299 return False 300 301 fd, newifcfg = tempfile.mkstemp(prefix="keys-%s" % self.iface, text=False) 302 os.write(fd, "KEY1=%s\n" % self.wepkey) 303 os.close(fd) 304 305 os.chmod(newifcfg, 0644) 306 try: 307 os.remove(keyfile) 308 except OSError as e: 309 if e.errno != 2: 310 raise 311 shutil.move(newifcfg, keyfile)
312
313 - def fileContent(self):
314 f = open(self.path, 'r') 315 content = f.read() 316 f.close() 317 return content
318
319 - def usedByFCoE(self, anaconda):
320 import storage 321 for d in anaconda.storage.devices: 322 if (isinstance(d, storage.devices.NetworkStorageDevice) and 323 d.nic == self.iface): 324 return True 325 return False
326
327 - def usedByRootOnISCSI(self, anaconda):
328 import storage 329 rootdev = anaconda.storage.rootDevice 330 for d in anaconda.storage.devices: 331 if (isinstance(d, storage.devices.NetworkStorageDevice) and 332 d.host_address and 333 rootdev.dependsOn(d)): 334 if self.iface == ifaceForHostIP(d.host_address): 335 return True 336 return False
337
338 - def usedByISCSI(self, anaconda):
339 import storage 340 for d in anaconda.storage.devices: 341 if (isinstance(d, storage.devices.NetworkStorageDevice) and 342 d.host_address): 343 if self.iface == ifaceForHostIP(d.host_address): 344 return True 345 return False
346
347 -class WirelessNetworkDevice(NetworkDevice):
348 349 """ 350 This class overwrites NetworkDevice's, IfcfgFile's and SimpleConfigFile's 351 methods to prevent working with per-device ifcfgfiles (which doesn't make 352 sense with wifi devices) 353 """ 354
355 - def __init__(self, iface):
356 self.info = dict() 357 self.iface = iface 358 self.dir = "" 359 self.description = ""
360
361 - def clear(self):
362 self.info = dict()
363 364 #method __str__ can be left untouched 365
366 - def loadIfcfgFile(self):
367 pass
368
369 - def writeIfcfgFile(self):
370 pass
371
372 - def set(self, *args):
373 msg = "".join(["%s=%s" % (key, val) for (key, val) in args]) 374 for (key, val) in args: 375 self.info[simpleconfig.uppercase_ASCII_string(key)] = val
376 377 #not used, remove?
378 - def fileContent(self):
379 return ""
380 381 #@property path can be left untouched (code using it skips nonexisting 382 #ifcfg files 383
384 - def read(self):
385 #same return value as IfcfgFile.read() 386 return len(self.info)
387
388 - def write(self):
389 pass
390
391 392 -class Network:
393
394 - def __init__(self):
395 396 self.hostname = socket.gethostname() 397 398 self.update() 399 400 # Set all devices to be controlled by NM by default. 401 # We can filter out storage devices only after 402 # we have device tree populated. So we do it before 403 # running nm-c-e and before writing ifcfg files to system. 404 self.setNMControlledDevices(self.netdevices.keys())
405
406 - def update(self):
407 ifcfglog.debug("Network.update() called") 408 409 self.netdevices = {} 410 self.ksdevice = None 411 412 if flags.imageInstall: 413 return 414 415 # populate self.netdevices 416 devhash = isys.getDeviceProperties(dev=None) 417 for iface in devhash.keys(): 418 if isys.isWirelessDevice(iface): 419 device = WirelessNetworkDevice(iface) 420 else: 421 device = NetworkDevice(netscriptsDir, iface) 422 if os.access(device.path, os.R_OK): 423 device.loadIfcfgFile() 424 else: 425 log.info("Network.update(): %s file not found" % 426 device.path) 427 continue 428 429 # TODORV - the last iface in loop wins, might be ok, 430 # not worthy of special juggling 431 if device.get('HOSTNAME'): 432 self.hostname = device.get('HOSTNAME') 433 434 device.description = isys.getNetDevDesc(iface) 435 436 self.netdevices[iface] = device 437 438 439 ksdevice = flags.cmdline.get('ksdevice', None) 440 if ksdevice: 441 bootif_mac = None 442 if ksdevice == 'bootif' and "BOOTIF" in flags.cmdline: 443 bootif_mac = flags.cmdline["BOOTIF"][3:].replace("-", ":").upper() 444 # sort for ksdevice=link (to select the same device as in loader)) 445 for dev in sorted(self.netdevices): 446 mac = self.netdevices[dev].get('HWADDR').upper() 447 if ksdevice == 'link' and isys.getLinkStatus(dev): 448 self.ksdevice = dev 449 break 450 elif ksdevice == 'bootif': 451 if bootif_mac == mac: 452 self.ksdevice = dev 453 break 454 elif ksdevice == dev: 455 self.ksdevice = dev 456 break 457 elif ':' in ksdevice: 458 if ksdevice.upper() == mac: 459 self.ksdevice = dev 460 break
461 462 463
464 - def getDevice(self, device):
465 return self.netdevices[device]
466
467 - def getKSDevice(self):
468 if self.ksdevice is None: 469 return None 470 471 try: 472 return self.netdevices[self.ksdevice] 473 except: 474 return None
475
476 - def setHostname(self, hn):
477 self.hostname = hn 478 if flags.imageInstall: 479 log.info("image install -- not setting hostname") 480 return 481 482 log.info("setting installation environment hostname to %s" % hn) 483 iutil.execWithRedirect("hostname", ["-v", hn ], 484 stdout="/dev/tty5", stderr="/dev/tty5")
485
486 - def unsetDNS(self, devname):
487 """Unset all DNS* ifcfg parameters.""" 488 i = 1 489 dev = self.netdevices[devname] 490 while True: 491 if dev.get("DNS%d" % i): 492 dev.unset("DNS%d" %i) 493 else: 494 break 495 i += 1
496
497 - def setDNS(self, ns, device):
498 dns = ns.split(',') 499 i = 1 500 for addr in dns: 501 addr = addr.strip() 502 dnslabel = "DNS%d" % (i,) 503 self.netdevices[device].set((dnslabel, addr)) 504 i += 1
505
506 - def setGateway(self, gw, device):
507 if ':' in gw: 508 self.netdevices[device].set(('IPV6_DEFAULTGW', gw)) 509 else: 510 self.netdevices[device].set(('GATEWAY', gw))
511 512 @property
513 - def gateway(self):
514 """GATEWAY - last device in list wins""" 515 for dev in reversed(self.netdevices.values()): 516 if (dev.get('GATEWAY') and 517 dev.get('DEFROUTE') != "no"): 518 return dev.get('GATEWAY') 519 return ""
520 521 @property
522 - def ipv6_defaultgw(self):
523 """IPV6_DEFAULTGW - last device in list wins""" 524 for dev in reversed(self.netdevices.values()): 525 if (dev.get('IPV6_DEFAULTGW') and 526 dev.get('DEFROUTE') != "no"): 527 return dev.get('IPV6_DEFAULTGW') 528 return ""
529
530 - def lookupHostname(self):
531 # can't look things up if they don't exist! 532 if not self.hostname or self.hostname == "localhost.localdomain": 533 return None 534 535 if not hasActiveNetDev(): 536 log.warning("no network devices were available to look up host name") 537 return None 538 539 try: 540 (family, socktype, proto, canonname, sockaddr) = \ 541 socket.getaddrinfo(self.hostname, None, socket.AF_INET)[0] 542 (ip, port) = sockaddr 543 except: 544 try: 545 (family, socktype, proto, canonname, sockaddr) = \ 546 socket.getaddrinfo(self.hostname, None, socket.AF_INET6)[0] 547 (ip, port, flowinfo, scopeid) = sockaddr 548 except: 549 return None 550 551 return ip
552 553 # Note that the file is written-out only if there is a value 554 # that has changed.
555 - def writeIfcfgFiles(self):
556 for device in self.netdevices.values(): 557 device.writeIfcfgFile()
558 559 # devices == None => set for all
560 - def setNMControlledDevices(self, devices=None):
561 for devname, device in self.netdevices.items(): 562 if devices and devname not in devices: 563 device.set(('NM_CONTROLLED', 'no')) 564 else: 565 device.set(('NM_CONTROLLED', 'yes'))
566 567 # devices == None => set for all
568 - def updateActiveDevices(self, devices=None):
569 for devname, device in self.netdevices.items(): 570 if devices and devname not in devices: 571 device.set(('ONBOOT', 'no')) 572 else: 573 device.set(('ONBOOT', 'yes'))
574
575 - def getOnbootControlledIfaces(self):
576 ifaces = [] 577 for iface, device in self.netdevices.items(): 578 if (device.get('ONBOOT') == "yes" and 579 device.get('NM_CONTROLLED') == "yes"): 580 ifaces.append(iface) 581 return ifaces
582
583 - def writeSSIDifcfgs(self, devssids):
584 ssids = [] 585 for ssidlist in devssids.values(): 586 ssids.extend(ssidlist) 587 for ssid in ssids: 588 path = "{0}/ifcfg-{1}".format(netscriptsDir, ssid) 589 ifcfgfile = open(path, "w") 590 ifcfgfile.write("NAME={0}\n".format(ssid)+ 591 "TYPE=Wireless\n"+ 592 "ESSID={0}\n".format(ssid)+ 593 "NM_CONTROLLED=yes\n") 594 ifcfgfile.close()
595 596
597 - def getSSIDs(self):
598 return getSSIDs()
599
600 - def writeKS(self, f):
601 devNames = self.netdevices.keys() 602 devNames.sort() 603 604 if len(devNames) == 0: 605 return 606 607 for devName in devNames: 608 dev = self.netdevices[devName] 609 610 line = "network" 611 612 # ipv4 and ipv6 613 if dev.get("ONBOOT"): 614 line += " --onboot %s" % dev.get("ONBOOT") 615 line += " --device %s" % dev.iface 616 if dev.get('MTU') and dev.get('MTU') != "0": 617 line += " --mtu=%s" % dev.get('MTU') 618 619 # ipv4 620 if not dev.get('BOOTPROTO'): 621 line += " --noipv4" 622 else: 623 if dev.get('BOOTPROTO').lower() == 'dhcp': 624 line += " --bootproto dhcp" 625 if dev.get('DHCPCLASS'): 626 line += " --dhcpclass %s" % dev.get('DHCPCLASS') 627 elif dev.get('IPADDR'): 628 line += " --bootproto static --ip %s" % dev.get('IPADDR') 629 netmask = dev.get('NETMASK') 630 prefix = dev.get('PREFIX') 631 if not netmask and prefix: 632 netmask = isys.prefix2netmask(int(prefix)) 633 if netmask: 634 line += " --netmask %s" % netmask 635 # note that --gateway is common for ipv4 and ipv6 636 if dev.get('GATEWAY'): 637 line += " --gateway %s" % dev.get('GATEWAY') 638 639 # ipv6 640 if (not dev.get('IPV6INIT') or 641 dev.get('IPV6INIT') == "no"): 642 line += " --noipv6" 643 else: 644 if dev.get('IPV6_AUTOCONF') == "yes": 645 line += " --ipv6 auto" 646 else: 647 if dev.get('IPV6ADDR'): 648 line += " --ipv6 %s" % dev.get('IPV6ADDR') 649 if dev.get('IPV6_DEFAULTGW'): 650 line += " --gateway %s" % dev.get('IPV6_DEFAULTGW') 651 if dev.get('DHCPV6') == "yes": 652 line += " --ipv6 dhcp" 653 654 # ipv4 and ipv6 655 dnsline = '' 656 for key in dev.info.keys(): 657 if key.upper().startswith('DNS'): 658 if dnsline == '': 659 dnsline = dev.get(key) 660 else: 661 dnsline += "," + dev.get(key) 662 if dnsline: 663 line += " --nameserver %s" % dnsline 664 665 if dev.get("ETHTOOL_OPTS"): 666 line += " --ethtool %s" % dev.get("ETHTOOL_OPTS") 667 668 if dev.get("ESSID"): 669 line += " --essid %s" % dev.get("ESSID") 670 671 # hostname 672 if dev.get("DHCP_HOSTNAME"): 673 line += " --hostname %s" % dev.get("DHCP_HOSTNAME") 674 elif dev.get("BOOTPROTO").lower != "dhcp": 675 if (self.hostname and 676 self.hostname != "localhost.localdomain"): 677 line += " --hostname %s" % self.hostname 678 679 line += "\n" 680 f.write(line)
681
682 - def hasNameServers(self, hash):
683 if hash.keys() == []: 684 return False 685 686 for key in hash.keys(): 687 if key.upper().startswith('DNS'): 688 return True 689 690 return False
691
692 - def hasWirelessDev(self):
693 for dev in self.netdevices: 694 if isys.isWirelessDevice(dev): 695 return True 696 return False
697
698 - def _copyFileToPath(self, file, instPath='', overwrite=False):
699 if not os.path.isfile(file): 700 return False 701 destfile = os.path.join(instPath, file.lstrip('/')) 702 if (os.path.isfile(destfile) and not overwrite): 703 return False 704 if not os.path.isdir(os.path.dirname(destfile)): 705 iutil.mkdirChain(os.path.dirname(destfile)) 706 shutil.copy(file, destfile) 707 return True
708
709 - def _copyIfcfgFiles(self):
710 files = os.listdir(netscriptsDir) 711 for cfgFile in files: 712 if cfgFile.startswith(("ifcfg-","keys-")): 713 srcfile = os.path.join(netscriptsDir, cfgFile) 714 self._copyFileToPath(srcfile, ROOT_PATH)
715
716 - def copyConfigToPath(self):
717 if flags.imageInstall: 718 # for image installs we only want to write out 719 # /etc/sysconfig/network 720 destfile = os.path.normpath(ROOT_PATH + networkConfFile) 721 if not os.path.isdir(os.path.dirname(destfile)): 722 iutil.mkdirChain(os.path.dirname(destfile)) 723 shutil.move("/tmp/sysconfig-network", destfile) 724 return 725 726 # /etc/sysconfig/network-scripts/ifcfg-* 727 # /etc/sysconfig/network-scripts/keys-* 728 # we can copy all of them 729 self._copyIfcfgFiles() 730 731 # /etc/dhcp/dhclient-DEVICE.conf 732 # TODORV: do we really don't want overwrite on live cd? 733 for devName, device in self.netdevices.items(): 734 dhclientfile = os.path.join("/etc/dhcp/dhclient-%s.conf" % devName) 735 self._copyFileToPath(dhclientfile, ROOT_PATH) 736 737 # /etc/sysconfig/network 738 self._copyFileToPath(networkConfFile, ROOT_PATH, 739 overwrite=flags.livecdInstall) 740 741 # /etc/resolv.conf 742 self._copyFileToPath("/etc/resolv.conf", ROOT_PATH, 743 overwrite=flags.livecdInstall) 744 745 # /etc/udev/rules.d/70-persistent-net.rules 746 self._copyFileToPath("/etc/udev/rules.d/70-persistent-net.rules", 747 ROOT_PATH, overwrite=flags.livecdInstall) 748 749 self._copyFileToPath(ipv6ConfFile, ROOT_PATH, 750 overwrite=flags.livecdInstall)
751
752 - def disableNMForStorageDevices(self, anaconda):
753 for devName, device in self.netdevices.items(): 754 if (device.usedByFCoE(anaconda) or 755 device.usedByRootOnISCSI(anaconda)): 756 dev = NetworkDevice(ROOT_PATH + netscriptsDir, devName) 757 if os.access(dev.path, os.R_OK): 758 dev.loadIfcfgFile() 759 dev.set(('NM_CONTROLLED', 'no')) 760 dev.writeIfcfgFile() 761 log.info("network device %s used by storage will not be " 762 "controlled by NM" % device.path) 763 else: 764 log.warning("disableNMForStorageDevices: %s file not found" % 765 device.path)
766
767 - def autostartFCoEDevices(self, anaconda):
768 for devName, device in self.netdevices.items(): 769 if device.usedByFCoE(anaconda): 770 dev = NetworkDevice(ROOT_PATH + netscriptsDir, devName) 771 if os.access(dev.path, os.R_OK): 772 dev.loadIfcfgFile() 773 dev.set(('ONBOOT', 'yes')) 774 dev.writeIfcfgFile() 775 log.debug("setting ONBOOT=yes for network device %s used by fcoe" 776 % device.path) 777 else: 778 log.warning("autoconnectFCoEDevices: %s file not found" % 779 device.path)
780
781 - def write(self):
782 ifcfglog.debug("Network.write() called") 783 784 # /etc/sysconfig/network 785 if flags.imageInstall: 786 # don't write files into host's /etc/sysconfig on image installs 787 newnetwork = "/tmp/sysconfig-network" 788 else: 789 newnetwork = "%s.new" % (networkConfFile) 790 791 f = open(newnetwork, "w") 792 f.write("NETWORKING=yes\n") 793 f.write("HOSTNAME=") 794 795 # use instclass hostname if set(kickstart) to override 796 if self.hostname: 797 f.write(self.hostname + "\n") 798 else: 799 f.write("localhost.localdomain\n") 800 801 if self.gateway: 802 f.write("GATEWAY=%s\n" % self.gateway) 803 804 if self.ipv6_defaultgw: 805 f.write("IPV6_DEFAULTGW=%s\n" % self.ipv6_defaultgw) 806 807 f.close() 808 if flags.imageInstall: 809 # for image installs, all we want to write out is the contents of 810 # /etc/sysconfig/network 811 ifcfglog.debug("not writing per-device configs for image install") 812 return 813 else: 814 shutil.move(newnetwork, networkConfFile) 815 816 devices = self.netdevices.values() 817 818 # /etc/sysconfig/network-scripts/ifcfg-* 819 # /etc/sysconfig/network-scripts/keys-* 820 for dev in devices: 821 822 dev.writeIfcfgFile() 823 824 # /etc/resolv.conf is managed by NM 825 826 # disable ipv6 827 if ('noipv6' in flags.cmdline 828 and not [dev for dev in devices 829 if dev.get('IPV6INIT') == "yes"]): 830 if os.path.exists(ipv6ConfFile): 831 log.warning('Not disabling ipv6, %s exists' % ipv6ConfFile) 832 else: 833 log.info('Disabling ipv6 on target system') 834 f = open(ipv6ConfFile, "w") 835 f.write("# Anaconda disabling ipv6\n") 836 f.write("options ipv6 disable=1\n") 837 f.close()
838
839 - def waitForDevicesActivation(self, devices):
840 waited_devs_props = {} 841 842 bus = dbus.SystemBus() 843 nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH) 844 device_paths = nm.get_dbus_method("GetDevices")() 845 for device_path in device_paths: 846 device = bus.get_object(isys.NM_SERVICE, device_path) 847 device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE) 848 iface = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface")) 849 if iface in devices: 850 waited_devs_props[iface] = device_props_iface 851 852 i = 0 853 while True: 854 for dev, device_props_iface in waited_devs_props.items(): 855 state = device_props_iface.Get(isys.NM_DEVICE_IFACE, "State") 856 if state == isys.NM_DEVICE_STATE_ACTIVATED: 857 waited_devs_props.pop(dev) 858 if len(waited_devs_props) == 0 or i >= CONNECTION_TIMEOUT: 859 break 860 i += 1 861 time.sleep(1) 862 863 return waited_devs_props.keys()
864 865 # write out current configuration state and wait for NetworkManager 866 # to bring the device up, watch NM state and return to the caller 867 # once we have a state
868 - def waitForConnection(self):
869 bus = dbus.SystemBus() 870 nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH) 871 props = dbus.Interface(nm, isys.DBUS_PROPS_IFACE) 872 873 i = 0 874 while i < CONNECTION_TIMEOUT: 875 state = props.Get(isys.NM_SERVICE, "State") 876 if nmIsConnected(state): 877 return True 878 i += 1 879 time.sleep(1) 880 881 state = props.Get(isys.NM_SERVICE, "State") 882 if nmIsConnected(state): 883 return True 884 885 return False
886 887 # write out current configuration state and wait for NetworkManager 888 # to bring the device up, watch NM state and return to the caller 889 # once we have a state
890 - def bringUp(self):
891 self.write() 892 if self.waitForConnection(): 893 resetResolver() 894 return True 895 else: 896 return False
897 898 # get a kernel cmdline string for dracut needed for access to host host
899 - def dracutSetupArgs(self, networkStorageDevice):
900 netargs=set() 901 902 if networkStorageDevice.nic: 903 # Storage bound to a specific nic (ie FCoE) 904 nic = networkStorageDevice.nic 905 else: 906 # Storage bound through ip, find out which interface leads to host 907 nic = ifaceForHostIP(networkStorageDevice.host_address) 908 if not nic: 909 return "" 910 911 if nic not in self.netdevices.keys(): 912 log.error('Unknown network interface: %s' % nic) 913 return "" 914 915 dev = self.netdevices[nic] 916 917 if dev.get('BOOTPROTO') == 'ibft': 918 netargs.add("ip=ibft") 919 elif networkStorageDevice.host_address: 920 if self.hostname: 921 hostname = self.hostname 922 else: 923 hostname = "" 924 925 # if using ipv6 926 if ':' in networkStorageDevice.host_address: 927 if dev.get('DHCPV6C') == "yes": 928 # XXX combination with autoconf not yet clear, 929 # support for dhcpv6 is not yet implemented in NM/ifcfg-rh 930 netargs.add("ip=%s:dhcp6" % nic) 931 elif dev.get('IPV6_AUTOCONF') == "yes": 932 netargs.add("ip=%s:auto6" % nic) 933 elif dev.get('IPV6ADDR'): 934 ipaddr = "[%s]" % dev.get('IPV6ADDR') 935 if dev.get('IPV6_DEFAULTGW'): 936 gateway = "[%s]" % dev.get('IPV6_DEFAULTGW') 937 else: 938 gateway = "" 939 netargs.add("ip=%s::%s:%s:%s:%s:none" % (ipaddr, gateway, 940 dev.get('PREFIX'), hostname, nic)) 941 else: 942 if dev.get('bootproto').lower() == 'dhcp': 943 netargs.add("ip=%s:dhcp" % nic) 944 else: 945 if dev.get('GATEWAY'): 946 gateway = dev.get('GATEWAY') 947 else: 948 gateway = "" 949 950 netmask = dev.get('netmask') 951 prefix = dev.get('prefix') 952 if not netmask and prefix: 953 netmask = isys.prefix2netmask(int(prefix)) 954 955 netargs.add("ip=%s::%s:%s:%s:%s:none" % (dev.get('ipaddr'), 956 gateway, netmask, hostname, nic)) 957 958 hwaddr = dev.get("HWADDR") 959 if hwaddr: 960 netargs.add("ifname=%s:%s" % (nic, hwaddr.lower())) 961 962 nettype = dev.get("NETTYPE") 963 subchannels = dev.get("SUBCHANNELS") 964 if iutil.isS390() and nettype and subchannels: 965 znet = "rd.znet=%s,%s" % (nettype, subchannels) 966 options = dev.get("OPTIONS").strip("'\"") 967 if options: 968 options = filter(lambda x: x != '', options.split(' ')) 969 znet += ",%s" % (','.join(options)) 970 netargs.add(znet) 971 972 return netargs
973
974 -def getSSIDs(devices_to_scan=None):
975 976 rv = {} 977 bus = dbus.SystemBus() 978 nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH) 979 device_paths = nm.get_dbus_method("GetDevices")() 980 981 for device_path in device_paths: 982 983 device = bus.get_object(isys.NM_SERVICE, device_path) 984 device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE) 985 # interface name, eg. "eth0", "wlan0" 986 dev = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface")) 987 988 if (isys.isWirelessDevice(dev) and 989 (not devices_to_scan or dev in devices_to_scan)): 990 991 i = 0 992 log.info("scanning APs for %s" % dev) 993 while i < 5: 994 ap_paths = device.GetAccessPoints(dbus_interface='org.freedesktop.NetworkManager.Device.Wireless') 995 if ap_paths: 996 break 997 time.sleep(0.5) 998 i += 0.5 999 1000 ssids = [] 1001 for ap_path in ap_paths: 1002 ap = bus.get_object(isys.NM_SERVICE, ap_path) 1003 ap_props = dbus.Interface(ap, isys.DBUS_PROPS_IFACE) 1004 ssid_bytearray = ap_props.Get(isys.NM_ACCESS_POINT_IFACE, "Ssid") 1005 ssid = "".join((str(b) for b in ssid_bytearray)) 1006 ssids.append(ssid) 1007 log.info("APs found for %s: %s" % (dev, str(ssids))) 1008 # XXX there can be duplicates in a list, but maybe 1009 # we want to keep them when/if we differentiate on something 1010 # more then just ssids; for now, remove them 1011 rv[dev]=list(set(ssids)) 1012 1013 return rv
1014
1015 -def ifaceForHostIP(host):
1016 route = iutil.execWithCapture("ip", [ "route", "get", "to", host ]) 1017 if not route: 1018 log.error("Could not get interface for route to %s" % host) 1019 return "" 1020 1021 routeInfo = route.split() 1022 if routeInfo[0] != host or len(routeInfo) < 5 or \ 1023 "dev" not in routeInfo or routeInfo.index("dev") > 3: 1024 log.error('Unexpected "ip route get to %s" reply: %s' % 1025 (host, routeInfo)) 1026 return "" 1027 1028 return routeInfo[routeInfo.index("dev") + 1]
1029
1030 -def resetResolver():
1031 isys.resetResolv() 1032 urlgrabber.grabber.reset_curl_obj()
1033