summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Woods <wwoods@redhat.com>2012-02-15 15:37:31 -0500
committerWill Woods <wwoods@redhat.com>2012-02-15 15:45:03 -0500
commit4e26256d931c41ed1469f456e4f05378d1f3a119 (patch)
tree3bbf85750a373fc94dbbcf2888651fcd465b332f
parent62a04d333268cbf117e8f1803b7f6e331961e688 (diff)
downloadanaconda-4e26256d931c41ed1469f456e4f05378d1f3a119.tar.gz
anaconda-4e26256d931c41ed1469f456e4f05378d1f3a119.tar.xz
anaconda-4e26256d931c41ed1469f456e4f05378d1f3a119.zip
Add anaconda dracut module [WIP!]
This adds the dracut directory and anaconda-dracut subpackage. The 'anaconda' dracut module replaces loader. It should handle all the tasks that loader used to handle in the first stage of the boot process. It's a work in progress, but it currently supports repo={http,ftp,nfs} and most anacaconda network options. Kickstart parsing is handled using a python interpreter and pykickstart, which (surprisingly) only adds ~600k to the initramfs. Driver disks are not yet supported.
-rw-r--r--Makefile.am2
-rw-r--r--anaconda.spec.in19
-rw-r--r--configure.ac1
-rw-r--r--dracut/Makefile.am35
-rwxr-xr-xdracut/anaconda-copy-ks.sh3
-rwxr-xr-xdracut/anaconda-hdroot22
-rwxr-xr-xdracut/anaconda-nfsroot24
-rwxr-xr-xdracut/fetch-kickstart44
-rwxr-xr-xdracut/module-setup.sh38
-rwxr-xr-xdracut/parse-anaconda-kickstart.sh63
-rwxr-xr-xdracut/parse-anaconda-options.sh94
-rwxr-xr-xdracut/parse-anaconda-repo.sh46
-rwxr-xr-xdracut/parse-kickstart192
-rwxr-xr-xdracut/pythondeps.sh32
-rwxr-xr-xdracut/repo-genrules.sh19
15 files changed, 633 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index b4a2d12f6..5f2113849 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = pyanaconda gptsync po data \
- tests utils scripts docs
+ tests utils scripts docs dracut
EXTRA_DIST = config.rpath COPYING \
anaconda.spec.in
diff --git a/anaconda.spec.in b/anaconda.spec.in
index b018a3aa3..03f6e1976 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -169,6 +169,21 @@ Obsoletes: booty
The anaconda package contains the program which was used to install your
system.
+%package dracut
+Summary: The anaconda dracut module
+Requires: dracut >= 16
+Requires: dracut-network
+Requires: xz
+Requires: pykickstart
+%ifarch %{ix86} x86_64
+Requires: dmidecode
+%endif
+
+%description dracut
+The 'anaconda' dracut module handles installer-specific boot tasks and
+options. This includes driver disks, kickstarts, and finding the anaconda
+runtime on NFS/HTTP/FTP servers or local disks.
+
%prep
%setup -q
@@ -233,6 +248,10 @@ update-desktop-database &> /dev/null || :
%{_datadir}/icons/hicolor/*
%endif
+%files dracut
+%dir %{_datadir}/dracut/modules.d/80%{name}
+%{_datadir}/dracut/modules.d/80%{name}/*
+
%changelog
* Thu Feb 09 2012 Brian C. Lane <bcl@redhat.com> - 18.0-1
- Set ONBOOT=yes for FCoE devices (#755147) (rvykydal)
diff --git a/configure.ac b/configure.ac
index 0a814507f..ef182a23b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -256,6 +256,7 @@ AC_CONFIG_FILES([Makefile
data/bootdisk/x86_64/Makefile
data/command-stubs/Makefile
docs/Makefile
+ dracut/Makefile
gptsync/Makefile
pyanaconda/installclasses/Makefile
pyanaconda/iw/Makefile
diff --git a/dracut/Makefile.am b/dracut/Makefile.am
new file mode 100644
index 000000000..152108de8
--- /dev/null
+++ b/dracut/Makefile.am
@@ -0,0 +1,35 @@
+# dracut/Makefile.am for anaconda
+#
+# Copyright (C) 2012 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Will Woods <wwoods@redhat.com>
+
+dracutdir = $(datadir)/dracut/modules.d/80$(PACKAGE_NAME)
+dist_dracut_DATA = module-setup.sh \
+ pythondeps.sh \
+ anaconda-lib.sh \
+ parse-anaconda-options.sh \
+ parse-anaconda-repo.sh \
+ parse-anaconda-kickstart.sh \
+ repo-genrules.sh \
+ anaconda-nfsroot \
+ anaconda-hdroot \
+ anaconda-copy-ks.sh \
+ fetch-kickstart \
+ parse-kickstart
+
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/dracut/anaconda-copy-ks.sh b/dracut/anaconda-copy-ks.sh
new file mode 100755
index 000000000..86c2724a0
--- /dev/null
+++ b/dracut/anaconda-copy-ks.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# Copy over kickstart files from the initrd to the sysroot before pivot
+cp /*cfg /*ks /sysroot/ 2> /dev/null
diff --git a/dracut/anaconda-hdroot b/dracut/anaconda-hdroot
new file mode 100755
index 000000000..e96ab583a
--- /dev/null
+++ b/dracut/anaconda-hdroot
@@ -0,0 +1,22 @@
+#!/bin/bash
+# hdroot script for anaconda
+
+. /lib/anaconda-lib.sh
+
+[ -f /tmp/root.info ] && . /tmp/root.info
+
+dev="$1"
+path="$2"
+mount "$dev" "$repodir" || die "Couldn't mount $root"
+img=$(find_runtime $repodir$path)
+if [ -z "$img" ]; then
+ iso=$(check_isodir $repodir$path)
+ if [ -n "$iso" ]; then
+ mount --move $repodir $isodir
+ iso=${isodir}${iso#$repodir}
+ mount -o loop,ro $iso $repodir
+ img=$(find_runtime $repodir)
+ fi
+fi
+[ -e "$img" ] && exec /sbin/dmsquash-live-root $img
+die "Couldn't find a suitable image or tree in $path on $dev
diff --git a/dracut/anaconda-nfsroot b/dracut/anaconda-nfsroot
new file mode 100755
index 000000000..68052d366
--- /dev/null
+++ b/dracut/anaconda-nfsroot
@@ -0,0 +1,24 @@
+#!/bin/bash
+# nfsroot script for anaconda
+
+. /lib/nfs-lib.sh
+. /lib/anaconda-lib.sh
+
+[ -f /tmp/root.info ] && . /tmp/root.info
+
+netif="$1"
+netroot="${2#anaconda-nfs:}"
+info "mounting installer repo $netroot"
+mount_nfs "$netroot" "$repodir" "$netif" || warn "Couldn't mount $netroot"
+img=$(find_runtime $repodir$path)
+if [ -z "$img" ]; then
+ iso=$(check_isodir $repodir$path)
+ if [ -n "$iso" ]; then
+ mount --move $repodir $isodir
+ iso=${isodir}${iso#$repodir}
+ mount -o loop,ro $iso $repodir
+ img=$(find_runtime $repodir)
+ fi
+fi
+[ -e "$img" ] && exec /sbin/dmsquash-live-root $img
+warn "Couldn't find a suitable image or tree in $netroot"
diff --git a/dracut/fetch-kickstart b/dracut/fetch-kickstart
new file mode 100755
index 000000000..8031f588b
--- /dev/null
+++ b/dracut/fetch-kickstart
@@ -0,0 +1,44 @@
+#!/bin/bash
+# fetch-kickstart - fetch kickstart file
+
+. /lib/url-lib.sh
+
+kickstart="$1"
+outfile="$2"
+ksdevice="$3"
+
+if [ "$kickstart" = "nfs:auto" ]; then
+ # construct kickstart URL from dhcp info
+ # server is next_server, or the dhcp server itself if missing
+ . /tmp/net.$ksdevice.dhcpopts
+ server="${new_dhcp_next_server:-$new_dhcp_server_identifier}"
+ # filename is dhcp 'filename' option, or '/kickstart/' if missing
+ filename="/kickstart/"
+ # read the dhcp lease file and see if we can find 'filename'
+ { while read line; do
+ val="${line#filename }"
+ if [ "$val" != "$line" ]; then
+ eval "filename=$val" # drop quoting and semicolon
+ fi
+ done
+ } < /tmp/net.$ksdevice.lease
+ # filename is appended with '$IP_ADDR-kickstart' if ending in '/'
+ if [ "${filename%/}" != "$filename" ]; then
+ filename="${filename}${new_ip_address}-kickstart"
+ fi
+ kickstart="nfs:$server:$filename"
+fi
+
+case "$kickstart" in
+ http:*|https:*|ftp:*|nfs:*) fetch_url "$kickstart" /tmp/ks.cfg ;;
+ bd:*) warn "FIXME: inst.ks=bd:.. is not yet supported." ;;
+ hd:*) warn "FIXME: inst.ks=hd:.. is not yet supported." ;;
+ file:*) cp "${kickstart#file:}" /tmp/ks.cfg ;;
+ *) warn "Don't know how to handle kickstart path '$kickstart'"; exit;;
+esac
+
+parse-kickstart /tmp/ks.cfg >> /etc/cmdline.d/80kickstart.conf
+# FIXME: do driverdisk if needed
+# FIXME: if there's updates to be fetched, add them to the list
+# FIXME: figure out which network devices to ifup
+# FIXME: if there's a repo, run the appropriate anaconda-*root or dmsquash
diff --git a/dracut/module-setup.sh b/dracut/module-setup.sh
new file mode 100755
index 000000000..6fdc54d55
--- /dev/null
+++ b/dracut/module-setup.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# module-setup.sh for anaconda
+
+check() {
+ [[ $hostonly ]] && return 1
+ return 255 # this module is optional
+}
+
+depends() {
+ echo livenet nfs img-lib
+ return 0
+}
+
+install() {
+ # anaconda
+ inst "$moddir/anaconda-lib.sh" "/lib/anaconda-lib.sh"
+ inst_hook cmdline 25 "$moddir/parse-anaconda-options.sh"
+ inst_hook cmdline 26 "$moddir/parse-anaconda-kickstart.sh"
+ inst_hook cmdline 27 "$moddir/parse-anaconda-repo.sh"
+ inst_hook pre-udev 40 "$moddir/repo-genrules.sh"
+ inst "$moddir/anaconda-nfsroot" "/sbin/anaconda-nfsroot"
+ inst "$moddir/anaconda-hdroot" "/sbin/anaconda-hdroot"
+ inst_hook pre-pivot 99 "$moddir/anaconda-copy-ks.sh"
+ # binaries we need sometimes
+ dracut_install -o dmidecode
+ # kickstart parsing, WOOOO
+ inst "$moddir/fetch-kickstart" "/sbin/fetch-kickstart"
+ inst "$moddir/parse-kickstart" "/sbin/parse-kickstart"
+ # python deps for parse-kickstart. DOUBLE WOOOO
+ $moddir/pythondeps.sh $moddir/parse-kickstart | while read dep; do
+ case "$dep" in
+ *.so) inst_library $dep ;;
+ *.py) inst_simple $dep ;;
+ *) inst $dep ;;
+ esac
+ done
+}
+
diff --git a/dracut/parse-anaconda-kickstart.sh b/dracut/parse-anaconda-kickstart.sh
new file mode 100755
index 000000000..916f49c80
--- /dev/null
+++ b/dracut/parse-anaconda-kickstart.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# parse-kickstart-options.sh: check to see if we need to get a kickstart
+
+warn_renamed_arg "ks" "inst.ks"
+
+kickstart="$(getarg ks= inst.ks=)"
+if [ -z "$kickstart" ]; then
+ getargbool 0 ks inst.ks && kickstart='nfs:auto'
+fi
+
+ksdev="$(getarg ksdevice= inst.ks.dev= inst.ks.device=)"
+
+warn_renamed_arg "kssendmac" "inst.ks.sendmac"
+if getargbool 0 kssendmac inst.ks.sendmac; then
+ ifnum=0
+ for ifname in /sys/class/net/*; do
+ mac=$(cat $ifname/address)
+ ifname=${ifname#/sys/class/net/}
+ # TODO: might need to choose devices better
+ if [ "$ifname" != "lo" ] && [ -n "$mac" ]; then
+ set_http_header "X-RHN-Provisioning-MAC-$ifnum" "$ifname $mac"
+ ifnum=$(($ifnum+1))
+ fi
+ done
+fi
+
+warn_renamed_arg "kssendsn" "inst.ks.sendsn"
+if getargbool 0 kssendsn inst.ks.sendsn; then
+ if ! command -v dmidecode; then
+ warn "inst.ks.sendsn: can't find serial number (dmidecode missing)"
+ else
+ system_serial=$(dmidecode -s system-serial-number)
+ set_http_header "X-System-Serial-Number" "$system_serial"
+ fi
+fi
+
+splitsep ":" "$kickstart" kstype ksdev ksfile
+case "$kstype" in
+ file|path)
+ # It's already here! Parse away!
+ if [ "$kstype" = "path" ]; then
+ warn "inst.ks='$kickstart'"
+ warn "'path:...' is deprecated; please use 'file:...' instead"
+ fi
+ ksfile=ksdev
+ if [ -f "$ksfile" ]; then
+ /sbin/parse-kickstart $ksfile >> /etc/cmdline.d/80kickstart.conf
+ else
+ warn "inst.ks='$kickstart': can't find $ksfile!"
+ fi
+ ;;
+ cdrom|hd)
+ # FIXME: mount and parse-kickstart once dev appears
+ ;;
+ http|https|ftp|nfs|nfs4)
+ [ -z "$netroot" ] && netroot="skip"
+ # FIXME: schedule fetch-kickstart when network dev comes up
+ ;;
+ bd) warn "can't get kickstart: biospart isn't supported yet." ;;
+esac
+
+# no root? the kickstart will probably tell us what our root device is. Onward!
+[ "$kickstart" ] && [ -z "$root" ] && root="kickstart" && rootok=1
diff --git a/dracut/parse-anaconda-options.sh b/dracut/parse-anaconda-options.sh
new file mode 100755
index 000000000..2d9c424d7
--- /dev/null
+++ b/dracut/parse-anaconda-options.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# parse-anaconda-options.sh - parse installer-specific options
+
+. /lib/anaconda-lib.sh
+. /lib/url-lib.sh
+
+# THIS! IS! ANACONDA!!!
+udevproperty ANACONDA=1
+# (used in udev rules to keep stuff like mdadm, multipath, etc. out of our way)
+
+# create the repodir and isodir that anaconda will look for
+mkdir -p $repodir $isodir
+
+# get some info from .buildstamp
+if [ ! -f /.buildstamp ]; then
+ warn ".buildstamp missing"
+else
+ product=$(config_get Main Product < /.buildstamp)
+ version=$(config_get Main Version < /.buildstamp)
+ # TODO: this is silly. There should be an "Arch" item in there..
+ uuid=$(config_get Main UUID < /.buildstamp)
+ strstr "$uuid" "." && arch=${uuid##*.}
+fi
+[ -z "$arch" ] && arch=$(uname -m)
+
+# set HTTP headers so server(s) will recognize us
+set_http_header "X-Anaconda-Architecture" "$arch"
+set_http_header "X-Anaconda-System-Release" "$product"
+
+# convenience function to warn the user about old argument names.
+warn_renamed_arg() {
+ local arg=""
+ arg="$(getarg $1)" && warn "'$1=$arg'" && warn "$1 has been renamed to $2"
+}
+
+# check for deprecated arg, warn user, and write new arg to /etc/cmdline
+check_depr_arg() {
+ local arg="" quiet="" newval=""
+ if [ "$1" == "--quiet" ]; then quiet=1; shift; fi
+ arg="$(getarg $1)"
+ [ "$arg" ] || return 1
+ newval=$(printf "$2" "$arg")
+ [ "$quiet" ] || warn "'$1' is deprecated. Using '$newval' instead."
+ echo "$newval" >> /etc/cmdline.d/75anaconda-options.conf
+}
+check_depr_args() {
+ local q=""
+ for i in $(getargs $1); do check_depr_arg $q "$i" "$2" && q="--quiet"; done
+}
+
+check_depr_arg "serial" "console=ttyS0"
+check_depr_arg "stage2=" "root=live:%s"
+check_depr_args "blacklist=" "inst.blacklist=%s"
+check_depr_arg "nofirewire" "inst.blacklist=firewire_ohci"
+
+# USB is built-in and can't be disabled anymore. DEAL WITH IT.
+getarg nousb && warn "'nousb' is deprecated. USB drivers can't be disabled."
+getarg ethtool && warn "'ethtool' is deprecated and has been removed."
+
+# interactive junk in initramfs
+# (maybe we'll bring it back someday?)
+getarg askmethod && warn "'askmethod' is deprecated and has been removed." && \
+ warn "Use an appropriate 'inst.repo=' argument instead."
+getarg asknetwork && warn "'asknetwork' is deprecated and has been removed." &&\
+ warn "Use an appropriate 'ip=' argument instead."
+
+check_depr_arg "lang=" "locale.LANG=%s"
+check_depr_arg "keymap=" "vconsole.keymap=%s"
+
+# FIXME: if we have ksdevice or multiple ip lines, we'll need interface names
+check_depr_arg "dns" "nameserver=%s"
+check_depr_arg "ipv6=auto" "ip=auto6"
+check_depr_arg "ipv6=dhcp" "ip=dhcp6"
+check_depr_arg "ipv6=" "ip=[%s]" # XXX is this right?
+
+check_depr_ip_args() {
+ local ip="$(getarg ip=)"
+ [ -z "$ip" ] && return # no ip? no problem
+ [ "$ip" = "dhcp" ] && return # this is fine as-is
+ strstr "$ip" ":" && return # PXE/dracut style. this is also fine.
+
+ local nm="$(getarg netmask=)" gw="$(getarg gateway=)" fail=""
+ [ -z "$gw" ] && warn "ip=<ip> missing gateway=<gw>!" && fail="yes"
+ [ -z "$nm" ] && warn "ip=<ip> missing netmask=<nm>!" && fail="yes"
+ [ "$fail" ] && return
+ warn "'ip=<ip> gateway=<gw> netmask=<nm>' is deprecated."
+ warn "Use 'ip=<ip>::<gw>:<nm>' instead."
+ strstr "$gw" ":" && gw="[$gw]" # ipv6 addr (XXX: did anaconda allow this?)
+ echo "ip=$ip::$gw:$nm" >> /etc/cmdline.d/75anaconda-options.conf
+}
+check_depr_ip_args
+
+# re-read the commandline args
+unset CMDLINE
diff --git a/dracut/parse-anaconda-repo.sh b/dracut/parse-anaconda-repo.sh
new file mode 100755
index 000000000..0155dbfe3
--- /dev/null
+++ b/dracut/parse-anaconda-repo.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# parse-repo-options.sh: parse the repo= arg (and set root=)
+
+check_depr_arg "method=" "inst.repo=%s"
+warn_renamed_arg "repo" "inst.repo"
+unset CMDLINE
+
+repo="$(getarg repo= inst.repo=)"
+
+disk_to_dev_path() {
+ case "$1" in
+ CDLABEL=*|LABEL=*) echo "/dev/disk/by-label/${1#*LABEL=}" ;;
+ UUID=*) echo "/dev/disk/by-uuid/${1#UUID=}" ;;
+ /dev/*) echo "$1" ;;
+ *) echo "/dev/$1" ;;
+ esac
+}
+
+case "$repo" in
+ "") ;; # no repo, no action needed
+ cdrom:*)
+ root="live:${repo#cdrom:}" ;;
+ http:*|https:*|ftp:*)
+ treeinfo=$(fetch_url $repo/.treeinfo) && \
+ stage2=$(config_get stage2 mainimage < $treeinfo)
+ root="live:$repo/${stage2:-images/install.img}" ;;
+ nfs:*|nfsiso:*)
+ root="anaconda-nfs" # root must be set
+ repo=nfs:${repo#nfs*:}
+ netroot="anaconda-nfs:$repo"
+ wait_for_dev /dev/root ;;
+ hd:*)
+ splitsep ":" "$repo" f dev path
+ root="anaconda.hdiso:$(resolve_disk $dev):$path" ;;
+ *)
+ warn "Invalid value for 'inst.repo': $repo"
+ [ -z "$root" ] && warn "No root= arg either! Will look for media.." ;;
+esac
+
+if [ -z "$root" ]; then
+ # FIXME: script to watch for valid installer media
+ root=live:/dev/sr0
+fi
+
+# okay we've got some kind of root thingy to deal with. onward!
+rootok=1
diff --git a/dracut/parse-kickstart b/dracut/parse-kickstart
new file mode 100755
index 000000000..af2229769
--- /dev/null
+++ b/dracut/parse-kickstart
@@ -0,0 +1,192 @@
+#!/usr/bin/python
+#vim: set fileencoding=utf8
+# parse-kickstart - read a kickstart file and emit equivalent dracut boot args.
+#
+# Copyright © 2012 Red Hat, Inc.
+# BLAH BLAH GPL BLAH.
+#
+# Designed to run inside the dracut initramfs environment.
+# Requires python 2.7 or later.
+#
+# Authors:
+# Will Woods <wwoods@redhat.com>
+
+import sys, os
+import logging
+from pykickstart.parser import KickstartParser, preprocessKickstart
+from pykickstart.version import returnClassForVersion
+from pykickstart.errors import KickstartParseError
+from pykickstart.constants import *
+from pykickstart import commands
+from collections import OrderedDict
+
+# Default logging: none
+log = logging.getLogger('parse-kickstart').addHandler(logging.NullHandler())
+
+# Here are the kickstart commands we care about:
+
+class Method(commands.method.F14_Method):
+ '''install methods: cdrom, harddrive, nfs, url'''
+ def dracut_args(self, args, lineno, obj):
+ if self.method == "cdrom":
+ method="/dev/sr0"
+ elif self.method == "harddrive":
+ if self.biospart:
+ dev = biospart_to_dev(self.biospart, args, lineno)
+ if dev:
+ method="hd:%s:%s" % (dev, self.dir)
+ method="hd:%s:%s" % (self.partition, self.dir)
+ elif self.method == "nfs":
+ method="nfs:%s:%s" % (self.server, self.dir)
+ if self.opts:
+ method += ":%s" % opts
+ elif self.method == "url":
+ # FIXME: self.proxy, self.noverifyssl
+ method = self.url
+ return "inst.repo=%s" % method
+
+class Updates(commands.updates.F7_Updates):
+ def dracut_args(self, args, lineno, obj):
+ if self.url == "floppy":
+ return "inst.updates=/dev/fd0"
+ elif self.url:
+ return "inst.updates=%s" % self.url
+
+class MediaCheck(commands.mediacheck.FC4_MediaCheck):
+ def dracut_args(self, args, lineno, obj):
+ if self.mediacheck:
+ return "rd.live.check"
+
+class DriverDisk(commands.driverdisk.F14_DriverDisk):
+ def dracut_args(self, args, lineno, obj):
+ dd = self.driverdiskList[-1]
+ if dd.biospart:
+ location = biospart_to_dev(dd.biospart, args, lineno)
+ else:
+ location = dd.partition or dd.source
+ if location:
+ return "inst.driverdisk=%s" % location
+
+class Network(commands.network.F16_Network):
+ def dracut_args(self, args, lineno, net):
+ if len(self.network) == 1: # first network line gets special treatment
+ net.activate = True # activate by default
+ if not net.device: # --device is optional, defaults to..
+ net.device = "ksdev" # whatever the kickstart device was
+ if not net.device:
+ log.error("'%s': missing --device", " ".join(args))
+ elif net.activate: # we only care about activated devices
+ return ksnet_to_dracut(args, lineno, net)
+
+# TODO: keymap, lang... device? upgrade?
+
+dracutCmds = {
+ 'cdrom': Method,
+ 'harddrive': Method,
+ 'nfs': Method,
+ 'url': Method,
+ 'updates': Updates,
+ 'mediacheck': MediaCheck,
+ 'driverdisk': DriverDisk,
+ 'network': Network,
+}
+handlerclass = returnClassForVersion()
+class DracutHandler(handlerclass):
+ def __init__(self):
+ handlerclass.__init__(self, commandUpdates=dracutCmds)
+ self.output = []
+ def dispatcher(self, args, lineno):
+ obj = handlerclass.dispatcher(self, args, lineno)
+ # and execute any specified dracut_args
+ cmd = args[0]
+ command = self.commands[cmd]
+ if hasattr(command, "dracut_args"):
+ log.debug("kickstart line %u: handling %s", lineno, cmd)
+ line = " ".join(args)
+ self.output.append(command.dracut_args(args, lineno, obj))
+ return obj
+
+# set up logging
+class KmsgFormatter(logging.Formatter):
+ '''Formats log output for /dev/kmsg like dracut does.'''
+ def format(self, record):
+ if record.levelno <= logging.INFO: tag = "<30>"
+ elif record.levelno <= logging.WARNING: tag = "<28>"
+ else: tag = "<24>"
+ return tag + logging.Formatter.format(self, record)
+def init_logger():
+ logfmt = "%(name)s %(levelname)s: %(message)s"
+ stderr = logging.StreamHandler()
+ stderr.setFormatter(logging.Formatter(logfmt))
+ logger = logging.getLogger('parse-kickstart')
+ logger.setLevel(logging.WARNING)
+ logger.addHandler(stderr)
+ try:
+ kmsg = logging.FileHandler("/dev/kmsg", "w")
+ kmsg.setFormatter(KmsgFormatter(logfmt))
+ logger.addHandler(kmsg)
+ except IOError:
+ pass
+ return logger
+
+def biospart_to_dev(biospart, args, lineno):
+ if not os.path.isdir("/sys/firmware/edd"):
+ log.error("'%s': --biospart unavailable (no EDD support)", " ".join(args))
+ return
+ log.error("'%s': biospart is not yet supported", " ".join(args), lineno)
+
+def ksnet_to_dracut(args, lineno, net):
+ '''Translate the kickstart network data into dracut network data.'''
+ line = []
+ dev = net.device
+ if net.bootProto == BOOTPROTO_DHCP:
+ line.append("ip=%s:dhcp" % dev if dev else "ip=dhcp")
+ elif net.bootProto == BOOTPROTO_IBFT:
+ line.append("ip=%s:ibft" % dev if dev else "ip=ibft")
+ elif net.bootProto == BOOTPROTO_BOOTP: # NOTE: no dracut support yet...
+ line.append("ip=%s:bootp" % dev if dev else "ip=bootp")
+ elif net.bootProto == BOOTPROTO_QUERY:
+ log.error("'%s': --bootproto=query is deprecated", " ".join(args))
+ elif net.bootProto == BOOTPROTO_STATIC:
+ req = ("gateway", "netmask", "nameserver", "ip")
+ missing = ", ".join("--%s" % i for i in req if not hasattr(net, i))
+ if missing:
+ log.warn("line %u: network missing %s", lineno, missing)
+ else:
+ line.append("ip={0.ip}::{0.gateway}:{0.netmask}:" \
+ "{0.hostname}:{0.device}".format(net))
+ for ns in net.nameserver.split(","):
+ line.append("nameserver=%s" % ns)
+ if net.ipv6 == "auto":
+ line.append("ip=%s:auto6" % dev if dev else "ip=auto6")
+ elif net.ipv6 == "dhcp":
+ line.append("ip=%s:dhcp6" % dev if dev else "ip=dhcp6")
+ elif net.ipv6:
+ line.append("ip=[{0.ipv6}]::{0.gateway}:{0.netmask}:" \
+ "{0.hostname}:{0.device}".format(net))
+ if net.mtu:
+ # XXX NOTE: dracut doesn't support mtu= (yet) so this arg might change
+ mtuarg = "mtu=%s:" % dev if dev else "mtu="
+ line.append(mtustr+str(mtu))
+ # TODO FIXME: nodns, nodefroute, noipv4, noipv6, dhcpclass, ethtool
+ if net.essid or net.wepkey or net.wpakey:
+ # TODO: make dracut support wireless? (do we care?)
+ log.error("'%s': dracut doesn't support wireless networks", " ".join(args))
+ return " ".join(line)
+
+def process_kickstart(ksfile):
+ handler = DracutHandler()
+ parser = KickstartParser(handler)
+ processed_file = preprocessKickstart(ksfile)
+ try:
+ parser.readKickstart(processed_file)
+ except KickstartParseError as e:
+ log.error(str(e))
+ return handler.output
+
+if __name__ == '__main__':
+ log = init_logger()
+ for path in sys.argv[1:]:
+ output = process_kickstart(path)
+ for line in filter(None, output):
+ print line
diff --git a/dracut/pythondeps.sh b/dracut/pythondeps.sh
new file mode 100755
index 000000000..2f7b06fc2
--- /dev/null
+++ b/dracut/pythondeps.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+python="python"
+
+eval $($python << _EOT_
+from distutils.sysconfig import *
+print 'makefile=' + get_makefile_filename()
+print 'config_h=' + get_config_h_filename()
+print 'sitedir=' + get_python_lib()
+_EOT_
+)
+libdir=${makefile%/config/Makefile}
+
+pydeps() {
+ echo $makefile
+ echo $config_h
+ while [ $# -gt 0 ]; do
+ $python -v $1 2>&1 | sed -ne 's/^import.* from //p'
+ shift
+ done
+}
+
+# basedir /path/top/module/sub/filename.py /path/top -> /path/top/module
+basedir() { mod=${1#$2/}; mod=${mod%%/*}; echo $2/$mod; }
+
+pydeps "$@" | sed 's/\.py[coO]$/.py/' | sort -u | while read dep; do
+ case "$dep" in
+ $sitedir/*/*.py) find "$(basedir $dep $sitedir)" -type f ;;
+ $libdir/*/*.py) find "$(basedir $dep $libdir)" -type f ;;
+ *) echo $dep ;;
+ esac
+done | grep -v '\.py[coO]' | sort -u
diff --git a/dracut/repo-genrules.sh b/dracut/repo-genrules.sh
new file mode 100755
index 000000000..50fe3f988
--- /dev/null
+++ b/dracut/repo-genrules.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+when_dev_appears() {
+ local dev="${1#/dev/}"; shift
+ {
+ printf 'KERNEL=="%s", ' "$dev"
+ printf 'RUN="/sbin/initqueue --settled --onetime --unique %s"\n' "$*"
+ printf 'SYMLINK=="%s", ' "$dev"
+ printf 'RUN="/sbin/initqueue --settled --onetime --unique %s"\n' "$*"
+ } >> /etc/udev/rules.d/99-anaconda.rules
+ wait_for_dev "$dev"
+}
+
+splitsep ":" "$root" repotype dev path
+
+if [ "$repotype" = "anaconda.hdiso" ]; then
+ when_dev_appears "$dev" "/sbin/anaconda-hdroot $dev $path"
+ wait_for_mount $repodir
+fi