Compare commits
77 Commits
master
...
f15-branch
Author | SHA1 | Date | |
---|---|---|---|
|
a2c36797fe | ||
|
88c85cf76f | ||
|
1e28497ee2 | ||
|
6823e5da69 | ||
|
b1ccc9827a | ||
|
682f049d33 | ||
|
c861707821 | ||
|
73c4198c22 | ||
|
40bd077a2a | ||
|
78709fe029 | ||
|
d8bb479421 | ||
|
a3593d05a2 | ||
|
09d6569fd3 | ||
|
4271a37e9a | ||
|
12db6da29a | ||
|
b054345a2a | ||
|
b41331ea75 | ||
|
5bb6d1e59b | ||
|
15edee2353 | ||
|
bd3197845a | ||
|
7bbb584c6c | ||
|
8588913b10 | ||
|
4e42a82b20 | ||
|
8fcbe0c773 | ||
|
ac0f1c3c51 | ||
|
e10403eeb5 | ||
|
3d8a48c69d | ||
|
35d85a7b4f | ||
|
3930b8ea6c | ||
|
3851ac2fb2 | ||
|
d5515f820b | ||
|
024f7137c6 | ||
|
507735e127 | ||
|
a73cedc951 | ||
|
4064c78fe6 | ||
|
fb8224b71d | ||
|
80650edb4d | ||
|
fbd8da6d40 | ||
|
ef1ae59a8a | ||
|
c3e7664448 | ||
|
f5258e7266 | ||
|
76ba5755fc | ||
|
1b5100b5ca | ||
|
c41e8a89b8 | ||
|
ae90d14e44 | ||
|
a588f46823 | ||
|
69ad288e66 | ||
|
bdba285796 | ||
|
662449d0f6 | ||
|
9b8a8c83d7 | ||
|
7bfb602ff4 | ||
|
682515da71 | ||
|
c7f43aaa6b | ||
|
3f64827719 | ||
|
d2daafa402 | ||
|
073e71ad8b | ||
|
7fddbc3b09 | ||
|
33688a99f2 | ||
|
589ae9e600 | ||
|
ac4572202f | ||
|
183bcc7065 | ||
|
203cc7b15f | ||
|
772cab692c | ||
|
72bfb754fd | ||
|
b3362abeff | ||
|
eed099d1cf | ||
|
aff37a71d1 | ||
|
600e9c16e8 | ||
|
866b36115a | ||
|
e17d3484e1 | ||
|
d5c4537476 | ||
|
1b67c2690b | ||
|
80035c6b7b | ||
|
c0a8d7deff | ||
|
d28b812189 | ||
|
5f27c4ee62 | ||
|
ccd8a136b0 |
@ -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
|
||||
|
110
lorax.spec
110
lorax.spec
@ -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
|
||||
|
2
setup.py
2
setup.py
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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-*"
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
804
src/pylorax/images.py
Normal 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
292
src/pylorax/imgutils.py
Normal 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)
|
@ -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),
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
111
src/sbin/mkefiboot
Executable 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)
|
Loading…
Reference in New Issue
Block a user