[Fedora-livecd-list] Net Boot
Mohammed_Khan at Dell.com
Mohammed_Khan at Dell.com
Thu Jun 7 21:52:43 UTC 2007
Ok, I am pasting them here...
These were hacked from the Fedora Release 7 Gold version of
livecd-tools, I would love to work off of the versions in git but I
can't get http:// to work to get to the git repo... Is http enabled for
the fedora git repos? (git:// will not work from my network b/c the port
is blocked going out).
To build livecd iso w/ net capability:
--------------------------------------
1. Backup and replace livecd-creator and mayflower on Fedora 7 with
versions pasted below...
2. Run: livecd-creator --enable-netroot --config=somefile.ks ...
The --enable-netroot option:
1. enables a netroot option for the kernel commandline that is consumed
by initramfs
2. adds some nic drivers and nfs modules to initramfs
2. adds busybox and some symlinks from it to initramfs (needed for net
operations)
4. adds a supporting file and some supporting dirs for busybox udhcp
NOTE: in your ks config file, you must specify following package, else
intramfs will not be able to perform network operations:
a. busybox
And the following packages are nice to have for use in real root:
a. nfs-utils
b. dhclient
c. net-tools
To netboot:
-----------
1. add netroot on the kernel commandline
2. you must also set following kernel commandline options:
rootfstype=nfs
rootflags=nolock
root=mynfsserverip:/location/of/squashfs.img
NOTE: this will enable initramfs to mount squashfs over nfs, so an nfs
server must be exporting squashfs.img at root specified location.
NOTE: the squashfs.img file on the nfs server must be exported (and
chmodded) as rw unless you also use the live_ram option.
If you use pxelinux for your pxe needs, below is an exmaple of a
pxelinux config file assuming you placed livecd contents in
/tftpboot/livecd (and nfs exported /tftpboot/livecd):
label boot
kernel livecd/isolinux/vmlinuz
initrd livecd/isolinux/initrd.img
append netroot rootfstype=nfs rootflags=nolock
root=192.168.0.1:/tftpboot/livecd
NOTE: You can also pass live_ram if you want to copy the squashfs.img
into ram so that you do not have to remain mounted over nfs.
That's it...
Limitations:
------------
1. Only supports dhcp for getting an ip in initramfs, no code to handle
static ip allocation is present, so you must have a dhcp server on your
network (this is a requirement for pxe-booting anyways... So not sure if
static ip capability is needed?)
Questions/Thoughts:
----------
1. Is there any interest in actually patching this capability in? or is
livecd intended purely for cd /usb...
2. I thought the kernel can be compiled with nfsroot capability? I tried
this w/ the stock initramfs and one hacked w/ network moduels but I
think standard kernels on fedora yum repos do no have this enabled b/c I
get a /dev/nfs is unknown error, using a kernel w/ nfsroot enabled may
be another avenue to explore for netbooting...
Thanks,
MFK
-------------------------
livecd-creator:
===========================================
#!/usr/bin/python -tt
#
# livecd-creator : Creates Live CD based for Fedora.
#
# 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; version 2 of the License.
#
# 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 Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
import getopt
import os
import os.path
import sys
import errno
import string
import tempfile
import time
import traceback
import subprocess
import shutil
import yum
import pykickstart.parser
import pykickstart.version
class MountError(Exception):
def __init__(self, msg):
Exception.__init__(self, msg)
class InstallationError(Exception):
def __init__(self, msg):
Exception.__init__(self, msg)
class BindChrootMount:
"""Represents a bind mount of a directory into a chroot."""
def __init__(self, src, chroot, dest = None):
self.src = src
self.root = chroot
if not dest:
dest = src
self.dest = self.root + "/" + dest
self.mounted = False
def mount(self):
if not self.mounted:
if not os.path.exists(self.dest):
os.makedirs(self.dest)
rc = subprocess.call(["/bin/mount", "--bind", self.src,
self.dest])
if rc != 0:
raise MountError("Bind-mounting '%s' to '%s' failed" %
(self.src, self.dest))
self.mounted = True
def umount(self):
if self.mounted:
rc = subprocess.call(["/bin/umount", self.dest])
self.mounted = False
class LoopbackMount:
def __init__(self, lofile, mountdir, fstype = None):
self.lofile = lofile
self.mountdir = mountdir
self.fstype = fstype
self.mounted = False
self.losetup = False
self.rmdir = False
self.loopdev = None
def cleanup(self):
self.umount()
self.lounsetup()
def umount(self):
if self.mounted:
rc = subprocess.call(["/bin/umount", self.mountdir])
self.mounted = False
if self.rmdir:
try:
os.rmdir(self.mountdir)
except OSError, e:
pass
self.rmdir = False
def lounsetup(self):
if self.losetup:
rc = subprocess.call(["/sbin/losetup", "-d", self.loopdev])
self.losetup = False
self.loopdev = None
def loopsetup(self):
if self.losetup:
return
rc = subprocess.call(["/sbin/losetup", "-f", self.lofile])
if rc != 0:
raise MountError("Failed to allocate loop device for '%s'" %
self.lofile)
# succeeded; figure out which loopdevice we're using
buf = subprocess.Popen(["/sbin/losetup", "-a"],
stdout=subprocess.PIPE).communicate()[0]
for line in buf.split("\n"):
# loopdev: fdinfo (filename)
fields = line.split()
if len(fields) != 3:
continue
if fields[2] == "(%s)" %(self.lofile,):
self.loopdev = fields[0][:-1]
break
if not self.loopdev:
raise MountError("Failed to find loop device associated with
'%s' from '/sbin/losetup -a'" % self.lofile)
self.losetup = True
def mount(self):
if self.mounted:
return
self.loopsetup()
if not os.path.isdir(self.mountdir):
os.makedirs(self.mountdir)
self.rmdir = True
args = [ "/bin/mount", self.loopdev, self.mountdir ]
if self.fstype:
args.extend(["-t", self.fstype])
rc = subprocess.call(args)
if rc != 0:
raise MountError("Failed to mount '%s' to '%s'" %
(self.loopdev, self.mountdir))
self.mounted = True
class SparseExt3LoopbackMount(LoopbackMount):
def __init__(self, lofile, mountdir, size, fslabel):
LoopbackMount.__init__(self, lofile, mountdir, fstype = "ext3")
self.size = size
self.fslabel = fslabel
def _createSparseFile(self):
dir = os.path.dirname(self.lofile)
if not os.path.isdir(dir):
os.makedirs(dir)
# create the sparse file
fd = os.open(self.lofile, os.O_WRONLY | os.O_CREAT)
off = long(self.size * 1024L * 1024L)
os.lseek(fd, off, 0)
os.write(fd, '\x00')
os.close(fd)
def _formatFilesystem(self):
rc = subprocess.call(["/sbin/mkfs.ext3", "-F", "-L",
self.fslabel,
"-m", "1", self.lofile])
if rc != 0:
raise MountError("Error creating ext3 filesystem")
rc = subprocess.call(["/sbin/tune2fs", "-c0", "-i0",
"-Odir_index",
"-ouser_xattr,acl", self.lofile])
def mount(self):
self._createSparseFile()
self._formatFilesystem()
return LoopbackMount.mount(self)
class LiveCDYum(yum.YumBase):
def __init__(self):
yum.YumBase.__init__(self)
def doFileLogSetup(self, uid, logfile):
# don't do the file log for the livecd as it can lead to open
fds
# being left and an inability to clean up after ourself
pass
def _writeConf(self, datadir, installroot):
conf = "[main]\n"
conf += "installroot=%s\n" % installroot
conf += "cachedir=/var/cache/yum\n"
conf += "plugins=0\n"
conf += "reposdir=\n"
path = datadir + "/yum.conf"
f = file(path, "w+")
f.write(conf)
f.close()
os.chmod(path, 0644)
return path
def setup(self, datadir, installroot):
self.doConfigSetup(fn = self._writeConf(datadir, installroot),
root = installroot)
self.conf.cache = 0
self.doTsSetup()
self.doRpmDBSetup()
self.doRepoSetup()
self.doSackSetup()
def selectPackage(self, pkg):
"""Select a given package. Can be specified with name.arch or
name*"""
try:
self.install(pattern = pkg)
except yum.Errors.InstallError, e:
raise InstallationError("Failed to find package '%s' : %s" %
(pkg, e))
def deselectPackage(self, pkg):
"""Deselect package. Can be specified as name.arch or name*"""
sp = pkg.rsplit(".", 2)
txmbrs = []
if len(sp) == 2:
txmbrs = self.tsInfo.matchNaevr(name=sp[0], arch=sp[1])
if len(txmbrs) == 0:
exact, match, unmatch =
yum.packages.parsePackages(self.pkgSack.returnPackages(), [pkg],
casematch=1)
for p in exact + match:
txmbrs.append(p)
if len(txmbrs) > 0:
map(lambda x: self.tsInfo.remove(x.pkgtup), txmbrs)
else:
print >> sys.stderr, "No such package %s to remove" %(pkg,)
def selectGroup(self, grp, include =
pykickstart.parser.GROUP_DEFAULT):
try:
yum.YumBase.selectGroup(self, grp)
except (yum.Errors.InstallError, yum.Errors.GroupsError), e:
raise InstallationError("Failed to find group '%s' : %s" %
(grp, e))
if include == pykickstart.parser.GROUP_REQUIRED:
map(lambda p: self.deselectPackage(p),
grp.default_packages.keys())
elif include == pykickstart.parser.GROUP_ALL:
map(lambda p: self.selectPackage(p),
grp.optional_packages.keys())
def addRepository(self, name, url = None, mirrorlist = None):
repo = yum.yumRepo.YumRepository(name)
if url:
repo.baseurl.append(url)
if mirrorlist:
repo.mirrorlist = mirrorlist
conf = yum.config.RepoConf()
for k, v in conf.iteritems():
if v or not hasattr(repo, k):
repo.setAttribute(k, v)
repo.basecachedir = self.conf.cachedir
repo.metadata_expire = 0
# disable gpg check???
repo.gpgcheck = 0
repo.enable()
repo.setup(0)
self.repos.add(repo)
def runInstall(self):
(res, resmsg) = self.buildTransaction()
if res != 2:
raise InstallationError("Failed to build transaction : %s" %
str.join("\n", resmsg))
dlpkgs = map(lambda x: x.po, filter(lambda txmbr: txmbr.ts_state
in ("i", "u"), self.tsInfo.getMembers()))
self.downloadPkgs(dlpkgs)
# FIXME: sigcheck?
self.initActionTs()
self.populateTs(keepold=0)
self.ts.check()
self.ts.order()
# FIXME: callback should be refactored a little in yum
sys.path.append('/usr/share/yum-cli')
import callback
cb = callback.RPMInstallCallback()
cb.tsInfo = self.tsInfo
cb.filelog = False
return self.runTransaction(cb)
class InstallationTarget:
def __init__(self, repos, packages, epackages, groups, fs_label,
skip_compression, skip_prelink):
self.ayum = None
self.repos = repos
self.packages = packages
self.epackages = epackages
self.groups = groups
self.fs_label = fs_label
self.skip_compression = skip_compression
self.skip_prelink = skip_prelink
self.build_dir = None
self.instloop = None
self.bindmounts = []
self.ksparser = None
def parse(self, kscfg):
ksversion = pykickstart.version.makeVersion()
self.ksparser = pykickstart.parser.KickstartParser(ksversion)
if kscfg:
try:
self.ksparser.readKickstart(kscfg)
except IOError, (err, msg):
raise InstallationError("Failed to read kickstart file
'%s' : %s" % (kscfg, msg))
except pykickstart.errors.KickstartError, e:
raise InstallationError("Failed to parse kickstart file
'%s' : %s" % (kscfg, e))
for repo in self.ksparser.handler.repo.repoList:
already_given = False
for cmd_name, cmd_url in self.repos:
if cmd_name == repo.name:
already_given = True
break
if not already_given:
self.repos.append( (repo.name, repo.baseurl) )
self.packages.extend(self.ksparser.handler.packages.packageList)
self.groups.extend(map(lambda g: (g.name, g.include),
self.ksparser.handler.packages.groupList))
self.epackages.extend(self.ksparser.handler.packages.excludedList)
if not self.packages and not self.groups:
raise InstallationError("No packages or groups specified")
if not self.repos:
raise InstallationError("No repositories specified")
def base_on_iso(self, base_on):
"""helper function to extract ext3 file system from a live CD
ISO"""
isoloop = LoopbackMount(base_on, "%s/base_on_iso"
%(self.build_dir,))
squashloop = LoopbackMount("%s/squashfs.img"
%(isoloop.mountdir,),
"%s/base_on_squashfs"
%(self.build_dir,),
"squashfs")
try:
try:
isoloop.mount()
except MountError, e:
raise InstallationError("Failed to loopback mount '%s' :
%s" % (base_on, e))
if not os.path.exists(squashloop.lofile):
raise InstallationError("'%s' is not a valid live CD ISO
: squashfs.img doesn't exist" % base_on)
try:
squashloop.mount()
except MountError, e:
raise InstallationError("Failed to loopback mount
squashfs.img from '%s' : %s" % (base_on, e))
os_image = self.build_dir + "/base_on_squashfs/os.img"
if not os.path.exists(os_image):
raise InstallationError("'%s' is not a valid live CD ISO
: os.img doesn't exist" % base_on)
shutil.copyfile(os_image, self.build_dir + "/data/os.img")
finally:
# unmount and tear down the mount points and loop devices
used
squashloop.cleanup()
isoloop.cleanup()
def write_fstab(self):
fstab = open(self.build_dir + "/install_root/etc/fstab", "w")
fstab.write("/dev/mapper/livecd-rw /
ext3 defaults,noatime 0 0\n")
fstab.write("devpts /dev/pts
devpts gid=5,mode=620 0 0\n")
fstab.write("tmpfs /dev/shm
tmpfs defaults 0 0\n")
fstab.write("proc /proc
proc defaults 0 0\n")
fstab.write("sysfs /sys
sysfs defaults 0 0\n")
fstab.close()
def setup(self, image_size, base_on = None):
"""setup target ext3 file system in preparation for an
install"""
# setup temporary build dirs
try:
self.build_dir = tempfile.mkdtemp(dir="/var/tmp",
prefix="livecd-creator-")
except OSError, (err, msg):
raise InstallationError("Failed create build directory in
/var/tmp: %s" % msg)
os.makedirs(self.build_dir + "/out/isolinux")
os.makedirs(self.build_dir + "/out/sysroot")
os.makedirs(self.build_dir + "/data/sysroot")
os.makedirs(self.build_dir + "/install_root")
os.makedirs(self.build_dir + "/yum-cache")
if base_on:
# get backing ext3 image if we're based this build on an
existing live CD ISO
self.base_on_iso(base_on)
self.instloop = LoopbackMount("%s/data/os.img"
%(self.build_dir,),
"%s/install_root"
%(self.build_dir,))
else:
self.instloop = SparseExt3LoopbackMount("%s/data/os.img"
%(self.build_dir,),
"%s/install_root"
%(self.build_dir,),
image_size,
self.fs_label)
try:
self.instloop.mount()
except MountError, e:
raise InstallationError("Failed to loopback mount '%s' : %s"
% (self.instloop.lofile, e))
if not base_on:
# create a few directories needed if it's a new image
os.makedirs(self.build_dir + "/install_root/etc")
os.makedirs(self.build_dir + "/install_root/boot")
os.makedirs(self.build_dir + "/install_root/var/log")
os.makedirs(self.build_dir + "/install_root/var/cache/yum")
# bind mount system directories into install_root/
for (f, dest) in [("/sys", None), ("/proc", None), ("/dev",
None),
("/dev/pts", None), ("/selinux", None),
(self.build_dir + "/yum-cache",
"/var/cache/yum")]:
self.bindmounts.append(BindChrootMount(f, self.build_dir +
"/install_root", dest))
for b in self.bindmounts:
b.mount()
# make sure /etc/mtab is current inside install_root
os.symlink("../proc/mounts", self.build_dir +
"/install_root/etc/mtab")
self.write_fstab()
self.ayum = LiveCDYum()
self.ayum.setup(self.build_dir + "/data",
self.build_dir + "/install_root")
def unmount(self):
"""detaches system bind mounts and install_root for the file
system and tears down loop devices used"""
self.ayum = None
# FIXME: Make one last ditch effort to close fds still open
# in the install root; this is only needed because
# there's no way to ask yum to close its sqlite dbs,
# though. See https://bugzilla.redhat.com/236409
for i in range(3, os.sysconf("SC_OPEN_MAX")):
try:
os.close(i)
except:
pass
try:
os.unlink(self.build_dir + "/install_root/etc/mtab")
except OSError:
pass
self.bindmounts.reverse()
for b in self.bindmounts:
b.umount()
if self.instloop:
self.instloop.cleanup()
self.instloop = None
def teardown(self):
if self.build_dir:
self.unmount()
shutil.rmtree(self.build_dir, ignore_errors = True)
def addRepository(self, name, url):
"""adds a yum repository to temporary yum.conf file used"""
self.ayum.addRepository(name, url)
def run_in_root(self):
os.chroot("%s/install_root" %(self.build_dir,))
os.chdir("/")
def installPackages(self, packageList, excludePackageList, groupList
= []):
"""install packages into target file system"""
try:
map(lambda pkg: self.ayum.selectPackage(pkg), packageList)
map(lambda grp: self.ayum.selectGroup(grp[0], grp[1]),
groupList)
map(lambda pkg: self.ayum.deselectPackage(pkg),
excludePackageList)
self.ayum.runInstall()
finally:
self.ayum.closeRpmDB()
def writeNetworkIfCfg(self, instroot, network):
path = instroot + "/etc/sysconfig/network-scripts/ifcfg-" +
network.device
f = file(path, "w+")
os.chmod(path, 0644)
f.write("DEVICE=%s\n" % network.device)
f.write("BOOTPROTO=%s\n" % network.bootProto)
if network.bootProto.lower() == "static":
if network.ip:
f.write("IPADDR=%s\n" % network.ip)
if network.netmask:
f.write("NETMASK=%s\n" % network.netmask)
if network.onboot:
f.write("ONBOOT=on\n")
else:
f.write("ONBOOT=off\n")
if network.essid:
f.write("ESSID=%s\n" % network.essid)
if network.ethtool:
if network.ethtool.find("autoneg") == -1:
network.ethtool = "autoneg off " + network.ethtool
f.write("ETHTOOL_OPTS=%s\n" % network.ethtool)
if network.bootProto.lower() == "dhcp":
if network.hostname:
f.write("DHCP_HOSTNAME=%s\n" % network.hostname)
if network.dhcpclass:
f.write("DHCP_CLASSID=%s\n" % network.dhcpclass)
if network.mtu:
f.write("MTU=%s\n" % network.mtu)
f.close()
def writeNetworkKey(self, instroot, network):
if not network.wepkey:
return
path = instroot + "/etc/sysconfig/network-scripts/keys-" +
network.device
f = file(path, "w+")
os.chmod(path, 0600)
f.write("KEY=%s\n" % network.wepkey)
f.close()
def writeNetworkConfig(self, instroot, useipv6, hostname, gateway):
path = instroot + "/etc/sysconfig/network"
f = file(path, "w+")
os.chmod(path, 0644)
f.write("NETWORKING=yes\n")
if useipv6:
f.write("NETWORKING_IPV6=yes\n")
else:
f.write("NETWORKING_IPV6=no\n")
if hostname:
f.write("HOSTNAME=%s\n" % hostname)
else:
f.write("HOSTNAME=localhost.localdomain\n")
if gateway:
f.write("GATEWAY=%s\n" % gateway)
f.close()
def writeNetworkHosts(self, instroot, hostname):
localline = ""
if hostname and hostname != "localhost.localdomain":
localline += hostname + " "
l = string.split(hostname, ".")
if len(l) > 1:
localline += l[0] + " "
localline += "localhost.localdomain localhost"
path = instroot + "/etc/hosts"
f = file(path, "w+")
os.chmod(path, 0644)
f.write("127.0.0.1\t\t%s\n" % localline)
f.write("::1\t\tlocalhost6.localdomain6 localhost6\n")
f.close()
def writeNetworkResolv(self, instroot, nodns, primaryns,
secondaryns):
if nodns or not primaryns:
return
path = instroot + "/etc/resolv.conf"
f = file(path, "w+")
os.chmod(path, 0644)
for ns in (primaryns, secondaryns):
if ns:
f.write("nameserver %s\n" % ns)
f.close()
def configureNetwork(self):
instroot = self.build_dir + "/install_root"
try:
os.makedirs(instroot + "/etc/sysconfig/network-scripts")
except OSError, (err, msg):
if err != errno.EEXIST:
raise
useipv6 = False
nodns = False
hostname = None
gateway = None
primaryns = None
secondaryns = None
for network in self.ksparser.handler.network.network:
if not network.device:
raise InstallationError("No --device specified with
network kickstart command")
if network.onboot and network.bootProto.lower() != "dhcp"
and \
not (network.ip and network.netmask):
raise InstallationError("No IP address and/or netmask
specified with static " +
"configuration for '%s'" %
network.device)
self.writeNetworkIfCfg(instroot, network)
self.writeNetworkKey(instroot, network)
if network.ipv6:
useipv6 = True
if network.nodns:
nodns = True
if network.hostname:
hostname = network.hostname
if network.gateway:
gateway = network.gateway
if network.nameserver:
nameservers = string.split(network.nameserver, ",")
if len(nameservers) >= 1:
primaryns = nameservers[0]
if len(nameservers) >= 2:
secondayns = nameservers[0]
self.writeNetworkConfig(instroot, useipv6, hostname, gateway)
self.writeNetworkHosts(instroot, hostname)
self.writeNetworkResolv(instroot, nodns, primaryns, secondaryns)
def configureSystem(self):
instroot = "%s/install_root" %(self.build_dir,)
# FIXME: this is a bit ugly, but with the current pykickstart
# API, we don't really have a lot of choice. it'd be nice to
# be able to do something different, but so it goes
# set up the language
lang = self.ksparser.handler.lang.lang or "en_US.UTF-8"
f = open("%s/etc/sysconfig/i18n" %(instroot,), "w+")
f.write("LANG=\"%s\"\n" %(lang,))
f.close()
# next, the keyboard
# FIXME: should this impact the X keyboard config too???
# or do we want to make X be able to do this mapping
import rhpl.keyboard
k = rhpl.keyboard.Keyboard()
if self.ksparser.handler.keyboard.keyboard:
k.set(self.ksparser.handler.keyboard.keyboard)
k.write(instroot)
# next up is timezone
tz = self.ksparser.handler.timezone.timezone or
"America/New_York"
utc = self.ksparser.handler.timezone.isUtc
f = open("%s/etc/sysconfig/clock" %(instroot,), "w+")
f.write("ZONE=\"%s\"\n" %(tz,))
f.write("UTC=%s\n" %(utc,))
f.close()
# do any authconfig bits
auth = self.ksparser.handler.authconfig.authconfig or
"--useshadow --enablemd5"
if os.path.exists("%s/usr/sbin/authconfig" %(instroot,)):
args = ["/usr/sbin/authconfig", "--update", "--nostart"]
args.extend(auth.split())
subprocess.call(args, preexec_fn=self.run_in_root)
# firewall. FIXME: should handle the rest of the options
if self.ksparser.handler.firewall.enabled and
os.path.exists("%s/usr/sbin/lokkit" %(instroot,)):
subprocess.call(["/usr/sbin/lokkit", "-f", "--quiet",
"--nostart", "--enabled"],
preexec_fn=self.run_in_root)
# selinux
if os.path.exists("%s/usr/sbin/lokkit" %(instroot,)):
args = ["/usr/sbin/lokkit", "-f", "--quiet", "--nostart"]
if self.ksparser.handler.selinux.selinux:
args.append("--selinux=enforcing")
else:
args.append("--selinux=disabled")
subprocess.call(args, preexec_fn=self.run_in_root)
# Set the root password
if self.ksparser.handler.rootpw.isCrypted:
subprocess.call(["/usr/sbin/usermod", "-p",
self.ksparser.handler.rootpw.password, "root"],
preexec_fn=self.run_in_root)
elif self.ksparser.handler.rootpw.password == "":
# Root password is not set and not crypted, empty it
subprocess.call(["/usr/bin/passwd", "-d", "root"],
preexec_fn=self.run_in_root)
else:
# Root password is set and not crypted
p1 = subprocess.Popen(["/bin/echo",
self.ksparser.handler.rootpw.password], stdout=subprocess.PIPE,
preexec_fn=self.run_in_root)
p2 = subprocess.Popen(["/usr/bin/passwd", "--stdin",
"root"], stdin=p1.stdout, stdout=subprocess.PIPE,
preexec_fn=self.run_in_root)
output = p2.communicate()[0]
# enable/disable services appropriately
if os.path.exists("%s/sbin/chkconfig" %(instroot,)):
for s in self.ksparser.handler.services.enabled:
subprocess.call(["/sbin/chkconfig", s, "--level", "345",
"on"],
preexec_fn=self.run_in_root)
for s in self.ksparser.handler.services.disabled:
subprocess.call(["/sbin/chkconfig", s, "--level", "345",
"off"],
preexec_fn=self.run_in_root)
# x by default?
if self.ksparser.handler.xconfig.startX:
f = open("%s/etc/inittab" %(instroot,), "rw+")
buf = f.read()
buf = buf.replace("id:3:initdefault", "id:5:initdefault")
f.seek(0)
f.write(buf)
f.close()
# and now, for arbitrary %post scripts
for s in filter(lambda s: s.type ==
pykickstart.parser.KS_SCRIPT_POST,
self.ksparser.handler.scripts):
# we can only safely run scripts in the chroot
if not s.inChroot:
print >> sys.stderr, "Not running script outside of
chroot"
continue
(fd, path) = tempfile.mkstemp("", "ks-script-", "%s/tmp"
%(instroot,))
os.write(fd, s.script)
os.close(fd)
os.chmod(path, 0700)
try:
subprocess.call([s.interp, "/tmp/%s"
%(os.path.basename(path),)],
preexec_fn = self.run_in_root)
except OSError, (err, msg):
os.unlink(path)
raise InstallationError("Failed to execute %%post script
with '%s' : %s" % (s.interp, msg))
os.unlink(path)
def get_kernel_version(self):
#
# FIXME: this doesn't handle multiple kernels - we should list
# them all in the isolinux menu
#
kernels = []
modules_dir = "%s/install_root/lib/modules" % self.build_dir
if os.path.isdir(modules_dir):
kernels = os.listdir(modules_dir)
if not kernels:
raise InstallationError("No kernels installed: /lib/modules
is empty")
return kernels[0]
def createInitramfs(self, enable_netroot):
# Create initramfs
if not os.path.isfile("/usr/lib/livecd-creator/mayflower"):
raise InstallationError("livecd-creator not correctly
installed : "+
"/usr/lib/livecd-creator/mayflower
not found")
shutil.copy("/usr/lib/livecd-creator/mayflower",
"%s/install_root/sbin/mayflower"
%(self.build_dir,))
# modules needed for booting (this is butt ugly and we need to
retrieve this from elsewhere, e.g. the kernel)
mayflowerconf = open(self.build_dir +
"/install_root/etc/mayflower.conf", "w")
mayflowerconf.write('MODULES+="cdrom ide-cd ahci loop
dm_snapshot squashfs ext3 ext2 ehci_hcd uhci_hcd ohci_hcd usb_storage
sd_mod sr_mod usbhid ata_piix vfat msdos "\n')
if enable_netroot:
mayflowerconf.write('MODULES+="3c59x 8139cp 8139too 8390
acenic amd8111e b44 de600 de620 dl2k e100 e1000 forcedeth ixgb ne2k-pci
pcnet32 r8169 tg3 sunrpc nfs nfs_acl lockd "\n')
mayflowerconf.write('MODULES+="sata_mv sata_qstor sata_sis
sata_uli "\n')
mayflowerconf.write('MODULES+="sata_nv sata_sil24 sata_svw
sata_via "\n')
mayflowerconf.write('MODULES+="sata_promise sata_sil sata_sx4
sata_vsc "\n')
mayflowerconf.write('MODULES+="ata_generic pata_ali pata_amd
pata_artop pata_atiixp pata_cmd64x pata_cs5520 pata_cs5530 pata_cs5535
pata_cypress pata_efar pata_hpt366 pata_hpt37x pata_hpt3x2n pata_hpt3x3
pata_isapnp pata_it821x pata_jmicron pata_marvell pata_mpiix
pata_netcell pata_ns87410 pata_oldpiix pata_optidma pata_opti
pata_pcmcia pata_pdc2027x pata_pdc202xx_old pata_qdi pata_serverworks
pata_sil680 pata_sis pata_sl82c105 pata_triflex pata_via pdc_adma "\n')
mayflowerconf.write('MODULES+="sym53c8xx aic7xxx "\n')
mayflowerconf.close()
if enable_netroot:
subprocess.call(["/sbin/mayflower", "--enable-netroot",
"-f",
"/boot/livecd-initramfs.img",
self.get_kernel_version()],
preexec_fn=self.run_in_root)
else:
subprocess.call(["/sbin/mayflower", "-f",
"/boot/livecd-initramfs.img",
self.get_kernel_version()],
preexec_fn=self.run_in_root)
for f in ("/sbin/mayflower", "/etc/mayflower.conf"):
os.unlink("%s/install_root/%s" %(self.build_dir, f))
def relabelSystem(self):
# finally relabel all files
if self.ksparser.handler.selinux.selinux:
instroot = "%s/install_root" %(self.build_dir,)
if os.path.exists("%s/sbin/restorecon" %(instroot,)):
subprocess.call(["/sbin/restorecon", "-v", "-r", "/"],
preexec_fn=self.run_in_root)
def prelinkSystem(self):
# prelink the system
instroot = "%s/install_root" %(self.build_dir,)
if os.path.exists("%s/usr/sbin/prelink" %(instroot,)):
subprocess.call(["/usr/sbin/prelink", "-mRaN"],
preexec_fn=self.run_in_root)
return True
def launchShell(self):
subprocess.call(["/bin/bash"], preexec_fn=self.run_in_root)
def configureBootloader(self):
"""configure the boot loader"""
# set up boot loader
#
# TODO:
# - fix for archs not using grub
# - fix for non-i386
# - error handling
#
shutil.copyfile("%s/install_root/boot/vmlinuz-%s"
%(self.build_dir, self.get_kernel_version()),
"%s/out/isolinux/vmlinuz" %(self.build_dir,))
shutil.copyfile("%s/install_root/boot/livecd-initramfs.img"
%(self.build_dir,),
"%s/out/isolinux/initrd.img" %(self.build_dir,))
os.unlink("%s/install_root/boot/livecd-initramfs.img"
%(self.build_dir,))
for p in ["isolinux.bin", "vesamenu.c32"]:
path = "%s/install_root/usr/lib/syslinux/%s" %
(self.build_dir, p)
if not os.path.isfile(path):
raise InstallationError("syslinux not installed : %s not
found" % path)
shutil.copy(path, "%s/out/isolinux/%s" % (self.build_dir,
p))
if
os.path.exists("%s/install_root/usr/lib/anaconda-runtime/syslinux-vesa-s
plash.jpg" %(self.build_dir,)):
shutil.copy("%s/install_root/usr/lib/anaconda-runtime/syslinux-vesa-spla
sh.jpg" %(self.build_dir,),
"%s/out/isolinux/splash.jpg" %(self.build_dir,))
have_background = "menu background splash.jpg"
else:
have_background = ""
cfg = """
default vesamenu.c32
timeout 600
%(background)s
menu title Welcome to %(label)s!
menu color border 0 #ffffffff #00000000
menu color sel 7 #ffffffff #ff000000
menu color title 0 #ffffffff #00000000
menu color tabmsg 0 #ffffffff #00000000
menu color unsel 0 #ffffffff #00000000
menu color hotsel 0 #ff000000 #ffffffff
menu color hotkey 7 #ffffffff #ff000000
""" %{"label": self.fs_label, "background" : have_background}
stanzas = [("linux", "Run from image", ""),
("runfromram", "Run from RAM - requires 1 GB+",
"live_ram")]
if
os.path.exists("%s/install_root/usr/lib/anaconda-runtime/checkisomd5"
%(self.build_dir,)):
stanzas.append( ("check", "Verify and run from image",
"check") )
for (short, long, extra) in stanzas:
cfg += """label %(short)s
menu label %(long)s
kernel vmlinuz
append initrd=initrd.img ro quiet root=CDLABEL=%(label)s
rootfstype=iso9660 liveimg %(extra)s
""" %{"label": self.fs_label, "background" : have_background,
"short": short, "long": long, "extra": extra}
cfgf = open("%s/out/isolinux/isolinux.cfg" %(self.build_dir,),
"w")
cfgf.write(cfg)
cfgf.close()
# TODO: enable external entitity to partipate in adding boot
entries
def install(self, enable_netroot):
for (name, url) in self.repos:
self.ayum.addRepository(name, url)
self.installPackages(self.packages, self.epackages, self.groups)
self.configureSystem()
self.configureNetwork()
self.relabelSystem()
if not self.skip_prelink:
self.prelinkSystem()
self.createInitramfs(enable_netroot)
self.configureBootloader()
def createIso(self):
"""write out the live CD ISO"""
subprocess.call(["/usr/bin/mkisofs", "-o", "%s.iso"
%(self.fs_label,),
"-b", "isolinux/isolinux.bin",
"-c", "isolinux/boot.cat",
"-no-emul-boot", "-boot-load-size", "4",
"-boot-info-table", "-J", "-r",
"-hide-rr-moved",
"-V", "%s" %(self.fs_label,), "%s/out"
%(self.build_dir)])
# implant an isomd5sum
if os.path.exists("/usr/lib/anaconda-runtime/implantisomd5"):
subprocess.call(["/usr/lib/anaconda-runtime/implantisomd5",
"%s.iso" %(self.fs_label,)])
else:
print >> sys.stderr, "anaconda-runtime not installed; not
setting up mediacheck"
def createSquashFS(self):
"""create compressed squashfs file system"""
if not self.skip_compression:
# FIXME: mksquashfs segfaults if PWD isn't set in the
environment
subprocess.call(["/sbin/mksquashfs", "os.img", "sysroot",
"../out/squashfs.img"],
cwd="%s/data" %(self.build_dir,),
env={"PWD": "%s/data" %(self.build_dir,)})
else:
shutil.move("%s/data/os.img" %(self.build_dir,),
"%s/out/ext3fs.img" %(self.build_dir,))
def package(self):
self.createSquashFS()
self.createIso()
def usage(out):
print >> out, """
usage: livecd-creator [--help]
[--config=<path-to-kickstart-file> |
--repo=<name>,<url> --package=<p>]
[--repo=<name1>,<url1>] [--repo=<name2>,<url2>
...]
[--package=<p1>] [--package=<p2> ...]
[--exclude-package=<e1>] [--exclude-package=<e2>
...]
[--base-on=<path-to-iso-file>]
[--fslabel=<label>]
[--skip-compression]
[--uncompressed-size=<size-in-MB>]
[--shell]
[--enable-netroot]
--help : Print usage and exit
--config : Path to kickstart config file
--repo : Add / override yum repository
--package : Include this package
--exclude-package : Exclude this package
--base-on : Add packages to an existing live CD iso9660 image
--fslabel : File system label (default: livecd-YYYYMMDD-HHMI)
--skip-compression : Don't compress the image
--prelink : Prelink the image
--uncompressed-size : Size of uncompressed fs in MB (default: 4096)
--shell : Start a shell in the chroot for
post-configuration
--enable-netroot : Enable net root (root can be mounted over net for
eg over nfs)
Examples:
Create minimal live cd:
# livecd-creator
--config=/usr/share/livecd-tools/livecd-fedora-minimal.ks
Create minimal live cd and use local package repositories:
# livecd-creator
--config=/usr/share/livecd-tools/livecd-fedora-minimal.ks \\
--repo=a-dev,file:///home/user/core/RPMS
\\
--repo=a-extras-dev,file:///home/user/extras/RPMS
"""
class Usage(Exception):
def __init__(self, msg = None, no_error = False):
Exception.__init__(self, msg, no_error)
class Options:
def __init__(self):
self.repos = []
self.packages = []
self.groups = []
self.epackages = []
self.fs_label = "livecd-" + time.strftime("%Y%m%d-%H%M")
self.base_on = None
self.kscfg = None
self.skip_compression = False
self.skip_prelink = True
self.uncompressed_size = 4096
self.give_shell = False
self.enable_netroot = False
def parse_options(args):
try:
opts, args = getopt.getopt(args, "hr:b:p:e:f:c:su:l",
["help", "repo=", "base-on=",
"package=",
"exclude-package=", "fslabel=",
"config=",
"skip-compression",
"uncompressed-size=",
"shell", "enable-netroot",
"no-prelink", "prelink"])
except getopt.GetoptError, msg:
raise Usage(msg)
options = Options()
for o, a in opts:
if o in ("-h", "--help"):
raise Usage(no_error = True)
if o in ("-l", "--shell"):
options.give_shell = True
continue
if o in ("--enable-netroot"):
options.enable_netroot = True
continue
if o in ("-s", "--skip-compression"):
options.skip_compression = True
continue
if o in ("--no-prelink",):
options.skip_prelink = True
continue
if o in ("--prelink",):
options.skip_prelink = False
continue
if o in ("-u", "--uncompressed-size"):
options.uncompressed_size = int(a)
continue
if o in ("-c", "--config"):
options.kscfg = a
if not os.path.isfile(options.kscfg):
raise Usage("Kickstart config '%s' does not exist" %
options.kscfg)
continue
if o in ("-r", "--repo"):
(name, url) = a.split(",")
for (n, u) in options.repos:
if n == name:
raise Usage("Repo name '%s' is already in use" % n)
options.repos.append((name, url))
continue
if o in ("-p", "--package"):
if a.startswith("@"):
options.groups.append((a[1:],
pykickstart.parser.GROUP_DEFAULT))
else:
options.packages.append(a)
continue
if o in ("-e", "--exclude-package"):
options.epackages.append(a)
continue
if o in ("-f", "--fslabel"):
options.fs_label = a
if len(options.fs_label) > 32:
raise Usage("CD labels are limited to 32 characters")
continue
if o in ("-b", "--base-on"):
options.base_on = a
if not os.path.isfile(options.base_on):
raise Usage("Live CD ISO '%s' does not exist" %
options.base_on)
continue
raise Usage("Unknown option %s" % o)
if not options.kscfg and not (options.packages or options.groups):
raise Usage("No packages or groups specified")
if not options.kscfg and not options.repos:
raise Usage("No repositories specified")
return options
def main():
try:
options = parse_options(sys.argv[1:])
except Usage, (msg, no_error):
if no_error:
out = sys.stdout
ret = 0
else:
out = sys.stderr
ret = 2
if msg:
print >> out, msg
usage(out)
return ret
if os.geteuid () != 0:
print >> sys.stderr, "You must run livecd-creator as root"
return 1
target = InstallationTarget(options.repos,
options.packages,
options.epackages,
options.groups,
options.fs_label,
options.skip_compression,
options.skip_prelink)
try:
target.parse(options.kscfg)
target.setup(options.uncompressed_size, options.base_on)
target.install(options.enable_netroot)
if options.give_shell:
print "Launching shell. Exit to continue."
print "----------------------------------"
target.launchShell()
target.unmount()
target.package()
except InstallationError, e:
print >> sys.stderr, "Error creating Live CD : %s" % e
target.teardown()
return 1
target.teardown()
return 0
if __name__ == "__main__":
sys.exit(main())
=================================
Mayflower:
=================================
#!/bin/bash
# mayflower - flexible mkinitrd replacement
#
# Copyright 2006 David Zeuthen <davidz at redhat.com>
#
# Licensed under the GPLv2. See the file COPYING for details.
# Inspired by similar programs from a bunch of other distributions.
#
usage() {
echo "$0 [--help] [--enable-netroot] <out-initrd-image>
<kernel-version>"
echo
echo "example: $0 /boot/myinitramfs.img \`uname -r\`"
}
opt_allow_overwrite=0
opt_verbose=0
opt_enable_netroot=0
INITRAMFS_TARGET=""
KERNEL=""
while [ $# -gt 0 ] ; do
case $1 in
--help)
usage
exit 0
;;
-f)
opt_allow_overwrite=1
;;
--allow-missing)
echo "Ignore option $1 for /sbin/mkinitrd compatibility"
;;
-v|--verbose)
opt_verbose=1
;;
--enable-netroot)
echo "Enabling netroot support"
opt_enable_netroot=1
;;
*)
if [ -z "$INITRAMFS_TARGET" ] ; then
INITRAMFS_TARGET=$1
elif [ -z "$KERNEL" ] ; then
KERNEL=$1
else
echo "Unknown option or parameter \"$1\""
echo
usage
exit 1
fi
;;
*)
;;
esac
shift
done
if [ -z "$INITRAMFS_TARGET" -o -z "$KERNEL" ] ; then
usage
exit 1
fi
if [ "$opt_allow_overwrite" == "0" ] ; then
if [ -e $INITRAMFS_TARGET ] ; then
echo "Image $INITRAMFS_TARGET already exists. Use -f to
overwrite"
exit 1
fi
fi
echo "Building an initramfs at $INITRAMFS_TARGET for kernel $KERNEL"
TEMPDIR=`mktemp -d` || exit 1
pushd $TEMPDIR > /dev/null
mkdir initramfs_dir
cd initramfs_dir
# Make directory structure
mkdir bin sbin dev sys proc lib lib/udev sysroot etc etc/udev
etc/udev/rules.d
cp /sbin/losetup sbin
cp /sbin/blockdev sbin
cp /sbin/dmsetup sbin
cp /bin/dd bin
MODULES=
if [ -e /etc/mayflower.conf ] ; then
source /etc/mayflower.conf
fi
# TODO: right now we only recognize MODULES... add support for more
# options such as 'include all modules neccessary to mount the mount
# point /mnt/temp_os_install' etc.
MODULES+=" "
if [ "$opt_verbose" == "1" ] ; then
echo "Kernel modules requested: $MODULES"
echo
fi
rm -f modules
for m in $MODULES ; do
/sbin/modprobe --set-version $KERNEL --show-depends $m >> modules
2>/dev/null
done
cat modules | awk '{if ($1=="install") print $5; else print $2; }' |
sort -u > modules2
rm -f modules
PRE_MODULES_FILES=`cat modules2`
rm -f modules2
for n in $PRE_MODULES_FILES ; do
if [ `dirname $n` = "." ]; then
echo `find /lib/modules -name "${n}.ko" | grep $KERNEL` >>
modules3
else
echo $n >> modules3
fi
done
MODULES_FILES=`cat modules3`
rm -rf modules3
mkdir -p lib/modules/$KERNEL/
# Copy kernel modules over
for f in $MODULES_FILES ; do
if [ "$opt_verbose" == "1" ] ; then
echo "Copying kernel module $f"
fi
cp $f lib/modules/$KERNEL/
done
# Build module deps file so we can use modprobe
if [ "$opt_verbose" == "1" ] ; then
/sbin/depmod -b `pwd` -v $KERNEL
else
/sbin/depmod -b `pwd` -v $KERNEL > /dev/null
fi
# Copy /etc/fstab over
cp /etc/fstab etc
# Copy modprobe.conf and friends over
if [ -e /etc/modprobe.conf ] ; then
cp /etc/modprobe.conf etc
fi
cp -R /etc/modprobe.d etc
# Copy binaries over
cp /bin/echo bin
cp /bin/sleep bin
cp /bin/bash bin
cp /bin/mount bin
cp /bin/umount bin
[ -x /usr/sbin/eject ] && cp /usr/sbin/eject sbin
cp /bin/ls bin
cp /bin/mknod bin
cp /bin/mkdir bin
cp /bin/chmod bin
cp /bin/ln bin
cp /bin/cat bin
cp /usr/bin/kill bin
cp /bin/rm bin
cp /sbin/udevsettle sbin
cp /sbin/udevtrigger sbin
cp /sbin/udevd sbin
cp /sbin/insmod sbin
cp /sbin/modprobe sbin
cp /sbin/pidof sbin
cp /sbin/killall5 sbin
cp /sbin/nash sbin
cp /lib/udev/vol_id lib/udev
# symlink niceties
ln -s bash bin/sh
# Not really required but nice
[ -x /usr/bin/tree ] && cp /usr/bin/tree bin
[ -x /usr/bin/less ] && cp /usr/bin/less bin
cp /bin/env bin
cp /bin/grep bin
cp /bin/dmesg bin
cp /sbin/lsmod sbin
# if we have the iso checker, we want it
[ -x /usr/lib/anaconda-runtime/checkisomd5 ] && cp
/usr/lib/anaconda-runtime/checkisomd5 bin
# Copy all required shared libs
for i in bin/* sbin/* lib/udev/*; do
ldd $i | sed 's|.*=>||g' | awk '/\// { print $1 }' | while read lib
; do
if [ "$opt_verbose" == "1" ] ; then
echo "Copying DSO $l"
fi
cp --parents $lib .
done
done
if [ "$opt_enable_netroot" == "1" ] ; then
cp /sbin/busybox sbin
ln -sf /sbin/busybox sbin/udhcpc
ln -sf /sbin/busybox sbin/ifconfig # needed by default.script
ln -sf /sbin/busybox sbin/route # needed by default.script
mkdir -p usr/share/udhcpc
cat > usr/share/udhcpc/default.script <<EOF
#!/bin/sh
# udhcpc script edited by Tim Riker <Tim at Rikers.org>
[ -z "\$1" ] && echo "Error: default.script should be called from
udhcpc" && exit 1
RESOLV_CONF="/etc/resolv.conf"
[ -n "\$broadcast" ] && BROADCAST="broadcast \$broadcast"
[ -n "\$subnet" ] && NETMASK="netmask \$subnet"
case "\$1" in
deconfig)
/sbin/ifconfig \$interface 0.0.0.0
;;
renew|bound)
/sbin/ifconfig \$interface \$ip \$BROADCAST \$NETMASK
if [ -n "\$router" ]; then
echo "deleting routers"
while route del default gw 0.0.0.0 dev
\$interface; do
:
done
for i in \$router; do
route add default gw \$i dev \$interface
done
fi
echo -n > \$RESOLV_CONF
[ -n "\$domain" ] && echo search \$domain >>
\$RESOLV_CONF
for i in \$dns; do
echo adding dns \$i
echo nameserver \$i >> \$RESOLV_CONF
done
;;
esac
exit 0
EOF
chmod +x usr/share/udhcpc/default.script
fi
cat > sbin/run-init <<EOF
#!/sbin/nash
setuproot
switchroot
EOF
chmod 755 sbin/run-init
# Write out init
cat > init <<EOF
#!/bin/bash
emergency_shell()
{
echo "Bug in initramfs /init detected. Dropping to a shell. Good
luck!"
echo
bash
}
trap "emergency_shell" 0 2
# exit immediately if a command fails
set -e
export PATH=/sbin:/bin
exec < /dev/console > /dev/console 2>&1
mount -n -t tmpfs -o mode=0755 udev /dev
mknod /dev/console c 5 1
mknod /dev/null c 1 3
mknod /dev/kmsg c 1 11
mkdir /dev/pts
mkdir -m 1777 /dev/shm
ln -s /proc/self/fd /dev/fd
ln -s fd/0 /dev/stdin
ln -s fd/1 /dev/stdout
ln -s fd/2 /dev/stderr
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
echo "" > /proc/sys/kernel/hotplug
# Declare all variables here.. mostly for housekeeping
#
init="/sbin/init"
root_ro=0
root_rw=0
root=""
rootflags=""
rootfstype=""
quiet=0
shell=0
eshell=0
live_ram=0
check_iso=0
live_locale=""
netroot=0
# Parse kernel commandline options
#
for o in \`cat /proc/cmdline\` ; do
case \$o in
init=*)
init=\${o#init=}
;;
ro)
root_ro=1
;;
rw)
root_rw=1
;;
quiet)
quiet=1
;;
shell)
shell=1
;;
eshell)
eshell=1
;;
live_ram)
live_ram=1
;;
live_locale=*)
live_locale=\${o#live_locale=}
;;
check)
check_iso=1
;;
netroot)
netroot=1
;;
esac
done
if [ "\$quiet" != "1" ] ; then
echo "kernel commandline: \`cat /proc/cmdline\`"
fi
# First, read rootfs target from embedded /etc/fstab file
#
if [ -f /etc/fstab ] ; then
root=$(cat /etc/fstab | while read d m f o r; do if [ "$m" == "/" ]
; then echo $d; fi; done)
rootflags=$(cat /etc/fstab | while read d m f o r; do if [ "$m" ==
"/" ] ; then echo $o; fi; done)
rootfstype=$(cat /etc/fstab | while read d m f o r; do if [ "$m" ==
"/" ] ; then echo $f; fi; done)
if [ "\$quiet" != "1" ] ; then
echo "fstab suggests root=\$root"
echo "fstab suggests rootflags=\$rootflags"
echo "fstab suggests rootfstype=\$rootfstype"
# Handle the case with bogus /etc/fstab pointing to /dev/root
# which by definition does not exist...
#
if [ "\$root" == "/dev/root" ] ; then
echo "WARNING: Bogus /etc/fstab file - cannot have /dev/root
as the device for /"
root=""
rootflags=""
rootfstype=""
fi
fi
fi
# Users can override rootfs target on the kernel commandline
#
for o in \`cat /proc/cmdline\` ; do
case \$o in
root=*)
root=\${o#root=}
;;
rootflags=*)
rootflags=\${o#rootflags=}
;;
rootfstype=*)
rootfstype=\${o#rootfstype=}
;;
esac
done
# Print out what we are going to do
#
if [ "\$quiet" != "1" ] ; then
echo "init=\$init"
echo "root=\$root"
echo "rootflags=\$rootflags"
echo "rootfstype=\$rootfstype"
echo "root_ro=\$root_ro"
echo "root_rw=\$root_rw"
echo "netroot=\$netroot"
fi
waitforsymlink=0
# generate udev rules to generate /dev/root symlink
if [ -z \$root ] ; then
root=/dev/something
else
case \$root in
/dev/disk/by-label/*)
LABEL=\${root#/dev/disk/by-label/}
echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$LABEL\", SYMLINK+=\"root\"" >
/etc/udev/rules.d/00-label.rules
if [ "\$quiet" != "1" ] ; then
echo "Added udev rule 00-label.rules:"
cat /etc/udev/rules.d/00-label.rules
fi
waitforsymlink=1
thingtomount=/dev/root
;;
CDLABEL=*)
CDLABEL=\${root#CDLABEL=}
echo "KERNEL==\"hd[a-z]\", BUS==\"ide\",
SYSFS{removable}==\"1\", ATTRS{media}==\"cdrom\",
PROGRAM=\"/lib/udev/vol_id -l %N\", RESULT==\"\$CDLABEL\",
SYMLINK+=\"root\"" > /etc/udev/rules.d/00-cdlabel.rules
echo "KERNEL==\"sr[0-9]\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" >>
/etc/udev/rules.d/00-cdlabel.rules
echo "KERNEL==\"scd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" >>
/etc/udev/rules.d/00-cdlabel.rules
echo "KERNEL==\"pcd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$CDLABEL\", SYMLINK+=\"root\"" >>
/etc/udev/rules.d/00-cdlabel.rules
if [ "\$quiet" != "1" ] ; then
echo "Added udev rule 00-cdlabel.rules:"
cat /etc/udev/rules.d/00-cdlabel.rules
fi
waitforsymlink=1
thingtomount=/dev/root
;;
LABEL=*)
LABEL=\${root#LABEL=}
echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$LABEL\", SYMLINK+=\"root\"" >
/etc/udev/rules.d/00-label.rules
if [ "\$quiet" != "1" ] ; then
echo "Added udev rule 00-label.rules:"
cat /etc/udev/rules.d/00-label.rules
fi
waitforsymlink=1
thingtomount=/dev/root
;;
/dev/disk/by-id/*)
UUID=\${root#/dev/disk/by-id/}
echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -u
%N\", RESULT==\"\$UUID\", SYMLINK+=\"root\"" >
/etc/udev/rules.d/01-uuid.rules
if [ "\$quiet" != "1" ] ; then
echo "Added udev rule 01-uuid.rules:"
cat /etc/udev/rules.d/01-uuid.rules
fi
waitforsymlink=1
thingtomount=/dev/root
;;
UUID=*)
UUID=\${root#UUID=}
echo "SUBSYSTEM==\"block\", PROGRAM=\"/lib/udev/vol_id -u
%N\", RESULT==\"\$UUID\", SYMLINK+=\"root\"" >
/etc/udev/rules.d/01-uuid.rules
if [ "\$quiet" != "1" ] ; then
echo "Added udev rule 01-uuid.rules:"
cat /etc/udev/rules.d/01-uuid.rules
fi
waitforsymlink=1
thingtomount=/dev/root
;;
/dev/*)
ln -s \$root /dev/root
thingtomount=\$root
;;
*)
thingtomount=\$root
;;
esac
fi
if [ "\$netroot" == "1" ] ; then
waitforsymlink=1
fi
echo "udev_log=\"error\"" >> /etc/udev/udev.conf
# rules for loading modules
#
echo -n "ACTION==\"add\", SUBSYSTEM==\"?*\", ENV{MODALIAS}==\"?*\",
RUN+=\"/sbin/modprobe \$" >> /etc/udev/rules.d/10-modprobe.rules
echo "env{MODALIAS}\"" >> /etc/udev/rules.d/10-modprobe.rules
echo "ACTION==\"add\", SUBSYSTEM==\"scsi_device\" RUN+=\"/sbin/modprobe
sg\"" >> /etc/udev/rules.d/10-modprobe.rules
echo "ACTION==\"add\", SUBSYSTEM==\"scsi_device\",
SYSFS{type}==\"0|7|14\", RUN+=\"/sbin/modprobe sd_mod\"" >>
/etc/udev/rules.d/10-modprobe.rules
echo "ACTION==\"add\", SUBSYSTEM==\"scsi_device\",
SYSFS{type}==\"[45]\", RUN+=\"/sbin/modprobe sr_mod\"" >>
/etc/udev/rules.d/10-modprobe.rules
# OLPC specific: olpc_nand_enable, hardcodes this device file.. sigh..
#
echo "KERNEL==\"msr[0-9]*\", NAME=\"cpu/%n/msr\"" >
/etc/udev/rules.d/20-cpu.rules
# FIXME: hack since sr_mod seems to fail to get loaded sometimes
(#239657)
/sbin/modprobe sr_mod
if [ "\$quiet" != "1" ] ; then
echo "starting udevd"
fi
/sbin/udevd --daemon
if [ "\$quiet" != "1" ] ; then
echo "creating devices"
fi
/sbin/udevtrigger
if [ "\$quiet" != "1" ] ; then
echo "waiting for system to settle"
fi
/sbin/udevsettle --timeout=30 || :
if [ "\$shell" == "1" ] ; then
echo "Shell requested on kernel commandline. Exit to continue
booting."
echo
bash
fi
# don't wait for "mtd0" as no device file will appear
if [ "\$root" != "mtd0" ] && [ "\$netroot" == "0" ] ; then
# If we don't have the /dev/root link.. ask the user to create..
if [ "\$waitforsymlink" != "1" ] ; then
if [ ! -L /dev/root ] ; then
echo
echo "--------------------------------------"
echo "WARNING: Cannot find root file system!"
echo "--------------------------------------"
echo
echo "Create symlink /dev/root and then exit this shell to
continue"
echo "the boot sequence."
echo
bash
fi
fi
# udevsettle might return before slow devices such as USB are in
shape
# Wait up to 60 seconds for them to appear...
#
if [ ! -b /dev/root ] ; then
if [ "\$quiet" != "1" ] ; then
echo "no root yet, udev rule will write symlink..."
echo
echo "waiting up to 60 seconds before dropping to emergency
shell."
fi
COUNTDOWN=60
while [ "x\$COUNTDOWN" != "x0" ] ; do
if [ "\$quiet" != "1" ] ; then
echo -n "."
fi
COUNTDOWN=\$((\$COUNTDOWN - 1))
/bin/sleep 1
if [ -e /dev/root ] ; then
COUNTDOWN=0
fi
done
fi
if [ ! -b /dev/root ] ; then
echo
echo "--------------------------------------"
echo "WARNING: Cannot find root file system!"
echo "--------------------------------------"
echo
echo "Create symlink /dev/root and then exit this shell to
continue"
echo "the boot sequence."
echo
bash
fi
if [ "\$quiet" != "1" ] && [ "\$netroot" == "0" ] ; then
echo "mounting /dev/root"
ls -l /dev/root
fi
if [ -z \$rootfstype ] ; then
rootfstype=auto
fi
fi
if [ "x\$check_iso" == "x1" -a -x /bin/checkisomd5 -a "x\$rootfstype" ==
"xiso9660" ]; then
echo "Verifying ISO image..."
/bin/checkisomd5 --verbose /dev/root
if [ \$? -ne 0 ]; then
echo "Are you SURE you want to continue?"
echo "Press Enter to continue or ctrl-alt-del to reboot."
read
fi
fi
if [ "x\$root_ro" == "x1" ] ; then
if [ -z \$rootflags ] ; then
rootflags="ro"
else
rootflags="\$rootflags,ro"
fi
fi
if [ "x\$root_rw" == "x1" ] ; then
if [ -z \$rootflags ] ; then
rootflags="rw"
else
rootflags="\$rootflags,rw"
fi
fi
if [ -z \$rootflags ] ; then
mountoptions=""
else
mountoptions=" -o\$rootflags"
fi
if [ "\$netroot" != "1" ]; then
mount -n -t \$rootfstype \$mountoptions \$thingtomount /sysroot
else
busybox udhcpc
busybox mount -n -t \$rootfstype \$mountoptions \$thingtomount
/sysroot
fi
RES=\$?
if [ "\$RES" != "0" ] ; then
echo "---------------------------------"
echo "WARNING: Cannot mount rootfs!"
echo "---------------------------------"
echo
echo "Dropping to a shell. "
echo "Mount rootfs at /sysroot and exit shell to continue. Good
luck!"
echo
bash
fi
# Now get ready to leave the initramfs
#
# only pass kernel command line if we're launching /sbin/init
if [ "\$init" == "/sbin/init" ] ; then
initargs=\$(cat /proc/cmdline)
else
initargs=""
fi
# live cd helper function
do_live_from_loop121() {
# create a sparse file for the overlay
dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((512*1024)) 2>
/dev/null
losetup /dev/loop119 /overlay
# set up the snapshot
echo 0 \`blockdev --getsize /dev/loop121\` snapshot /dev/loop121
/dev/loop119 p 8 | dmsetup create live-rw
# set up new /dev/root symlink
rm -f /dev/root
ln -s /dev/mapper/live-rw /dev/root
mount -n -t ext3 /dev/mapper/live-rw /sysroot
# here you can modify the rw ext3 fs for testing if you don't want
to
# respin the entire rootfs (which takes ages). Example
#
# echo foo > /sysroot/etc/bar.conf
#
# We also use it to dynamically set the system locale from the boot
# menu on live cd's.
#
if [ "\$live_locale" != "" ] ; then
echo "LANG=\$live_locale" > /sysroot/etc/sysconfig/i18n
fi
# create rule so udev creates /dev/live symlink on real rootfs
if [ -n "\$CDLABEL" ]; then
echo "KERNEL==\"hd[a-z]\", BUS==\"ide\", SYSFS{removable}==\"1\",
ATTRS{media}==\"cdrom\", PROGRAM=\"/lib/udev/vol_id -l %N\",
RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"sr[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\",
RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"scd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\",
RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"pcd[0-9]\", PROGRAM=\"/lib/udev/vol_id -l %N\",
RESULT==\"\$CDLABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
elif [ -n "\$LABEL" ]; then
echo "KERNEL==\"hd[a-z]\", PROGRAM=\"/lib/udev/vol_id -l %N\",
RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"hd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"sd[a-z]\", PROGRAM=\"/lib/udev/vol_id -l %N\",
RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"sd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -l
%N\", RESULT==\"\$LABEL\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
elif [ -n "\$UUID" ]; then
echo "KERNEL==\"hd[a-z]\", PROGRAM=\"/lib/udev/vol_id -u %N\",
RESULT==\"\$UUID\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"hd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -u
%N\", RESULT==\"\$UUID\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"sd[a-z]\", PROGRAM=\"/lib/udev/vol_id -u %N\",
RESULT==\"\$UUID\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"sd[a-z][0-9]*\", PROGRAM=\"/lib/udev/vol_id -u
%N\", RESULT==\"\$UUID\", SYMLINK+=\"live\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
fi
# add rules for /dev/live-squashed and /dev/live-osimg
echo "KERNEL==\"loop120\" SYMLINK+=\"live-squashed\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
echo "KERNEL==\"loop121\" SYMLINK+=\"live-osimg\"" >>
/sysroot/etc/udev/rules.d/50-udev.rules
if [ "\$netroot" == "0" ] ; then
mount -n -o ro,remount /sysroot
fi
}
# we might have an uncompressed embedded ext3 to use as rootfs
(uncompressed live)
#
if [ -e /sysroot/LiveOS/ext3fs.img ]; then
EXT3FS="/sysroot/LiveOS/ext3fs.img"
elif [ -e /sysroot/ext3fs.img ] ; then
EXT3FS="/sysroot/ext3fs.img"
fi
if [ -n "\$EXT3FS" ] ; then
if [ "\$quiet" != "1" ] ; then
echo "setting up embedded ext3 fs "
fi
mknod /dev/loop118 b 7 118
mknod /dev/loop119 b 7 119
mknod /dev/loop120 b 7 120
mknod /dev/loop121 b 7 121
mkdir -p /dev/mapper
mknod /dev/mapper/control c 10 63
modprobe loop max_loop=128
modprobe dm_snapshot
losetup /dev/loop121 \$EXT3FS
umount -l /sysroot
do_live_from_loop121
fi
# we might have an embedded ext3 on squashfs to use as rootfs
(compressed live)
#
if [ -e /sysroot/LiveOS/squashfs.img ]; then
SQUASHED="/sysroot/LiveOS/squashfs.img"
elif [ -e /sysroot/squashfs.img ]; then
SQUASHED="/sysroot/squashfs.img"
fi
if [ -n "\$SQUASHED" ] ; then
if [ "\$quiet" != "1" ] ; then
echo "setting up embedded squash -> ext3 fs "
fi
mknod /dev/loop118 b 7 118
mknod /dev/loop119 b 7 119
mknod /dev/loop120 b 7 120
mknod /dev/loop121 b 7 121
mkdir -p /dev/mapper
mknod /dev/mapper/control c 10 63
modprobe loop max_loop=128
modprobe dm_snapshot
if [ "\$live_ram" == "1" ] ; then
echo "Copying live image to RAM..."
echo "(this may take a few minutes)"
dd if=\$SQUASHED of=/squashed.img bs=512 2> /dev/null
umount -n /sysroot
echo "Done copying live image to RAM."
if [ "\$netroot" == "0" ]; then
eject -p /dev/root
fi
SQUASHED="/squashed.img"
fi
losetup /dev/loop120 \$SQUASHED
mkdir -p /squashfs
mount -n -t squashfs -o ro /dev/loop120 /squashfs
losetup /dev/loop121 /squashfs/os.img
umount -l /squashfs
if [ "\$live_ram" == "0" ] ; then
umount -l /sysroot
fi
do_live_from_loop121
fi
if [ "\$eshell" == "1" ] ; then
echo "Shell requested on kernel commandline."
echo "Rootfs is mounted ro on /sysroot. Exit to continue booting."
echo
bash
fi
if [ -x /sysroot\$init ] ; then
# Leave initramfs and transition to rootfs
kill \`pidof udevd\`
if [ "\$quiet" != "1" ] ; then
echo "transfering control to \$init"
fi
exec /sbin/run-init
echo "---------------------------------"
echo "WARNING: Error switching to real rootfs!"
echo "---------------------------------"
echo
echo "Dropping to a shell. Good luck!"
echo
bash
else
echo "---------------------------------------------------------"
echo "WARNING: Requested \$init binary does not exist on rootfs."
echo "---------------------------------------------------------"
echo
echo "Dropping to a shell. Good luck!"
echo
bash
fi
EOF
chmod a+x init
if [ "$opt_verbose" == "1" ] ; then
tree -s .
echo
cat -n init
echo
fi
find . | cpio --quiet -o -H newc | gzip -9 > ../initramfs
popd > /dev/null
rm -f $INITRAMFS_TARGET
cp $TEMPDIR/initramfs $INITRAMFS_TARGET
rm -rf $TEMPDIR
echo "Done; initramfs is $(du -h $INITRAMFS_TARGET | awk '{print $1}')."
echo
exit 0
-----Original Message-----
From: fedora-livecd-list-bounces at redhat.com
[mailto:fedora-livecd-list-bounces at redhat.com] On Behalf Of Jane Dogalt
Sent: Wednesday, June 06, 2007 6:29 PM
To: fedora-livecd-list at redhat.com
Subject: RE: [Fedora-livecd-list] Net Boot
--- Mohammed_Khan at Dell.com wrote:
> I hacked mayflower and livecd-creator to add busybox and some network
> modules and their dependencies... I can now get the livecd to boot
> kernel / initramfs over pxe and then louad the squashfs.img over nfs.
> If
> you guys are interested I can post the code here.
Yes please. I suspect it may help out if I ever get around to trying to
scratch that fuse-http-iso-fs itch. (i.e. mounting squashfs.img from
the web)
-dmc/jdog
________________________________________________________________________
____________
Choose the right car based on your needs. Check out Yahoo! Autos new
Car Finder tool.
http://autos.yahoo.com/carfinder/
--
Fedora-livecd-list mailing list
Fedora-livecd-list at redhat.com
https://www.redhat.com/mailman/listinfo/fedora-livecd-list
More information about the Fedora-livecd-list
mailing list