Compare commits

...

77 Commits

Author SHA1 Message Date
Brian C. Lane
a2c36797fe New version 0.4.7 2012-03-06 10:12:51 -08:00
Brian C. Lane
88c85cf76f add mkefiboot and imgutils.py
livecd-creator needs mkefiboot to make images that are bootable on Mac
2012-03-06 10:11:19 -08:00
Martin Gracik
1e28497ee2 New version 2011-05-10 17:09:44 +02:00
Martin Gracik
6823e5da69 Do not remove libmodman (#701622) 2011-05-10 14:45:16 +02:00
Martin Gracik
b1ccc9827a Add firmware for Intel Wireless WiFi Link 6030 Adapters (#703291) 2011-05-10 12:37:02 +02:00
Martin Gracik
682f049d33 New version 2011-05-03 15:32:08 +02:00
Martin Gracik
c861707821 Disable debuginfo package 2011-05-03 15:30:26 +02:00
Martin Gracik
73c4198c22 Do not remove libproxy (#701622) 2011-05-03 15:28:22 +02:00
Martin Gracik
40bd077a2a New version 2011-05-02 09:20:33 +02:00
Ales Kozumplik
78709fe029 Disable rsyslogd rate limiting on imuxsock.
Unbelievably, a new rsyslogd version turned on this undesirable feature by
default.

Related: rhbz#696943
2011-05-02 08:53:39 +02:00
Chris Lumens
d8bb479421 Add the udf module to the image. 2011-04-21 11:14:47 -04:00
Martin Gracik
a3593d05a2 New version 2011-04-19 10:06:27 +02:00
Martin Gracik
09d6569fd3 bits is an integer and replace needs arguments to be strings (#697542) 2011-04-19 08:44:01 +02:00
Martin Gracik
4271a37e9a Use arch macros in the lorax.spec 2011-04-15 16:01:32 +02:00
Martin Gracik
12db6da29a use reqs not regs for files to backup (dgilmore) 2011-04-15 15:44:38 +02:00
Martin Gracik
b054345a2a Reflect changes made in ntfs-3g and ntfsprogs packages (#696706) 2011-04-15 10:09:19 +02:00
Martin Gracik
b41331ea75 getkeymaps resides in /usr/libexec/anaconda 2011-04-15 09:47:21 +02:00
Martin Gracik
5bb6d1e59b workdir is a local variable, not a class attribute 2011-04-15 09:41:59 +02:00
Martin Gracik
15edee2353 Add sparcv9 to arch map 2011-04-13 16:13:36 +02:00
Martin Gracik
bd3197845a Change the location of *.b files on sparc 2011-04-13 16:11:58 +02:00
Martin Gracik
7bbb584c6c New version 2011-04-13 14:25:19 +02:00
Martin Gracik
8588913b10 Do not remove shutdown from sbin 2011-04-13 14:19:52 +02:00
Martin Gracik
4e42a82b20 Change BuildRequires to python2-devel 2011-04-13 14:04:32 +02:00
Martin Gracik
8fcbe0c773 Remove pungi patch 2011-04-13 13:25:02 +02:00
Martin Gracik
ac0f1c3c51 Remove pseudo code 2011-04-13 13:24:51 +02:00
Martin Gracik
e10403eeb5 New version 2011-04-13 10:34:56 +02:00
Martin Gracik
3d8a48c69d Provide shutdown on s390x (#694518) 2011-04-12 13:19:39 +02:00
Martin Gracik
35d85a7b4f Fix arch specific requires in spec file 2011-04-12 13:19:39 +02:00
Martin Gracik
3930b8ea6c Add s390 modules and do some cleanup of the template 2011-04-12 13:19:39 +02:00
Martin Gracik
3851ac2fb2 Generate ssh keys on s390 2011-04-12 13:19:39 +02:00
Martin Gracik
d5515f820b Don't remove tr, needed for s390 2011-04-12 13:19:39 +02:00
Martin Gracik
024f7137c6 Do not check if we have all commands 2011-04-12 13:19:39 +02:00
Martin Gracik
507735e127 Change location of addrsize and mk-s390-cdboot 2011-04-12 13:19:39 +02:00
Martin Gracik
a73cedc951 Shutdown is in another location 2011-04-12 13:19:39 +02:00
Martin Gracik
4064c78fe6 Do not skip broken packages 2011-04-12 13:19:39 +02:00
Martin Gracik
fb8224b71d Don't install network-manager-netbook 2011-04-12 13:19:38 +02:00
Martin Gracik
80650edb4d Wait for subprocess to finish 2011-04-12 13:19:38 +02:00
Martin Gracik
fbd8da6d40 Have to call os.makedirs 2011-04-12 13:19:38 +02:00
Martin Gracik
ef1ae59a8a images dir already exists, we just need to set it 2011-04-12 13:19:38 +02:00
Martin Gracik
c3e7664448 The biarch is a function not an attribute 2011-04-12 13:19:38 +02:00
Martin Gracik
f5258e7266 Create images directory in outputtree 2011-04-12 13:19:38 +02:00
Martin Gracik
76ba5755fc Create efibootdir if doing efi images 2011-04-12 13:19:38 +02:00
Ales Kozumplik
1b5100b5ca Get rid of create_gconf().
We do what create_gconf is trying to achieve in get_config_files(). What's
more, the files in crete_gconf() end up in the root directory where
nothing can possibly use them because the root user's home is now /root.
2011-04-12 13:19:38 +02:00
Martin Gracik
c41e8a89b8 Replace variables in yaboot.conf 2011-04-12 13:19:38 +02:00
Martin Gracik
ae90d14e44 Add sparc specific packages 2011-04-12 13:19:38 +02:00
Martin Gracik
a588f46823 Skip keymap creation on s390 2011-04-12 13:19:38 +02:00
Martin Gracik
69ad288e66 Copy shutdown and linuxrc.s390 on s390 2011-04-12 13:19:38 +02:00
Martin Gracik
bdba285796 Add packages for s390 2011-04-12 13:19:38 +02:00
Martin Gracik
662449d0f6 Add support for sparc 2011-04-12 13:19:38 +02:00
Martin Gracik
9b8a8c83d7 Use factory to get the image classes 2011-04-12 13:19:38 +02:00
Martin Gracik
7bfb602ff4 treeinfo has to be addressed as self.treeinfo 2011-04-12 13:19:38 +02:00
Martin Gracik
682515da71 Add support for s390 2011-04-12 13:19:38 +02:00
Martin Gracik
c7f43aaa6b Add the xen section to treeinfo on x86_64 2011-04-12 13:19:38 +02:00
Martin Gracik
3f64827719 Fix magic and mapping paths 2011-04-12 13:19:38 +02:00
Martin Gracik
d2daafa402 Fix passing of prepboot and macboot arguments 2011-04-12 13:19:38 +02:00
Martin Gracik
073e71ad8b Small ppc fixes 2011-04-12 13:19:38 +02:00
Martin Gracik
7fddbc3b09 Check if the file we want to remove exists
If we have directory symlinks, some files could have already
been removed and we get a traceback. This prevents the traceback.
2011-04-12 13:19:38 +02:00
Martin Gracik
33688a99f2 Install x86 specific packages only on x86 2011-04-12 13:19:38 +02:00
Martin Gracik
589ae9e600 Change the location of zImage.lds 2011-04-12 13:19:38 +02:00
Martin Gracik
ac4572202f Added ppc specific packages 2011-04-12 13:19:38 +02:00
Martin Gracik
183bcc7065 memtest and efika.forth are in /boot 2011-04-12 13:19:38 +02:00
Martin Gracik
203cc7b15f Add support for ppc
The way we create the images had to be changed a little.
Some code had to be moved to other places, so we can create
images for other architectures too.
2011-04-12 13:19:37 +02:00
Martin Gracik
772cab692c Minor sparc pseudo code changes 2011-04-12 13:19:37 +02:00
Martin Gracik
72bfb754fd Added sparc pseudo code (dgilmore) 2011-04-12 13:19:37 +02:00
Martin Gracik
b3362abeff Added s390 and x86 pseudo code 2011-04-12 13:19:37 +02:00
Martin Gracik
eed099d1cf Added ppc pseudo code 2011-04-12 13:19:37 +02:00
Martin Gracik
aff37a71d1 Print a message when no arguments given (#684463) 2011-04-12 13:19:37 +02:00
Martin Gracik
600e9c16e8 Mako template returns unicode strings (#681003)
New mako template returns unicode strings, which are
a problem for shlex. We need to encode them to ascii.
2011-04-12 13:19:37 +02:00
Martin Gracik
866b36115a The check option in options causes ValueError
The crc32 check we want is the default anyway,
so we don't need to specify it.
2011-04-12 13:19:37 +02:00
Ales Kozumplik
e17d3484e1 Disable all ctrl-alt-arrow metacity shortcuts.
No need for desktop switching, just makes the users confused.

Resolves: rhbz#678892
2011-04-12 13:19:37 +02:00
Martin Gracik
d5c4537476 Use xz when compressing the initrd
This makes the image a lot smaller.
2011-04-12 13:19:37 +02:00
Martin Gracik
1b67c2690b New version 2011-03-21 14:50:33 +01:00
Ales Kozumplik
80035c6b7b gconf/metacity: have only one workspace.
Related: rhbz#683548
2011-03-21 08:57:05 +01:00
Ales Kozumplik
c0a8d7deff Do not remove libassuan.
A python lib we use (python-value_key) depends on this. If it fails to
import the module we see weird problems importing python modules backed up
by .so libraries, for instance:

ImportError: /lib64/libcryptsetup.so.1: undefined symbol: uuid_generate

Related: rhbz#684742
2011-03-21 08:48:16 +01:00
Martin Gracik
d28b812189 Add yum-langpacks yum plugin to anaconda environment (notting) (#687866)
This allows for installation of package's language packs without needing to
list them explicitly in the <foo>-support comps groups. Those groups (and
the corresponding code in yuminstall.py) are still needed at least in the
short term, due to fonts, input methods, and some internal architecture
issues in the plugin.
2011-03-15 16:48:23 +01:00
Martin Gracik
5f27c4ee62 New version 2011-03-15 14:51:44 +01:00
Martin Gracik
ccd8a136b0 Add the images-xen section to treeinfo on x86_64 (#683383) 2011-03-15 14:51:07 +01:00
16 changed files with 1594 additions and 281 deletions

View File

@ -1,82 +0,0 @@
From 3daa27d445a3181c3b95ec695af0114b5e7bfa2a Mon Sep 17 00:00:00 2001
From: Martin Gracik <mgracik@redhat.com>
Date: Mon, 8 Nov 2010 15:28:36 +0100
Subject: [PATCH] Lorax patch
Use lorax instead of buildinstall
---
src/pypungi/__init__.py | 52 ++++++++++++++++------------------------------
1 files changed, 18 insertions(+), 34 deletions(-)
diff --git a/src/pypungi/__init__.py b/src/pypungi/__init__.py
index 0e3efbd..7a9dbe7 100644
--- a/src/pypungi/__init__.py
+++ b/src/pypungi/__init__.py
@@ -773,46 +773,30 @@ class Pungi(pypungi.PungiBase):
self._makeMetadata(path, cachedir, repoview=False)
def doBuildinstall(self):
- """Run anaconda-runtime's buildinstall on the tree."""
+ """Run lorax on the tree."""
+ self._inityum()
+ yb = self.ayum
- # setup the buildinstall call
- buildinstall = ['/usr/libexec/anaconda/buildinstall']
- #buildinstall.append('TMPDIR=%s' % self.workdir) # TMPDIR broken in buildinstall
+ product = self.config.get('pungi', 'name')
+ version = self.config.get('pungi', 'version')
+ release = '%s %s' % (self.config.get('pungi', 'name'), self.config.get('pungi', 'version'))
- buildinstall.append('--product')
- buildinstall.append(self.config.get('pungi', 'name'))
+ variant = self.config.get('pungi', 'flavor')
+ bugurl = self.config.get('pungi', 'bugurl')
- if not self.config.get('pungi', 'flavor') == "":
- buildinstall.append('--variant')
- buildinstall.append(self.config.get('pungi', 'flavor'))
-
- buildinstall.append('--version')
- buildinstall.append(self.config.get('pungi', 'version'))
-
- buildinstall.append('--release')
- buildinstall.append('%s %s' % (self.config.get('pungi', 'name'), self.config.get('pungi', 'version')))
-
- if self.config.has_option('pungi', 'bugurl'):
- buildinstall.append('--bugurl')
- buildinstall.append(self.config.get('pungi', 'bugurl'))
-
- buildinstall.append('--output')
- buildinstall.append(self.topdir)
-
- for mirrorlist in self.mirrorlists:
- buildinstall.append('--mirrorlist')
- buildinstall.append(mirrorlist)
-
- buildinstall.append(self.topdir)
-
- # Add any extra repos of baseurl type
- for repo in self.repos:
- buildinstall.append(repo)
+ workdir = self.workdir
+ outputdir = self.topdir
# run the command
- # TMPDIR is still broken with buildinstall.
- pypungi.util._doRunCommand(buildinstall, self.logger) #, env={"TMPDIR": self.workdir})
+ import pylorax
+ lorax = pylorax.Lorax()
+ lorax.configure()
+
+ # FIXME get the actual is_beta value
+ lorax.run(yb, product=product, version=version, release=release,
+ variant=variant, bugurl=bugurl, is_beta=False,
+ workdir=workdir, outputdir=outputdir)
# write out the tree data for snake
self.writeinfo('tree: %s' % self.mkrelative(self.topdir))
--
1.7.1.1

View File

@ -1,5 +1,7 @@
%define debug_package %{nil}
Name: lorax
Version: 0.3
Version: 0.4.7
Release: 1%{?dist}
Summary: Tool for creating the anaconda install images
@ -7,10 +9,8 @@ Group: Applications/System
License: GPLv2+
URL: http://git.fedorahosted.org/git/?p=lorax.git
Source0: https://fedorahosted.org/releases/l/o/%{name}/%{name}-%{version}.tar.bz2
BuildArch: noarch
BuildRequires: python-setuptools
Requires: python2-devel
BuildRequires: python2-devel
Requires: python-mako
Requires: gawk
Requires: glibc-common
@ -20,12 +20,20 @@ Requires: device-mapper
Requires: findutils
Requires: GConf2
Requires: isomd5sum
Requires: syslinux
Requires: glibc
Requires: util-linux-ng
Requires: dosfstools
Requires: genisoimage
Requires: parted
Requires: pyliblzma
%ifarch %{ix86} x86_64
Requires: syslinux
%endif
%ifarch %{sparc}
Requires: silo
%endif
%description
Lorax is a tool for creating the anaconda install images.
@ -45,6 +53,7 @@ make DESTDIR=$RPM_BUILD_ROOT install
%{python_sitelib}/pylorax
%{python_sitelib}/*.egg-info
%{_sbindir}/lorax
%{_sbindir}/mkefiboot
%dir %{_sysconfdir}/lorax
%config(noreplace) %{_sysconfdir}/lorax/lorax.conf
%dir %{_datadir}/lorax
@ -52,6 +61,97 @@ make DESTDIR=$RPM_BUILD_ROOT install
%changelog
* Tue Mar 06 2012 Brian C. Lane <bcl@redhat.com> 0.4.7-1
- add mkefiboot and imgutils.py (bcl)
* Tue May 10 2011 Martin Gracik <mgracik@redhat.com> 0.4.6-1
- Do not remove libmodman (#701622)
- Add firmware for Intel Wireless WiFi Link 6030 Adapters (#703291)
* Tue May 03 2011 Martin Gracik <mgracik@redhat.com> 0.4.5-1
- Disable debuginfo package
- Do not remove libproxy (#701622)
* Mon May 02 2011 Martin Gracik <mgracik@redhat.com> 0.4.4-1
- Disable rsyslogd rate limiting on imuxsock.
- Add the udf module to the image.
* Tue Apr 19 2011 Martin Gracik <mgracik@redhat.com> 0.4.3-1
- bits is an integer and replace needs arguments to be strings (#697542)
- Use arch macros in the lorax.spec
- use reqs not regs for files to backup (dgilmore)
- Reflect changes made in ntfs-3g and ntfsprogs packages (#696706)
- getkeymaps resides in /usr/libexec/anaconda
- workdir is a local variable, not a class attribute
- Add sparcv9 to arch map
- Change the location of *.b files on sparc
* Wed Apr 13 2011 Martin Gracik <mgracik@redhat.com> 0.4.2-1
- Do not remove shutdown from sbin
- Change BuildRequires to python2-devel
- Remove pungi patch
- Remove pseudo code
* Wed Apr 13 2011 Martin Gracik <mgracik@redhat.com> 0.4.1-1
- Provide shutdown on s390x (#694518)
- Fix arch specific requires in spec file
- Add s390 modules and do some cleanup of the template
- Generate ssh keys on s390
- Don't remove tr, needed for s390
- Do not check if we have all commands
- Change location of addrsize and mk-s390-cdboot
- Shutdown is in another location
- Do not skip broken packages
- Don't install network-manager-netbook
- Wait for subprocess to finish
- Have to call os.makedirs
- images dir already exists, we just need to set it
- The biarch is a function not an attribute
- Create images directory in outputtree
- Create efibootdir if doing efi images
- Get rid of create_gconf().
- Replace variables in yaboot.conf
- Add sparc specific packages
- Skip keymap creation on s390
- Copy shutdown and linuxrc.s390 on s390
- Add packages for s390
- Add support for sparc
- Use factory to get the image classes
- treeinfo has to be addressed as self.treeinfo
- Add support for s390
- Add the xen section to treeinfo on x86_64
- Fix magic and mapping paths
- Fix passing of prepboot and macboot arguments
- Small ppc fixes
- Check if the file we want to remove exists
- Install x86 specific packages only on x86
- Change the location of zImage.lds
- Added ppc specific packages
- memtest and efika.forth are in /boot
- Add support for ppc
- Minor sparc pseudo code changes
- Added sparc pseudo code (dgilmore)
- Added s390 and x86 pseudo code
- Added ppc pseudo code
- Print a message when no arguments given (#684463)
- Mako template returns unicode strings (#681003)
- The check option in options causes ValueError
- Disable all ctrl-alt-arrow metacity shortcuts.
- Use xz when compressing the initrd
* Mon Mar 21 2011 Martin Gracik <mgracik@redhat.com> 0.3.2-1
- gconf/metacity: have only one workspace. (#683548)
- Do not remove libassuan. (#684742)
- Add yum-langpacks yum plugin to anaconda environment (notting) (#687866)
* Tue Mar 15 2011 Martin Gracik <mgracik@redhat.com> 0.3.1-1
- Add the images-xen section to treeinfo on x86_64
- Add /sbin to $PATH (for the tty2 terminal)
- Create /var/run/dbus directory in installtree
- Add mkdir support to template
- gpart is present only on i386 arch (#672611)
- util-linux-ng changed to util-linux
* Mon Jan 24 2011 Martin Gracik <mgracik@redhat.com> 0.3-1
- Don't remove libmount package
- Don't create mtab symlink, already exists

View File

@ -15,7 +15,7 @@ for root, dnames, fnames in os.walk("share"):
[os.path.join(root, fname)]))
# executable
data_files.append(("/usr/sbin", ["src/sbin/lorax"]))
data_files.append(("/usr/sbin", ["src/sbin/lorax", "src/sbin/mkefiboot"]))
setup(name="lorax",
version="0.1",

View File

@ -1,6 +1,7 @@
#### MODULES ####
$ModLoad imuxsock.so # provides support for local system logging
$ModLoad imklog.so # provides kernel logging support
$ModLoad imuxsock.so # provides support for local system logging
$SystemLogRateLimitInterval 0 # disables message dropping, we need all of them
$ModLoad imklog.so # provides kernel logging support
$ModLoad imfile
$InputFileName /tmp/X.log

View File

@ -10,6 +10,41 @@ install "kernel"
install "gpart"
% endif
## x86 specific packages
% if basearch == "i386" or basearch == "x86_64":
install "biosdevname"
install "efibootmgr"
install "firstaidkit-plugin-grub"
install "grub"
install "memtest86+"
% endif
## ppc specific packages
% if basearch == "ppc":
install "fbset"
install "hfsutils"
install "kernel-bootwrapper"
install "pcmciautils"
install "pdisk"
install "ppc64-utils"
install "yaboot"
% endif
## s390 specific packages
% if basearch == "s390x":
install "lsscsi"
install "modutils"
install "mount"
install "s390utils-base"
install "s390utils-cmsfs"
% endif
## sparc specific packages
% if basearch == "sparc":
install "silo"
install "tilo"
% endif
## other required packages
install "NetworkManager-gnome"
install "at-spi"
@ -18,7 +53,6 @@ install "at-spi2-atk"
install "audit"
install "bind-libs"
install "bind-utils"
install "biosdevname"
install "bitmap-fangsongti-fonts"
install "btrfs-progs"
install "bzip2-libs"
@ -29,12 +63,10 @@ install "dejavu-sans-fonts"
install "dejavu-sans-mono-fonts"
install "dogtail"
install "dump"
install "efibootmgr"
install "ethtool"
install "fedora-gnome-theme"
install "fedora-icon-theme"
install "firstaidkit-engine"
install "firstaidkit-plugin-grub"
install "firstboot"
install "ftp"
install "gdb-gdbserver"
@ -46,11 +78,9 @@ install "gnome-icon-theme-legacy"
install "gnome-keyring"
install "gnome-python2-bonobo"
install "gnome-python2-gconf"
##install "gnome-themes-legacy"
install "gnome-themes-standard"
install "gobject-introspection"
install "groff"
install "grub"
install "gtk+"
install "hdparm"
install "jfsutils"
@ -79,15 +109,12 @@ install "lsof"
install "lvm2-cluster"
install "madan-fonts"
install "man-db"
install "memtest86+"
install "metacity"
install "mt-st"
install "mtr"
install "network-manager-netbook"
install "nfs-utils"
install "notification-daemon"
install "ntfs-3g"
install "ntfsprogs"
install "openssh-server"
install "pciutils"
install "pciutils-libs"
@ -125,75 +152,36 @@ install "volume_key-libs"
install "wget"
install "xfsprogs"
install "xorg-x11-drivers"
##install "xorg-x11-drv-acecad"
##install "xorg-x11-drv-aiptek"
##install "xorg-x11-drv-apm"
##install "xorg-x11-drv-ast"
##install "xorg-x11-drv-ati"
##install "xorg-x11-drv-cirrus"
##install "xorg-x11-drv-dummy"
##install "xorg-x11-drv-elographics"
##install "xorg-x11-drv-evdev"
##install "xorg-x11-drv-fbdev"
##install "xorg-x11-drv-fpit"
##install "xorg-x11-drv-glint"
##install "xorg-x11-drv-hyperpen"
##install "xorg-x11-drv-i128"
##install "xorg-x11-drv-i740"
##install "xorg-x11-drv-intel"
##install "xorg-x11-drv-keyboard"
##install "xorg-x11-drv-mach64"
##install "xorg-x11-drv-mga"
##install "xorg-x11-drv-mouse"
##install "xorg-x11-drv-mutouch"
##install "xorg-x11-drv-nouveau"
##install "xorg-x11-drv-nv"
##install "xorg-x11-drv-openchrome"
##install "xorg-x11-drv-penmount"
##install "xorg-x11-drv-qxl"
##install "xorg-x11-drv-r128"
##install "xorg-x11-drv-rendition"
##install "xorg-x11-drv-s3virge"
##install "xorg-x11-drv-savage"
##install "xorg-x11-drv-siliconmotion"
##install "xorg-x11-drv-sis"
##install "xorg-x11-drv-sisusb"
##install "xorg-x11-drv-synaptics"
##install "xorg-x11-drv-tdfx"
##install "xorg-x11-drv-trident"
##install "xorg-x11-drv-v4l"
##install "xorg-x11-drv-vesa"
##install "xorg-x11-drv-vmmouse"
##install "xorg-x11-drv-vmware"
##install "xorg-x11-drv-void"
##install "xorg-x11-drv-voodoo"
##install "xorg-x11-drv-wacom"
install "xorg-x11-fonts-ethiopic"
install "xorg-x11-fonts-misc"
install "xorg-x11-server-Xorg"
install "xorg-x11-server-utils"
install "yum-langpacks"
install "${product}-logos"
install "${product}-release"
## required firmware
install "aic94xx-firmware"
install "ar9170-firmware"
install "atmel-firmware"
install "ipw2100-firmware"
install "ipw2200-firmware"
install "iwl1000-firmware"
install "iwl3945-firmware"
install "iwl4965-firmware"
install "iwl5000-firmware"
install "iwl5150-firmware"
install "iwl6000-firmware"
install "iwl6050-firmware"
install "ql2100-firmware"
install "ql2200-firmware"
install "ql23xx-firmware"
install "ql2400-firmware"
install "ql2500-firmware"
install "zd1211-firmware"
% if basearch != "s390x":
install "aic94xx-firmware"
install "ar9170-firmware"
install "atmel-firmware"
install "ipw2100-firmware"
install "ipw2200-firmware"
install "iwl1000-firmware"
install "iwl3945-firmware"
install "iwl4965-firmware"
install "iwl5000-firmware"
install "iwl5150-firmware"
install "iwl6000-firmware"
install "iwl6000g2b-firmware"
install "iwl6050-firmware"
install "ql2100-firmware"
install "ql2200-firmware"
install "ql23xx-firmware"
install "ql2400-firmware"
install "ql2500-firmware"
install "zd1211-firmware"
% endif
## required directories
mkdir "/var/run/dbus"
@ -266,7 +254,6 @@ remove "libXv"
remove "libXvMC"
remove "libXxf86misc"
remove "libXxf86vm"
remove "libassuan"
remove "libasyncns"
remove "libccss"
remove "libcgroup"
@ -278,11 +265,9 @@ remove "libhbaapi"
remove "libhbalinux"
remove "libibverbs"
remove "libmcpp"
remove "libmodman"
remove "libmx"
remove "libnih"
remove "libpcap"
remove "libproxy"
remove "librdmacm"
remove "librsvg2"
remove "libselinux-utils"
@ -455,6 +440,7 @@ module "st"
module "sunrpc"
module "tcic"
module "ub"
module "udf"
module "uhci-hcd"
module "ums-alauda"
module "ums-cypress"
@ -474,6 +460,13 @@ module "xfs"
module "xts"
module "yenta_socket"
## s390 modules
% if basearch == "s390x":
module "dasd_eckd_mod"
module "dasd_fba_mod"
module "dasd_diag_mod"
% endif
## other removals
remove --path "/usr/share/doc"
remove --path "/usr/share/info"
@ -640,7 +633,6 @@ remove "coreutils" "/usr/bin/stdbuf"
remove "coreutils" "/usr/bin/sum"
remove "coreutils" "/usr/bin/test"
remove "coreutils" "/usr/bin/timeout"
remove "coreutils" "/usr/bin/tr"
remove "coreutils" "/usr/bin/truncate"
remove "coreutils" "/usr/bin/tsort"
remove "coreutils" "/usr/bin/unexpand"
@ -1029,7 +1021,6 @@ remove "ntfs-3g" "/sbin/mount.lowntfs-3g"
remove "ntfs-3g" "/usr/share/hal/*"
remove "ntfs-3g" "/usr/bin/*"
remove "ntfsprogs" "/sbin/*"
remove "ntfsprogs" "/usr/bin/ntfsck"
remove "openldap" "/etc/openldap/*"
remove "openldap" "/usr/${libdir}/libldap_r-*"
remove "openldap" "/usr/${libdir}/libldap_r-*"

View File

@ -54,6 +54,7 @@ from outputtree import LoraxOutputTree
from buildstamp import BuildStamp
from treeinfo import TreeInfo
from discinfo import DiscInfo
import images
ARCHMAPS = {
@ -66,6 +67,7 @@ ARCHMAPS = {
"s390": {"base": "s390", "efi": "", "is64": False},
"s390x": {"base": "s390x", "efi": "", "is64": True},
"sparc": {"base": "sparc", "efi": "", "is64": False},
"sparcv9": {"base": "sparc", "efi": "", "is64": False},
"sparc64": {"base": "sparc", "efi": "", "is64": True},
"ia64": {"base": "ia64", "efi": "IA64", "is64": True}
}
@ -162,10 +164,13 @@ class Lorax(BaseLoraxClass):
# do we have all lorax required commands?
self.lcmds = constants.LoraxRequiredCommands()
"""
missing = self.lcmds.get_missing()
if missing:
logger.critical("missing required command: {0}".format(missing))
sys.exit(1)
"""
# do we have a proper yum base object?
logger.info("checking yum base object")
@ -296,10 +301,6 @@ class Lorax(BaseLoraxClass):
logger.info("running depmod")
self.installtree.run_depmod(kernel)
# create gconf
logger.info("creating gconf files")
self.installtree.create_gconf()
# move repos
logger.info("moving anaconda repos")
self.installtree.move_repos()
@ -325,12 +326,12 @@ class Lorax(BaseLoraxClass):
self.outputtree = LoraxOutputTree(self.outputdir, self.installtree,
self.product, self.version)
self.outputtree.prepare()
self.outputtree.get_isolinux()
self.outputtree.get_memtest()
self.outputtree.get_splash()
self.outputtree.get_msg_files()
self.outputtree.get_grub_conf()
#self.outputtree.prepare()
#self.outputtree.get_isolinux()
#self.outputtree.get_memtest()
#self.outputtree.get_splash()
#self.outputtree.get_msg_files()
#self.outputtree.get_grub_conf()
# write .discinfo
discinfo = DiscInfo(self.workdir, self.release, self.basearch)
@ -338,6 +339,7 @@ class Lorax(BaseLoraxClass):
shutil.copy2(discinfo.path, self.outputtree.root)
# move grubefi to workdir
grubefi = joinpaths(self.installtree.root, "boot/efi/EFI/redhat",
"grub.efi")
@ -347,14 +349,37 @@ class Lorax(BaseLoraxClass):
else:
grubefi = None
# move grub splash to workdir
splash = joinpaths(self.installtree.root, "boot/grub/",
"splash.xpm.gz")
shutil.move(splash, self.workdir)
splash = joinpaths(self.workdir, os.path.basename(splash))
if os.path.isfile(splash):
shutil.move(splash, self.workdir)
splash = joinpaths(self.workdir, os.path.basename(splash))
else:
splash = None
# copy kernels to output directory
self.outputtree.get_kernels()
self.outputtree.get_kernels(self.workdir)
# create .treeinfo
treeinfo = TreeInfo(self.workdir, self.product, self.version,
self.variant, self.basearch)
# get the image class
factory = images.Factory()
imgclass = factory.get_class(self.basearch)
i = imgclass(kernellist=self.outputtree.kernels,
installtree=self.installtree,
outputroot=self.outputtree.root,
product=self.product,
version=self.version,
treeinfo=treeinfo,
basearch=self.basearch)
# backup required files
i.backup_required(self.workdir)
# get list of not required packages
logger.info("getting list of not required packages")
@ -394,57 +419,65 @@ class Lorax(BaseLoraxClass):
logger.info("cleaning up python files")
self.installtree.cleanup_python_files()
# create .treeinfo
treeinfo = TreeInfo(self.workdir, self.product, self.version,
self.variant, self.basearch)
# compress install tree (create initrd)
initrds = []
for kernel in self.outputtree.kernels:
suffix = ""
if kernel.ktype == constants.K_PAE:
suffix = "-PAE"
elif kernel.ktype == constants.K_XEN:
suffix = "-XEN"
logger.info("creating the initrd")
i.create_initrd(self.libdir)
fname = "initrd{0}.img".format(suffix)
initrd = DataHolder(fname=fname,
fpath=joinpaths(self.workdir, fname),
itype=kernel.ktype)
logger.info("compressing install tree ({0})".format(kernel.version))
success, elapsed = self.installtree.compress(initrd, kernel)
if not success:
logger.error("error while compressing install tree")
else:
logger.info("took {0:.2f} seconds".format(elapsed))
initrds.append(initrd)
# add kernel and initrd paths to .treeinfo
section = "images-{0}".format("xen" if suffix else self.basearch)
data = {"kernel": "images/pxeboot/{0}".format(kernel.fname)}
treeinfo.add_section(section, data)
data = {"initrd": "images/pxeboot/{0}".format(initrd.fname)}
treeinfo.add_section(section, data)
# copy initrds to outputtree
shutil.copy2(initrds[0].fpath, self.outputtree.isolinuxdir)
# create hard link
source = joinpaths(self.outputtree.isolinuxdir, initrds[0].fname)
link_name = joinpaths(self.outputtree.pxebootdir, initrds[0].fname)
os.link(source, link_name)
for initrd in initrds[1:]:
shutil.copy2(initrd.fpath, self.outputtree.pxebootdir)
#initrds = []
#for kernel in self.outputtree.kernels:
# suffix = ""
# if kernel.ktype == constants.K_PAE:
# suffix = "-PAE"
# elif kernel.ktype == constants.K_XEN:
# suffix = "-XEN"
#
# fname = "initrd{0}.img".format(suffix)
#
# initrd = DataHolder(fname=fname,
# fpath=joinpaths(self.workdir, fname),
# itype=kernel.ktype)
#
# logger.info("compressing install tree ({0})".format(kernel.version))
# success, elapsed = self.installtree.compress(initrd, kernel)
# if not success:
# logger.error("error while compressing install tree")
# else:
# logger.info("took {0:.2f} seconds".format(elapsed))
#
# initrds.append(initrd)
#
# # add kernel and initrd paths to .treeinfo
# section = "images-{0}".format("xen" if suffix else self.basearch)
# data = {"kernel": "images/pxeboot/{0}".format(kernel.fname)}
# treeinfo.add_section(section, data)
# data = {"initrd": "images/pxeboot/{0}".format(initrd.fname)}
# treeinfo.add_section(section, data)
#
## copy initrds to outputtree
#shutil.copy2(initrds[0].fpath, self.outputtree.isolinuxdir)
#
## create hard link
#source = joinpaths(self.outputtree.isolinuxdir, initrds[0].fname)
#link_name = joinpaths(self.outputtree.pxebootdir, initrds[0].fname)
#os.link(source, link_name)
#
#for initrd in initrds[1:]:
# shutil.copy2(initrd.fpath, self.outputtree.pxebootdir)
# create efi images
efiboot = None
if grubefi and self.efiarch not in ("IA32",):
kernel = self.outputtree.kernels[0]
initrd = initrds[0]
# create efibootdir
self.outputtree.efibootdir = joinpaths(self.outputtree.root,
"EFI/BOOT")
os.makedirs(self.outputtree.efibootdir)
# set imgdir
self.outputtree.imgdir = joinpaths(self.outputtree.root,
"images")
kernel = i.kernels[0]
initrd = i.initrds[0]
# create efiboot image with kernel
logger.info("creating efiboot image with kernel")
@ -480,17 +513,19 @@ class Lorax(BaseLoraxClass):
# create boot iso
logger.info("creating boot iso")
bootiso = self.create_bootiso(self.outputtree, efiboot)
if bootiso is None:
logger.critical("unable to create boot iso")
sys.exit(1)
i.create_boot(efiboot)
shutil.move(bootiso, self.outputtree.imgdir)
# add the boot.iso
section = "images-{0}".format(self.basearch)
data = {"boot.iso": "images/{0}".format(os.path.basename(bootiso))}
treeinfo.add_section(section, data)
#bootiso = self.create_bootiso(self.outputtree, efiboot)
#if bootiso is None:
# logger.critical("unable to create boot iso")
# sys.exit(1)
#
#shutil.move(bootiso, self.outputtree.imgdir)
#
## add the boot.iso
#section = "images-{0}".format(self.basearch)
#data = {"boot.iso": "images/{0}".format(os.path.basename(bootiso))}
#treeinfo.add_section(section, data)
treeinfo.write()

View File

@ -51,6 +51,7 @@ class LoraxRequiredCommands(dict):
self["MODINFO"] = "modinfo"
self["MOUNT"] = "mount"
self["PARTED"] = "parted"
self["SSHKEYGEN"] = "ssh-keygen"
self["UMOUNT"] = "umount"
def __getattr__(self, attr):

804
src/pylorax/images.py Normal file
View File

@ -0,0 +1,804 @@
#
# images.py
#
# Copyright (C) 2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import logging
logger = logging.getLogger("pylorax.images")
import os
import subprocess
import shutil
import glob
import collections
from base import DataHolder
from sysutils import joinpaths, cpfile, replace
import constants
##### constants #####
ANABOOTDIR = "usr/share/anaconda/boot"
# ppc
ETCDIR = "etc"
PPCPARENT = "ppc"
CHRPDIR = "ppc/chrp"
IMAGESDIR = "images"
PPC32DIR = "ppc/ppc32"
PPC64DIR = "ppc/ppc64"
MACDIR = "ppc/mac"
NETBOOTDIR = "images/netboot"
MKZIMAGE = "usr/bin/mkzimage"
ZIMAGE_STUB = "usr/share/ppc64-utils/zImage.stub"
WRAPPER = "usr/sbin/wrapper"
ISOPATHDIR = "isopath"
MKISOFS = "mkisofs"
MAPPING = joinpaths(ANABOOTDIR, "mapping")
MAGIC = joinpaths(ANABOOTDIR, "magic")
IMPLANTISOMD5 = "implantisomd5"
# x86
ISOLINUXDIR = "isolinux"
PXEBOOTDIR = "images/pxeboot"
ISOLINUX_BIN = "usr/share/syslinux/isolinux.bin"
SYSLINUX_CFG = "usr/share/anaconda/boot/syslinux.cfg"
ISOHYBRID = "isohybrid"
# s390
INITRD_ADDRESS = "0x02000000"
# sparc
SPARCDIR = "boot"
class PPC(object):
def __init__(self, kernellist, installtree, outputroot, product, version,
treeinfo, basearch):
self.kernellist = kernellist
self.installtree = installtree
self.outputroot = outputroot
self.product = product
self.version = version
self.treeinfo = treeinfo
self.basearch = basearch
self.kernels, self.initrds = [], []
self.reqs = collections.defaultdict(str)
def backup_required(self, workdir):
# yaboot.conf
yabootconf = joinpaths(self.installtree.root, ANABOOTDIR,
"yaboot.conf.in")
self.reqs["yabootconf"] = cpfile(yabootconf, workdir)
# bootinfo.txt
bootinfo_txt = joinpaths(self.installtree.root, ANABOOTDIR,
"bootinfo.txt")
self.reqs["bootinfo_txt"] = cpfile(bootinfo_txt, workdir)
# efika.forth
efika_forth = joinpaths(self.installtree.root, "boot",
"efika.forth")
self.reqs["efika_forth"] = cpfile(efika_forth, workdir)
# yaboot
yaboot = joinpaths(self.installtree.root, "usr/lib/yaboot/yaboot")
self.reqs["yaboot"] = cpfile(yaboot, workdir)
# ofboot.b
ofboot_b = joinpaths(self.installtree.root, ANABOOTDIR, "ofboot.b")
self.reqs["ofboot_b"] = cpfile(ofboot_b, workdir)
# yaboot.conf.3264
yabootconf3264 = joinpaths(self.installtree.root, ANABOOTDIR,
"yaboot.conf.3264")
self.reqs["yabootconf3264"] = cpfile(yabootconf3264, workdir)
def create_initrd(self, libdir):
# create directories
logger.info("creating required directories")
os.makedirs(joinpaths(self.outputroot, ETCDIR))
os.makedirs(joinpaths(self.outputroot, PPCPARENT))
os.makedirs(joinpaths(self.outputroot, CHRPDIR))
os.makedirs(joinpaths(self.outputroot, IMAGESDIR))
# set up biarch test
ppc32dir = joinpaths(self.outputroot, PPC32DIR)
ppc64dir = joinpaths(self.outputroot, PPC64DIR)
biarch = lambda: (os.path.exists(ppc32dir) and
os.path.exists(ppc64dir))
# create images
for kernel in self.kernellist:
# set up bits
kernel_arch = kernel.version.split(".")[-1]
if (kernel_arch == "ppc"):
bits = 32
ppcdir = PPC32DIR
fakearch = "ppc"
elif (kernel_arch == "ppc64"):
bits = 64
ppcdir = PPC64DIR
fakearch = ""
else:
raise Exception("unknown kernel arch {0}".format(kernel_arch))
# create ppc dir
os.makedirs(joinpaths(self.outputroot, ppcdir))
# create mac dir
os.makedirs(joinpaths(self.outputroot, MACDIR))
# create netboot dir
os.makedirs(joinpaths(self.outputroot, NETBOOTDIR))
# copy kernel
logger.info("copying kernel image")
kernel.fname = "vmlinuz"
dst = joinpaths(self.outputroot, ppcdir, kernel.fname)
kernel.fpath = cpfile(kernel.fpath, dst)
# create and copy initrd
initrd = DataHolder()
initrd.fname = "ramdisk.image.gz"
initrd.fpath = joinpaths(self.outputroot, ppcdir, initrd.fname)
initrd.itype = kernel.ktype
logger.info("compressing the install tree")
self.installtree.compress(initrd, kernel)
# add kernel and initrd to the list
self.kernels.append(kernel)
self.initrds.append(initrd)
# add kernel and initrd to .treeinfo
section = "images-{0}".format(kernel_arch)
data = {"kernel": joinpaths(ppcdir, kernel.fname)}
self.treeinfo.add_section(section, data)
data = {"initrd": joinpaths(ppcdir, initrd.fname)}
self.treeinfo.add_section(section, data)
# copy yaboot.conf
dst = joinpaths(self.outputroot, ppcdir, "yaboot.conf")
yabootconf = cpfile(self.reqs["yabootconf"], dst)
replace(yabootconf, r"%BITS%", str(bits))
replace(yabootconf, r"%PRODUCT%", self.product)
replace(yabootconf, r"%VERSION%", self.version)
mkzimage = joinpaths(self.installtree.root, MKZIMAGE)
zimage_stub = joinpaths(self.installtree.root, ZIMAGE_STUB)
wrapper = joinpaths(self.installtree.root, WRAPPER)
# XXX
wrapper_a = joinpaths(self.installtree.root,
"usr/%s/kernel-wrapper/wrapper.a" % libdir)
ppc_img_fname = "ppc{0}.img".format(bits)
ppc_img_fpath = joinpaths(self.outputroot, NETBOOTDIR,
ppc_img_fname)
if (os.path.exists(mkzimage) and os.path.exists(zimage_stub)):
logger.info("creating the z image")
# XXX copy zImage.lds
zimage_lds = joinpaths(self.installtree.root,
"usr/%s/kernel-wrapper/zImage.lds" % libdir)
zimage_lds = cpfile(zimage_lds,
joinpaths(self.outputroot, ppcdir))
# change current working directory
cwd = os.getcwd()
os.chdir(joinpaths(self.outputroot, ppcdir))
# run mkzimage
cmd = [mkzimage, kernel.fpath, "no", "no", initrd.fpath,
zimage_stub, ppc_img_fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# remove zImage.lds
os.unlink(zimage_lds)
# return to former working directory
os.chdir(cwd)
elif (os.path.exists(wrapper) and os.path.exists(wrapper_a)):
logger.info("running kernel wrapper")
# run wrapper
cmd = [wrapper, "-o", ppc_img_fpath, "-i", initrd.fpath,
"-D", os.path.dirname(wrapper_a), kernel.fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
if os.path.exists(ppc_img_fpath):
# add ppc image to .treeinfo
section = "images-{0}".format(kernel_arch)
data = {"zimage": joinpaths(NETBOOTDIR, ppc_img_fname)}
self.treeinfo.add_section(section, data)
if (bits == 32):
# set up prepboot
p = joinpaths(NETBOOTDIR, ppc_img_fname)
prepboot = ["-prep-boot {0}".format(p)]
# remove netboot dir if empty
try:
os.rmdir(joinpaths(self.outputroot, NETBOOTDIR))
except OSError:
pass
# copy bootinfo.txt
cpfile(self.reqs["bootinfo_txt"],
joinpaths(self.outputroot, PPCPARENT))
# copy efika.forth
cpfile(self.reqs["efika_forth"],
joinpaths(self.outputroot, PPCPARENT))
# copy yaboot to chrp dir
yaboot = cpfile(self.reqs["yaboot"],
joinpaths(self.outputroot, CHRPDIR))
if (os.path.exists(joinpaths(self.outputroot, MACDIR))):
# copy yaboot and ofboot.b to mac dir
cpfile(yaboot, joinpaths(self.outputroot, MACDIR))
cpfile(self.reqs["ofboot_b"], joinpaths(self.outputroot, MACDIR))
# set up macboot
p = joinpaths(self.outputroot, ISOPATHDIR, MACDIR)
macboot = ["-hfs-volid {0}".format(self.version),
"-hfs-bless {0}".format(p)]
# add note to yaboot
cmd = [joinpaths(self.installtree.root, "usr/lib/yaboot/addnote"),
yaboot]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# copy yaboot.conf to etc dir
if biarch():
yabootconf = cpfile(self.reqs["yabootconf3264"],
joinpaths(self.outputroot, ETCDIR,
"yaboot.conf"))
replace(yabootconf, r"%BITS%", "32")
replace(yabootconf, r"%PRODUCT%", self.product)
replace(yabootconf, r"%VERSION%", self.version)
else:
cpfile(joinpaths(self.outputroot, ppcdir, "yaboot.conf"),
joinpaths(self.outputroot, ETCDIR))
def create_boot(self, efiboot=None):
# create isopath dir
isopathdir = joinpaths(self.outputroot, ISOPATHDIR)
os.makedirs(isopathdir)
# copy etc dir and ppc dir to isopath dir
shutil.copytree(joinpaths(self.outputroot, ETCDIR),
joinpaths(isopathdir, ETCDIR))
shutil.copytree(joinpaths(self.outputroot, PPCPARENT),
joinpaths(isopathdir, PPCPARENT))
if (os.path.exists(joinpaths(self.outputroot, NETBOOTDIR))):
# create images dir in isopath dir if we have ppc images
imagesdir = joinpaths(isopathdir, IMAGESDIR)
os.makedirs(imagesdir)
# copy netboot dir to images dir
shutil.copytree(joinpaths(self.outputroot, NETBOOTDIR),
joinpaths(imagesdir, os.path.basename(NETBOOTDIR)))
# define prepboot and macboot
prepboot = [] if "prepboot" not in locals() else locals()["prepboot"]
macboot = [] if "macboot" not in locals() else locals()["macboot"]
# create boot image
boot_fpath = joinpaths(self.outputroot, IMAGESDIR, "boot.iso")
# run mkisofs
cmd = [MKISOFS, "-o", boot_fpath, "-chrp-boot", "-U"] + prepboot + \
["-part", "-hfs", "-T", "-r", "-l", "-J", "-A",
'"%s %s"' % (self.product, self.version),
"-sysid", "PPC", "-V", '"PBOOT"',
"-volset", '"%s"' % self.version, "-volset-size", "1",
"-volset-seqno", "1"] + macboot + \
["-map", joinpaths(self.installtree.root, MAPPING),
"-magic", joinpaths(self.installtree.root, MAGIC),
"-no-desktop", "-allow-multidot", "-graft-points", isopathdir]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# run implantisomd5
cmd = [IMPLANTISOMD5, boot_fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# remove isopath dir
shutil.rmtree(isopathdir)
class X86(object):
def __init__(self, kernellist, installtree, outputroot, product, version,
treeinfo, basearch):
self.kernellist = kernellist
self.installtree = installtree
self.outputroot = outputroot
self.product = product
self.version = version
self.treeinfo = treeinfo
self.basearch = basearch
self.kernels, self.initrds = [], []
self.reqs = collections.defaultdict(str)
def backup_required(self, workdir):
# isolinux.bin
isolinux_bin = joinpaths(self.installtree.root, ISOLINUX_BIN)
if not os.path.exists(isolinux_bin):
raise Exception("isolinux.bin not present")
self.reqs["isolinux_bin"] = cpfile(isolinux_bin, workdir)
# syslinux.cfg
syslinux_cfg = joinpaths(self.installtree.root, SYSLINUX_CFG)
self.reqs["syslinux_cfg"] = cpfile(syslinux_cfg, workdir)
# memtest
memtest = glob.glob(joinpaths(self.installtree.root, "boot",
"memtest*"))
if memtest:
self.reqs["memtest"] = cpfile(memtest[-1],
joinpaths(workdir, "memtest"))
# *.msg files
msgfiles = glob.glob(joinpaths(self.installtree.root, ANABOOTDIR,
"*.msg"))
if not msgfiles:
raise Exception("message files not present")
self.reqs["msgfiles"] = []
for src in msgfiles:
self.reqs["msgfiles"].append(cpfile(src, workdir))
# splash
splash = joinpaths(self.installtree.root, ANABOOTDIR,
"syslinux-vesa-splash.jpg")
if not splash:
raise Exception("syslinux-vesa-splash.jpg not present")
self.reqs["splash"] = cpfile(splash, workdir)
# vesamenu.c32
vesamenu = joinpaths(self.installtree.root,
"usr/share/syslinux/vesamenu.c32")
self.reqs["vesamenu"] = cpfile(vesamenu, workdir)
# grub.conf
grubconf = joinpaths(self.installtree.root, ANABOOTDIR, "grub.conf")
self.reqs["grubconf"] = cpfile(grubconf, workdir)
def create_initrd(self, libdir):
# create directories
logger.info("creating required directories")
os.makedirs(joinpaths(self.outputroot, ISOLINUXDIR))
os.makedirs(joinpaths(self.outputroot, PXEBOOTDIR))
# copy isolinux.bin to isolinux dir
cpfile(self.reqs["isolinux_bin"],
joinpaths(self.outputroot, ISOLINUXDIR))
# copy syslinux.cfg to isolinux dir (XXX rename to isolinux.cfg)
isolinux_cfg = cpfile(self.reqs["syslinux_cfg"],
joinpaths(self.outputroot, ISOLINUXDIR,
"isolinux.cfg"))
replace(isolinux_cfg, r"@PRODUCT@", self.product)
replace(isolinux_cfg, r"@VERSION@", self.version)
# copy memtest
if self.reqs["memtest"]:
cpfile(self.reqs["memtest"],
joinpaths(self.outputroot, ISOLINUXDIR))
with open(isolinux_cfg, "a") as f:
f.write("label memtest86\n")
f.write(" menu label ^Memory test\n")
f.write(" kernel memtest\n")
f.write(" append -\n")
# copy *.msg files
for src in self.reqs["msgfiles"]:
dst = cpfile(src, joinpaths(self.outputroot, ISOLINUXDIR))
replace(dst, r"@VERSION@", self.version)
# copy syslinux-vesa-splash.jpg
splash = cpfile(self.reqs["splash"],
joinpaths(self.outputroot, ISOLINUXDIR, "splash.jpg"))
# copy vesamenu.c32
cpfile(self.reqs["vesamenu"],
joinpaths(self.outputroot, ISOLINUXDIR))
# set up isolinux.cfg
replace(isolinux_cfg, r"default linux", "default vesamenu.c32")
replace(isolinux_cfg, r"prompt 1", "#prompt 1")
# copy grub.conf
grubconf = cpfile(self.reqs["grubconf"],
joinpaths(self.outputroot, ISOLINUXDIR))
replace(grubconf, r"@PRODUCT@", self.product)
replace(grubconf, r"@VERSION@", self.version)
# create images
for kernel in self.kernellist:
# set up file names
suffix = ""
if (kernel.ktype == constants.K_PAE):
suffix = "-PAE"
elif (kernel.ktype == constants.K_XEN):
suffix = "-XEN"
logger.info("copying kernel image")
kernel.fname = "vmlinuz{0}".format(suffix)
if not suffix:
# copy kernel to isolinux dir
kernel.fpath = cpfile(kernel.fpath,
joinpaths(self.outputroot, ISOLINUXDIR,
kernel.fname))
# create link in pxeboot dir
os.link(kernel.fpath,
joinpaths(self.outputroot, PXEBOOTDIR, kernel.fname))
else:
# copy kernel to pxeboot dir
kernel.fpath = cpfile(kernel.fpath,
joinpaths(self.outputroot, PXEBOOTDIR,
kernel.fname))
# create and copy initrd to pxeboot dir
initrd = DataHolder()
initrd.fname = "initrd{0}.img".format(suffix)
initrd.fpath = joinpaths(self.outputroot, PXEBOOTDIR, initrd.fname)
initrd.itype = kernel.ktype
logger.info("compressing the install tree")
self.installtree.compress(initrd, kernel)
# add kernel and initrd to the list
self.kernels.append(kernel)
self.initrds.append(initrd)
if not suffix:
# create link in isolinux dir
os.link(initrd.fpath,
joinpaths(self.outputroot, ISOLINUXDIR, initrd.fname))
# add kernel and initrd to .treeinfo
section = "images-{0}".format("xen" if suffix else self.basearch)
data = {"kernel": joinpaths(PXEBOOTDIR, kernel.fname)}
self.treeinfo.add_section(section, data)
data = {"initrd": joinpaths(PXEBOOTDIR, initrd.fname)}
self.treeinfo.add_section(section, data)
if not suffix:
# add boot.iso to .treeinfo
data = {"boot.iso": joinpaths(IMAGESDIR, "boot.iso")}
self.treeinfo.add_section(section, data)
# create images-xen section on x86_64
if self.basearch == "x86_64":
section = "images-xen"
data = {"kernel": joinpaths(PXEBOOTDIR, kernel.fname)}
self.treeinfo.add_section(section, data)
data = {"initrd": joinpaths(PXEBOOTDIR, initrd.fname)}
self.treeinfo.add_section(section, data)
def create_boot(self, efiboot=None):
# define efiargs and efigraft
efiargs, efigraft = [], []
if efiboot:
efiargs = ["-eltorito-alt-boot", "-e",
joinpaths(IMAGESDIR, "efiboot.img"), "-no-emul-boot"]
efigraft = ["EFI/BOOT={0}/EFI/BOOT".format(self.outputroot)]
# create boot image
boot_fpath = joinpaths(self.outputroot, IMAGESDIR, "boot.iso")
# run mkisofs
cmd = [MKISOFS, "-v", "-o", boot_fpath, "-b",
"{0}/isolinux.bin".format(ISOLINUXDIR), "-c",
"{0}/boot.cat".format(ISOLINUXDIR), "-no-emul-boot",
"-boot-load-size", "4", "-boot-info-table"] + efiargs + \
["-R", "-J", "-V", "'{0}'".format(self.product), "-T",
"-graft-points",
"isolinux={0}".format(joinpaths(self.outputroot, ISOLINUXDIR)),
"images={0}".format(joinpaths(self.outputroot, IMAGESDIR))] + \
efigraft
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
if os.path.exists(ISOHYBRID):
# run isohybrid
cmd = [ISOHYBRID, boot_fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# run implantisomd5
cmd = [IMPLANTISOMD5, boot_fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
class S390(object):
def __init__(self, kernellist, installtree, outputroot, product, version,
treeinfo, basearch):
self.kernellist = kernellist
self.installtree = installtree
self.outputroot = outputroot
self.product = product
self.version = version
self.treeinfo = treeinfo
self.basearch = basearch
self.kernels, self.initrds = [], []
self.reqs = collections.defaultdict(str)
def backup_required(self, workdir):
pass
def create_initrd(self, libdir):
# create directories
os.makedirs(joinpaths(self.outputroot, IMAGESDIR))
# copy redhat.exec
cpfile(joinpaths(self.installtree.root, ANABOOTDIR, "redhat.exec"),
joinpaths(self.outputroot, IMAGESDIR))
# copy generic.prm
generic_prm = cpfile(joinpaths(self.installtree.root, ANABOOTDIR,
"generic.prm"),
joinpaths(self.outputroot, IMAGESDIR))
# copy generic.ins
generic_ins = cpfile(joinpaths(self.installtree.root, ANABOOTDIR,
"generic.ins"), self.outputroot)
replace(generic_ins, r"@INITRD_LOAD_ADDRESS@", INITRD_ADDRESS)
for kernel in self.kernellist:
# copy kernel
kernel.fname = "kernel.img"
kernel.fpath = cpfile(kernel.fpath,
joinpaths(self.outputroot, IMAGESDIR,
kernel.fname))
# create and copy initrd
initrd = DataHolder()
initrd.fname = "initrd.img"
initrd.fpath = joinpaths(self.outputroot, IMAGESDIR, initrd.fname)
logger.info("compressing the install tree")
self.installtree.compress(initrd, kernel)
# run addrsize
addrsize = joinpaths(self.installtree.root, "usr/libexec",
"anaconda", "addrsize")
cmd = [addrsize, INITRD_ADDRESS, initrd.fpath,
joinpaths(self.outputroot, IMAGESDIR, "initrd_addrsize")]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# add kernel and initrd to .treeinfo
kernel_arch = kernel.version.split(".")[-1]
section = "images-{0}".format(kernel_arch)
data = {"kernel": joinpaths(IMAGESDIR, kernel.fname),
"initrd": joinpaths(IMAGESDIR, initrd.fname),
"initrd.addrsize": joinpaths(IMAGESDIR, "initrd_addrsize"),
"generic.prm": joinpaths(IMAGESDIR,
os.path.basename(generic_prm)),
"generic.ins": os.path.basename(generic_ins)}
self.treeinfo.add_section(section, data)
# create cdboot.img
bootiso_fpath = joinpaths(self.outputroot, IMAGESDIR, "cdboot.img")
# run mks390cdboot
mks390cdboot = joinpaths(self.installtree.root, "usr/libexec",
"anaconda", "mk-s390-cdboot")
cmd = [mks390cdboot, "-i", kernel.fpath, "-r", initrd.fpath,
"-p", generic_prm, "-o", bootiso_fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# add cdboot.img to treeinfo
data = {"cdboot.img": joinpaths(IMAGESDIR, "cdboot.img")}
self.treeinfo.add_section(section, data)
def create_boot(self, efiboot=None):
pass
class SPARC(object):
def __init__(self, kernellist, installtree, outputroot, product, version,
treeinfo, basearch):
self.kernellist = kernellist
self.installtree = installtree
self.outputroot = outputroot
self.product = product
self.version = version
self.treeinfo = treeinfo
self.basearch = basearch
self.kernels, self.initrds = [], []
self.reqs = collections.defaultdict(str)
def backup_required(self, workdir):
os.makedirs(joinpaths(workdir, "bfiles"))
for fname in glob.glob(joinpaths(self.installtree.root, "boot/*.b")):
cpfile(fname, joinpaths(workdir, "bfiles"))
self.reqs["bfiles"] = glob.glob(joinpaths(workdir, "bfiles/*.b"))
def create_initrd(self, libdir):
# create directories
os.makedirs(joinpaths(self.outputroot, IMAGESDIR))
os.makedirs(joinpaths(self.outputroot, SPARCDIR))
# copy silo.conf
siloconf = cpfile(joinpaths(self.installtree.root, ANABOOTDIR,
"silo.conf"),
joinpaths(self.outputroot, SPARCDIR))
# copy boot.msg
bootmsg = cpfile(joinpaths(self.installtree.root, ANABOOTDIR,
"boot.msg"),
joinpaths(self.outputroot, SPARCDIR))
replace(bootmsg, r"%PRODUCT%", self.product)
replace(bootmsg, r"%VERSION%", self.version)
# copy *.b to sparc dir
for fname in self.reqs["bfiles"]:
cpfile(fname, joinpaths(self.outputroot, SPARCDIR))
# create images
for kernel in self.kernellist:
# copy kernel
kernel.fname = "vmlinuz"
kernel.fpath = cpfile(kernel.fpath,
joinpaths(self.outputroot, SPARCDIR,
kernel.fname))
# create and copy initrd
initrd = DataHolder()
initrd.fname = "initrd.img"
initrd.fpath = joinpaths(self.outputroot, SPARCDIR, initrd.fname)
logger.info("compressing the install tree")
self.installtree.compress(initrd, kernel)
# add kernel and initrd to .treeinfo
kernel_arch = kernel.version.split(".")[-1]
section = "images-{0}".format(kernel_arch)
data = {"kernel": joinpaths(SPARCDIR, kernel.fname),
"initrd":joinpaths(SPARCDIR, initrd.fname)}
self.treeinfo.add_section(section, data)
def create_boot(self, efiboot=None):
# create isopath dir
isopathdir = joinpaths(self.outputroot, ISOPATHDIR)
os.makedirs(isopathdir)
# copy sparc dir to isopath dir
shutil.copytree(joinpaths(self.outputroot, SPARCDIR),
joinpaths(isopathdir, SPARCDIR))
# create boot.iso
bootiso_fpath = joinpaths(self.outputroot, IMAGESDIR, "boot.iso")
# run mkisofs (XXX what's with the "Fedora" exclude?)
cmd = [MKISOFS, "-R", "-J", "-T",
"-G", "/%s" % joinpaths(SPARCDIR, "isofs.b"),
"-B", "...",
"-s", "/%s" % joinpaths(SPARCDIR, "silo.conf"),
"-r", "-V", '"PBOOT"', "-A",
'"%s %s"' % (self.product, self.version),
"-x", "Fedora", "-x", "repodata", "-sparc-label",
'"%s %s Boot Disc"' % (self.product, self.version),
"-o", bootiso_fpath, "-graft-points",
"boot=%s" % joinpaths(self.outputroot, SPARCDIR)]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# run implantisomd5
cmd = [IMPLANTISOMD5, bootiso_fpath]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p.wait()
# remove isopath dir
shutil.rmtree(isopathdir)
class Factory(object):
DISPATCH_MAP = {"ppc": PPC,
"i386": X86,
"x86_64": X86,
"s390": S390,
"s390x": S390,
"sparc": SPARC}
def __init__(self):
pass
def get_class(self, arch):
if arch in self.DISPATCH_MAP:
return self.DISPATCH_MAP[arch]
else:
raise Exception("no support for {0}".format(arch))

292
src/pylorax/imgutils.py Normal file
View File

@ -0,0 +1,292 @@
# imgutils.py - utility functions/classes for building disk images
#
# Copyright (C) 2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Author(s): Will Woods <wwoods@redhat.com>
import logging
logger = logging.getLogger("pylorax.imgutils")
import os, tempfile
from os.path import join, dirname
from pylorax.sysutils import cpfile
from subprocess import *
import traceback
######## Functions for making container images (cpio, squashfs) ##########
def mkcpio(rootdir, outfile, compression="xz", compressargs=["-9"]):
'''Make a compressed CPIO archive of the given rootdir.
compression should be "xz", "gzip", "lzma", or None.
compressargs will be used on the compression commandline.'''
if compression not in (None, "xz", "gzip", "lzma"):
raise ValueError, "Unknown compression type %s" % compression
chdir = lambda: os.chdir(rootdir)
if compression == "xz":
compressargs.insert(0, "--check=crc32")
if compression is None:
compression = "cat" # this is a little silly
compressargs = []
find = Popen(["find", ".", "-print0"], stdout=PIPE, preexec_fn=chdir)
cpio = Popen(["cpio", "--null", "--quiet", "-H", "newc", "-o"],
stdin=find.stdout, stdout=PIPE, preexec_fn=chdir)
comp = Popen([compression] + compressargs,
stdin=cpio.stdout, stdout=open(outfile, "wb"))
comp.wait()
return comp.returncode
def mksquashfs(rootdir, outfile, compression="default", compressargs=[]):
'''Make a squashfs image containing the given rootdir.'''
if compression != "default":
compressargs = ["-comp", compression] + compressargs
return call(["mksquashfs", rootdir, outfile] + compressargs)
######## Utility functions ###############################################
def mksparse(outfile, size):
'''use os.ftruncate to create a sparse file of the given size.'''
fobj = open(outfile, "w")
os.ftruncate(fobj.fileno(), size)
def loop_attach(outfile):
'''Attach a loop device to the given file. Return the loop device name.
Raises CalledProcessError if losetup fails.'''
dev = check_output(["losetup", "--find", "--show", outfile], stderr=PIPE)
return dev.strip()
def loop_detach(loopdev):
'''Detach the given loop device. Return False on failure.'''
return (call(["losetup", "--detach", loopdev]) == 0)
def dm_attach(dev, size, name=None):
'''Attach a devicemapper device to the given device, with the given size.
If name is None, a random name will be chosen. Returns the device name.
raises CalledProcessError if dmsetup fails.'''
if name is None:
name = tempfile.mktemp(prefix="lorax.imgutils.", dir="")
check_call(["dmsetup", "create", name, "--table",
"0 %i linear %s 0" % (size/512, dev)],
stdout=PIPE, stderr=PIPE)
return name
def dm_detach(dev):
'''Detach the named devicemapper device. Returns False if dmsetup fails.'''
dev = dev.replace("/dev/mapper/", "") # strip prefix, if it's there
return call(["dmsetup", "remove", dev], stdout=PIPE, stderr=PIPE)
def mount(dev, opts="", mnt=None):
'''Mount the given device at the given mountpoint, using the given opts.
opts should be a comma-separated string of mount options.
if mnt is none, a temporary directory will be created and its path will be
returned.
raises CalledProcessError if mount fails.'''
if mnt is None:
mnt = tempfile.mkdtemp(prefix="lorax.imgutils.")
mount = ["mount"]
if opts:
mount += ["-o", opts]
check_call(mount + [dev, mnt])
return mnt
def umount(mnt):
'''Unmount the given mountpoint. If the mount was a temporary dir created
by mount, it will be deleted. Returns false if the unmount fails.'''
rv = call(["umount", mnt])
if 'lorax.imgutils' in mnt:
os.rmdir(mnt)
return (rv == 0)
def copytree(src, dest, preserve=True):
'''Copy a tree of files using cp -a, thus preserving modes, timestamps,
links, acls, sparse files, xattrs, selinux contexts, etc.
If preserve is False, uses cp -R (useful for modeless filesystems)'''
chdir = lambda: os.chdir(src)
cp = ["cp", "-a"] if preserve else ["cp", "-R", "-L"]
check_call(cp + [".", os.path.abspath(dest)], preexec_fn=chdir)
def do_grafts(grafts, dest, preserve=True):
'''Copy each of the items listed in grafts into dest.
If the key ends with '/' it's assumed to be a directory which should be
created, otherwise just the leading directories will be created.'''
for imgpath, filename in grafts.items():
if imgpath[-1] == '/':
targetdir = join(dest, imgpath)
imgpath = imgpath[:-1]
else:
targetdir = join(dest, dirname(imgpath))
if not os.path.isdir(targetdir):
os.makedirs(targetdir)
if os.path.isdir(filename):
copytree(filename, join(dest, imgpath), preserve)
else:
cpfile(filename, join(dest, imgpath))
def round_to_blocks(size, blocksize):
'''If size isn't a multiple of blocksize, round up to the next multiple'''
diff = size % blocksize
if diff or not size:
size += blocksize - diff
return size
# TODO: move filesystem data outside this function
def estimate_size(rootdir, graft={}, fstype=None, blocksize=4096, overhead=128):
getsize = lambda f: os.lstat(f).st_size
if fstype == "btrfs":
overhead = 64*1024 # don't worry, it's all sparse
if fstype in ("vfat", "msdos"):
blocksize = 2048
getsize = lambda f: os.stat(f).st_size # no symlinks, count as copies
total = overhead*blocksize
dirlist = graft.values()
if rootdir:
dirlist.append(rootdir)
for root in dirlist:
for top, dirs, files in os.walk(root):
for f in files + dirs:
total += round_to_blocks(getsize(join(top,f)), blocksize)
if fstype == "btrfs":
total = max(256*1024*1024, total) # btrfs minimum size: 256MB
return total
######## Execution contexts - use with the 'with' statement ##############
class LoopDev(object):
def __init__(self, filename, size=None):
self.filename = filename
if size:
mksparse(self.filename, size)
def __enter__(self):
self.loopdev = loop_attach(self.filename)
return self.loopdev
def __exit__(self, exc_type, exc_value, traceback):
loop_detach(self.loopdev)
class DMDev(object):
def __init__(self, dev, size, name=None):
(self.dev, self.size, self.name) = (dev, size, name)
def __enter__(self):
self.mapperdev = dm_attach(self.dev, self.size, self.name)
return self.mapperdev
def __exit__(self, exc_type, exc_value, traceback):
dm_detach(self.mapperdev)
class Mount(object):
def __init__(self, dev, opts="", mnt=None):
(self.dev, self.opts, self.mnt) = (dev, opts, mnt)
def __enter__(self):
self.mnt = mount(self.dev, self.opts, self.mnt)
return self.mnt
def __exit__(self, exc_type, exc_value, traceback):
umount(self.mnt)
class PartitionMount(object):
""" Mount a partitioned image file using kpartx """
def __init__(self, disk_img, mount_ok=None):
"""
disk_img is the full path to a partitioned disk image
mount_ok is a function that is passed the mount point and
returns True if it should be mounted.
"""
self.mount_dir = None
self.disk_img = disk_img
self.mount_ok = mount_ok
# Default is to mount partition with /etc/passwd
if not self.mount_ok:
self.mount_ok = lambda mount_dir: os.path.isfile(mount_dir+"/etc/passwd")
# Example kpartx output
# kpartx -p p -v -a /tmp/diskV2DiCW.im
# add map loop2p1 (253:2): 0 3481600 linear /dev/loop2 2048
# add map loop2p2 (253:3): 0 614400 linear /dev/loop2 3483648
cmd = [ "kpartx", "-v", "-p", "p", "-a", self.disk_img ]
logger.debug(cmd)
kpartx_output = check_output(cmd)
logger.debug(kpartx_output)
# list of (deviceName, sizeInBytes)
self.loop_devices = []
for line in kpartx_output.splitlines():
# add map loop2p3 (253:4): 0 7139328 linear /dev/loop2 528384
# 3rd element is size in 512 byte blocks
if line.startswith("add map "):
fields = line[8:].split()
self.loop_devices.append( (fields[0], int(fields[3])*512) )
def __enter__(self):
# Mount the device selected by mount_ok, if possible
mount_dir = tempfile.mkdtemp()
for dev, size in self.loop_devices:
try:
mount( "/dev/mapper/"+dev, mnt=mount_dir )
if self.mount_ok(mount_dir):
self.mount_dir = mount_dir
self.mount_dev = dev
self.mount_size = size
break
umount( mount_dir )
except CalledProcessError:
logger.debug(traceback.format_exc())
if self.mount_dir:
logger.info("Partition mounted on {0} size={1}".format(self.mount_dir, self.mount_size))
else:
logger.debug("Unable to mount anything from {0}".format(self.disk_img))
os.rmdir(mount_dir)
return self
def __exit__(self, exc_type, exc_value, traceback):
if self.mount_dir:
umount( self.mount_dir )
os.rmdir(self.mount_dir)
self.mount_dir = None
call(["kpartx", "-d", self.disk_img])
######## Functions for making filesystem images ##########################
def mkfsimage(fstype, rootdir, outfile, size=None, mkfsargs=[], mountargs="", graft={}):
'''Generic filesystem image creation function.
fstype should be a filesystem type - "mkfs.${fstype}" must exist.
graft should be a dict: {"some/path/in/image": "local/file/or/dir"};
if the path ends with a '/' it's assumed to be a directory.
Will raise CalledProcessError if something goes wrong.'''
preserve = (fstype not in ("msdos", "vfat"))
if not size:
size = estimate_size(rootdir, graft, fstype)
with LoopDev(outfile, size) as loopdev:
check_call(["mkfs.%s" % fstype] + mkfsargs + [loopdev],
stdout=PIPE, stderr=PIPE)
with Mount(loopdev, mountargs) as mnt:
if rootdir:
copytree(rootdir, mnt, preserve)
do_grafts(graft, mnt, preserve)
# convenience functions with useful defaults
def mkdosimg(rootdir, outfile, size=None, label="", mountargs="shortname=winnt,umask=0077", graft={}):
mkfsimage("msdos", rootdir, outfile, size, mountargs=mountargs,
mkfsargs=["-n", label], graft=graft)
def mkext4img(rootdir, outfile, size=None, label="", mountargs="", graft={}):
mkfsimage("ext4", rootdir, outfile, size, mountargs=mountargs,
mkfsargs=["-L", label, "-b", "1024", "-m", "0"], graft=graft)
def mkbtrfsimg(rootdir, outfile, size=None, label="", mountargs="", graft={}):
mkfsimage("btrfs", rootdir, outfile, size, mountargs=mountargs,
mkfsargs=["-L", label], graft=graft)
def mkhfsimg(rootdir, outfile, size=None, label="", mountargs="", graft={}):
mkfsimage("hfsplus", rootdir, outfile, size, mountargs=mountargs,
mkfsargs=["-v", label], graft=graft)

View File

@ -26,6 +26,7 @@ import sys
import os
import shutil
import gzip
import lzma
import re
import glob
import time
@ -102,6 +103,10 @@ class LoraxInstallTree(BaseLoraxClass):
shutil.move(langtable, joinpaths(self.root, "etc"))
def create_keymaps(self):
if self.basearch in ("s390", "s390x"):
# skip on s390
return True
keymaps = joinpaths(self.root, "etc/keymaps.gz")
# look for override
@ -112,7 +117,7 @@ class LoraxInstallTree(BaseLoraxClass):
shutil.move(override, keymaps)
else:
# create keymaps
cmd = [joinpaths(self.root, "usr/share/anaconda", "getkeymaps"),
cmd = [joinpaths(self.root, "usr/libexec/anaconda", "getkeymaps"),
self.basearch, keymaps, self.root]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
proc.wait()
@ -346,30 +351,6 @@ class LoraxInstallTree(BaseLoraxClass):
# move modules out of the tree
shutil.move(moddir, self.workdir)
def create_gconf(self):
gconfdir = joinpaths(self.root, ".gconf/desktop")
os.makedirs(gconfdir)
touch(joinpaths(gconfdir, "%gconf.xml"))
gconfdir = joinpaths(gconfdir, "gnome")
os.mkdir(gconfdir)
touch(joinpaths(gconfdir, "%gconf.xml"))
gconfdir = joinpaths(gconfdir, "interface")
os.mkdir(gconfdir)
text = """<?xml version="1.0"?>
<gconf>
<entry name="accessibility" mtime="1176200664" type="bool" value="true">
</entry>
<entry name="at-spi-corba" mtime="1176200664" type="bool" value="true">
</entry>
</gconf>
"""
with open(joinpaths(gconfdir, "%gconf.xml"), "w") as fobj:
fobj.write(text)
def move_repos(self):
src = joinpaths(self.root, "etc/yum.repos.d")
dst = joinpaths(self.root, "etc/anaconda.repos.d")
@ -382,11 +363,24 @@ class LoraxInstallTree(BaseLoraxClass):
fobj.write(text)
def misc_tree_modifications(self):
# replace init with anaconda init
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "init")
dst = joinpaths(self.root, "sbin", "init")
os.unlink(dst)
shutil.copy2(src, dst)
if self.basearch in ("s390", "s390x"):
# copy shutdown
src = joinpaths(self.root, "usr", self.libdir, "anaconda/shutdown")
dst = joinpaths(self.root, "sbin", "shutdown")
os.unlink(dst)
shutil.copy2(src, dst)
# copy linuxrc.s390
src = joinpaths(self.root, "usr/share/anaconda/linuxrc.s390")
dst = joinpaths(self.root, "sbin", "init")
os.unlink(dst)
shutil.copy2(src, dst)
else:
# replace init with anaconda init
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "init")
dst = joinpaths(self.root, "sbin", "init")
os.unlink(dst)
shutil.copy2(src, dst)
# init symlinks
target = "/sbin/init"
@ -398,7 +392,7 @@ class LoraxInstallTree(BaseLoraxClass):
os.unlink(name)
os.symlink("init", name)
for fname in ["runlevel", "shutdown", "telinit"]:
for fname in ["runlevel", "telinit"]:
name = joinpaths(self.root, "sbin", fname)
os.unlink(name)
@ -419,11 +413,20 @@ class LoraxInstallTree(BaseLoraxClass):
[("/apps/metacity/general/button_layout", "string", ":"),
("/apps/metacity/general/action_right_click_titlebar",
"string", "none"),
("/apps/metacity/general/num_workspaces", "int", "1"),
("/apps/metacity/window_keybindings/close", "string", "disabled"),
("/apps/metacity/global_keybindings/run_command_window_screenshot",
"string", "disabled"),
("/apps/metacity/global_keybindings/run_command_screenshot",
"string", "disabled"),
("/apps/metacity/global_keybindings/switch_to_workspace_down",
"string", "disabled"),
("/apps/metacity/global_keybindings/switch_to_workspace_left",
"string", "disabled"),
("/apps/metacity/global_keybindings/switch_to_workspace_right",
"string", "disabled"),
("/apps/metacity/global_keybindings/switch_to_workspace_up",
"string", "disabled"),
("/desktop/gnome/interface/accessibility", "bool", "true"),
("/desktop/gnome/interface/at-spi-corba", "bool", "true")]
@ -493,6 +496,35 @@ class LoraxInstallTree(BaseLoraxClass):
# change permissions
chmod_(shadow, 400)
# generate ssh keys for s390
if self.basearch in ("s390", "s390x"):
logger.info("generating SSH1 RSA host key")
rsa1 = joinpaths(self.root, "etc/ssh/ssh_host_key")
cmd = [self.lcmds.SSHKEYGEN, "-q", "-t", "rsa1", "-f", rsa1,
"-C", "", "-N", ""]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.wait()
logger.info("generating SSH2 RSA host key")
rsa2 = joinpaths(self.root, "etc/ssh/ssh_host_rsa_key")
cmd = [self.lcmds.SSHKEYGEN, "-q", "-t", "rsa", "-f", rsa2,
"-C", "", "-N", ""]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.wait()
logger.info("generating SSH2 DSA host key")
dsa = joinpaths(self.root, "etc/ssh/ssh_host_dsa_key")
cmd = [self.lcmds.SSHKEYGEN, "-q", "-t", "dsa", "-f", dsa,
"-C", "", "-N", ""]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.wait()
# change key file permissions
for key in [rsa1, rsa2, dsa]:
chmod_(key, 0600)
chmod_(key + ".pub", 0644)
def get_anaconda_portions(self):
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "loader")
dst = joinpaths(self.root, "sbin")
@ -506,7 +538,7 @@ class LoraxInstallTree(BaseLoraxClass):
dst = joinpaths(self.root, "sbin")
shutil.copy2(src, dst)
def compress(self, initrd, kernel):
def compress(self, initrd, kernel, type="xz"):
chdir = lambda: os.chdir(self.root)
start = time.time()
@ -521,9 +553,14 @@ class LoraxInstallTree(BaseLoraxClass):
stdin=find.stdout, stdout=subprocess.PIPE,
preexec_fn=chdir)
gzipped = gzip.open(initrd.fpath, "wb")
gzipped.write(cpio.stdout.read())
gzipped.close()
if type == "gzip":
compressed = gzip.open(initrd.fpath, "wb")
elif type == "xz":
compressed = lzma.LZMAFile(initrd.fpath, "w",
options={"format":"xz", "level":9})
compressed.write(cpio.stdout.read())
compressed.close()
# move modules out of the tree again
shutil.move(joinpaths(self.root, "modules", kernel.version),

View File

@ -50,6 +50,9 @@ class LoraxTemplate(object):
lines = map(lambda line: line.strip(), lines)
lines = filter(lambda line: line, lines)
# mako template now returns unicode strings
lines = map(lambda line: line.encode("ascii"), lines)
# split with shlex
lines = map(shlex.split, lines)

View File

@ -65,7 +65,7 @@ class LoraxOutputTree(BaseLoraxClass):
self.isolinuxdir = isolinuxdir
self.efibootdir = efibootdir
def get_kernels(self):
def get_kernels(self, workdir):
self.kernels = []
for n, kernel in enumerate(self.installtree.kernels):
@ -77,18 +77,21 @@ class LoraxOutputTree(BaseLoraxClass):
kname = "vmlinuz{0}".format(suffix)
if n == 0:
# copy main kernel to isolinuxdir
dst = joinpaths(self.isolinuxdir, kname)
shutil.copy2(kernel.fpath, dst)
dst = joinpaths(workdir, kname)
shutil.copy2(kernel.fpath, dst)
# create hard link to main kernel in pxebootdir
link_name = joinpaths(self.pxebootdir, kname)
os.link(dst, link_name)
else:
# copy other kernels to pxebootdir
dst = joinpaths(self.pxebootdir, kname)
shutil.copy2(kernel.fpath, dst)
#if n == 0:
# # copy main kernel to isolinuxdir
# dst = joinpaths(self.isolinuxdir, kname)
# shutil.copy2(kernel.fpath, dst)
#
# # create hard link to main kernel in pxebootdir
# link_name = joinpaths(self.pxebootdir, kname)
# os.link(dst, link_name)
#else:
# # copy other kernels to pxebootdir
# dst = joinpaths(self.pxebootdir, kname)
# shutil.copy2(kernel.fpath, dst)
# change the fname and fpath to new values
self.kernels.append(DataHolder(fname=kname,

View File

@ -32,6 +32,7 @@ import pwd
import grp
import glob
import subprocess
import shutil
def joinpaths(*args, **kwargs):
@ -126,3 +127,11 @@ def remove_dm_dev(dev):
cmd = ["dmsetup", "remove", dev]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
return proc.wait()
def cpfile(src, dst):
shutil.copy2(src, dst)
if os.path.isdir(dst):
dst = joinpaths(dst, os.path.basename(src))
return dst

View File

@ -116,6 +116,10 @@ class LoraxYumHelper(object):
fullpattern = joinpaths(self.installroot, pattern)
count = 0
for fname in glob.glob(fullpattern):
# if there are symlinks, we could already removed the file
if not os.path.exists(fname):
continue
if os.path.islink(fname) or os.path.isfile(fname):
os.unlink(fname)
else:
@ -130,7 +134,7 @@ class LoraxYumHelper(object):
return True
def process_transaction(self, skip_broken=True):
def process_transaction(self, skip_broken=False):
# skip broken
self.ybo.conf.skip_broken = skip_broken
self.ybo.buildTransaction()

View File

@ -74,7 +74,11 @@ def main(args):
# parse the arguments
opts, args = parser.parse_args()
outputdir = args[0]
try:
outputdir = args[0]
except IndexError:
parser.error("missing one or more required arguments")
if opts.showver:
print(version)

111
src/sbin/mkefiboot Executable file
View File

@ -0,0 +1,111 @@
#!/usr/bin/python
# mkefiboot - a tool to make EFI boot images
# Copyright (C) 2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Will Woods <wwoods@redhat.com>
import os, tempfile, argparse
from subprocess import check_call, PIPE
from pylorax.imgutils import mkdosimg, round_to_blocks, LoopDev, DMDev, dm_detach
from pylorax.imgutils import mkhfsimg, Mount
import struct, shutil, glob
def mkefiboot(bootdir, outfile, label):
'''Make an EFI boot image with the contents of bootdir in EFI/BOOT'''
mkdosimg(None, outfile, label=label, graft={'EFI/BOOT':bootdir})
def mkmacboot(bootdir, outfile, label, icon=None):
'''Make an EFI boot image for Apple's EFI implementation'''
graft = {'EFI/BOOT':bootdir}
if icon:
graft['.VolumeIcon.icns'] = icon
mkhfsimg(None, outfile, label=label, graft=graft)
macbless(outfile)
# To make an HFS+ image bootable, we need to fill in parts of the
# HFSPlusVolumeHeader structure - specifically, finderInfo[0,1,5].
# For details, see Technical Note TN1150: HFS Plus Volume Format
# http://developer.apple.com/library/mac/#technotes/tn/tn1150.html
def macbless(imgfile):
'''"bless" the EFI bootloader inside the given Mac EFI boot image, by
writing its inode info into the HFS+ volume header.'''
# Get the inode number for the boot image and its parent directory
with LoopDev(imgfile) as loopdev:
with Mount(loopdev) as mnt:
loader = glob.glob(os.path.join(mnt,'EFI/BOOT/BOOT*.efi'))[0]
blessnode = os.stat(loader).st_ino
dirnode = os.stat(os.path.dirname(loader)).st_ino
# format data properly (big-endian UInt32)
nodedata = struct.pack(">i", blessnode)
dirdata = struct.pack(">i", dirnode)
# Write it to the volume header
with open(imgfile, "r+b") as img:
img.seek(0x450) # HFSPlusVolumeHeader->finderInfo
img.write(dirdata) # finderInfo[0]
img.write(nodedata) # finderInfo[1]
img.seek(0x464) #
img.write(dirdata) # finderInfo[5]
def mkefidisk(efiboot, outfile):
'''Make a bootable EFI disk image out of the given EFI boot image.'''
# pjones sez: "17408 is the size of the GPT tables parted creates"
partsize = os.path.getsize(efiboot) + 17408
disksize = round_to_blocks(17408 + partsize, 512)
with LoopDev(outfile, disksize) as loopdev:
with DMDev(loopdev, disksize) as dmdev:
check_call(["parted", "--script", "/dev/mapper/%s" % dmdev,
"mklabel", "gpt",
"unit", "b",
"mkpart", "'EFI System Partition'", "fat32", "17408", str(partsize),
"set", "1", "boot", "on"], stdout=PIPE, stderr=PIPE)
partdev = "/dev/mapper/{0}p1".format(dmdev)
with open(efiboot, "rb") as infile:
with open(partdev, "wb") as outfile:
outfile.write(infile.read())
dm_detach(dmdev+"p1")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Make an EFI boot image from the given directory.")
parser.add_argument("-d", "--disk", action="store_true",
help="make a full EFI disk image (including partition table)")
parser.add_argument("-a", "--apple", action="store_const", const="apple",
dest="imgtype", default="default",
help="make an Apple EFI image (use hfs+, bless bootloader)")
parser.add_argument("-l", "--label", default="EFI",
help="filesystem label to use (default: %(default)s)")
parser.add_argument("-i", "--icon", metavar="ICONFILE",
help="icon file to include (for Apple EFI image)")
parser.add_argument("bootdir", metavar="EFIBOOTDIR",
help="input directory (will become /EFI/BOOT in the image)")
parser.add_argument("outfile", metavar="OUTPUTFILE",
help="output file to write")
opt = parser.parse_args()
# sanity checks
if not os.path.isdir(opt.bootdir):
parser.error("%s is not a directory" % opt.bootdir)
if os.getuid() > 0:
parser.error("need root permissions")
if opt.icon and not opt.imgtype == "apple":
print "Warning: --icon is only useful for Apple EFI images"
# do the thing!
if opt.imgtype == "apple":
mkmacboot(opt.bootdir, opt.outfile, opt.label, opt.icon)
else:
mkefiboot(opt.bootdir, opt.outfile, opt.label)
if opt.disk:
efiboot = tempfile.NamedTemporaryFile(prefix="mkefiboot.").name
shutil.move(opt.outfile, efiboot)
mkefidisk(efiboot, opt.outfile)