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
|
Name: lorax
|
||||||
Version: 0.3
|
Version: 0.4.7
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Tool for creating the anaconda install images
|
Summary: Tool for creating the anaconda install images
|
||||||
|
|
||||||
@ -7,10 +9,8 @@ Group: Applications/System
|
|||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: http://git.fedorahosted.org/git/?p=lorax.git
|
URL: http://git.fedorahosted.org/git/?p=lorax.git
|
||||||
Source0: https://fedorahosted.org/releases/l/o/%{name}/%{name}-%{version}.tar.bz2
|
Source0: https://fedorahosted.org/releases/l/o/%{name}/%{name}-%{version}.tar.bz2
|
||||||
BuildArch: noarch
|
|
||||||
|
|
||||||
BuildRequires: python-setuptools
|
BuildRequires: python2-devel
|
||||||
Requires: python2-devel
|
|
||||||
Requires: python-mako
|
Requires: python-mako
|
||||||
Requires: gawk
|
Requires: gawk
|
||||||
Requires: glibc-common
|
Requires: glibc-common
|
||||||
@ -20,12 +20,20 @@ Requires: device-mapper
|
|||||||
Requires: findutils
|
Requires: findutils
|
||||||
Requires: GConf2
|
Requires: GConf2
|
||||||
Requires: isomd5sum
|
Requires: isomd5sum
|
||||||
Requires: syslinux
|
|
||||||
Requires: glibc
|
Requires: glibc
|
||||||
Requires: util-linux-ng
|
Requires: util-linux-ng
|
||||||
Requires: dosfstools
|
Requires: dosfstools
|
||||||
Requires: genisoimage
|
Requires: genisoimage
|
||||||
Requires: parted
|
Requires: parted
|
||||||
|
Requires: pyliblzma
|
||||||
|
|
||||||
|
%ifarch %{ix86} x86_64
|
||||||
|
Requires: syslinux
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifarch %{sparc}
|
||||||
|
Requires: silo
|
||||||
|
%endif
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Lorax is a tool for creating the anaconda install images.
|
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}/pylorax
|
||||||
%{python_sitelib}/*.egg-info
|
%{python_sitelib}/*.egg-info
|
||||||
%{_sbindir}/lorax
|
%{_sbindir}/lorax
|
||||||
|
%{_sbindir}/mkefiboot
|
||||||
%dir %{_sysconfdir}/lorax
|
%dir %{_sysconfdir}/lorax
|
||||||
%config(noreplace) %{_sysconfdir}/lorax/lorax.conf
|
%config(noreplace) %{_sysconfdir}/lorax/lorax.conf
|
||||||
%dir %{_datadir}/lorax
|
%dir %{_datadir}/lorax
|
||||||
@ -52,6 +61,97 @@ make DESTDIR=$RPM_BUILD_ROOT install
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%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
|
* Mon Jan 24 2011 Martin Gracik <mgracik@redhat.com> 0.3-1
|
||||||
- Don't remove libmount package
|
- Don't remove libmount package
|
||||||
- Don't create mtab symlink, already exists
|
- 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)]))
|
[os.path.join(root, fname)]))
|
||||||
|
|
||||||
# executable
|
# executable
|
||||||
data_files.append(("/usr/sbin", ["src/sbin/lorax"]))
|
data_files.append(("/usr/sbin", ["src/sbin/lorax", "src/sbin/mkefiboot"]))
|
||||||
|
|
||||||
setup(name="lorax",
|
setup(name="lorax",
|
||||||
version="0.1",
|
version="0.1",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#### MODULES ####
|
#### MODULES ####
|
||||||
$ModLoad imuxsock.so # provides support for local system logging
|
$ModLoad imuxsock.so # provides support for local system logging
|
||||||
$ModLoad imklog.so # provides kernel logging support
|
$SystemLogRateLimitInterval 0 # disables message dropping, we need all of them
|
||||||
|
$ModLoad imklog.so # provides kernel logging support
|
||||||
|
|
||||||
$ModLoad imfile
|
$ModLoad imfile
|
||||||
$InputFileName /tmp/X.log
|
$InputFileName /tmp/X.log
|
||||||
|
@ -10,6 +10,41 @@ install "kernel"
|
|||||||
install "gpart"
|
install "gpart"
|
||||||
% endif
|
% 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
|
## other required packages
|
||||||
install "NetworkManager-gnome"
|
install "NetworkManager-gnome"
|
||||||
install "at-spi"
|
install "at-spi"
|
||||||
@ -18,7 +53,6 @@ install "at-spi2-atk"
|
|||||||
install "audit"
|
install "audit"
|
||||||
install "bind-libs"
|
install "bind-libs"
|
||||||
install "bind-utils"
|
install "bind-utils"
|
||||||
install "biosdevname"
|
|
||||||
install "bitmap-fangsongti-fonts"
|
install "bitmap-fangsongti-fonts"
|
||||||
install "btrfs-progs"
|
install "btrfs-progs"
|
||||||
install "bzip2-libs"
|
install "bzip2-libs"
|
||||||
@ -29,12 +63,10 @@ install "dejavu-sans-fonts"
|
|||||||
install "dejavu-sans-mono-fonts"
|
install "dejavu-sans-mono-fonts"
|
||||||
install "dogtail"
|
install "dogtail"
|
||||||
install "dump"
|
install "dump"
|
||||||
install "efibootmgr"
|
|
||||||
install "ethtool"
|
install "ethtool"
|
||||||
install "fedora-gnome-theme"
|
install "fedora-gnome-theme"
|
||||||
install "fedora-icon-theme"
|
install "fedora-icon-theme"
|
||||||
install "firstaidkit-engine"
|
install "firstaidkit-engine"
|
||||||
install "firstaidkit-plugin-grub"
|
|
||||||
install "firstboot"
|
install "firstboot"
|
||||||
install "ftp"
|
install "ftp"
|
||||||
install "gdb-gdbserver"
|
install "gdb-gdbserver"
|
||||||
@ -46,11 +78,9 @@ install "gnome-icon-theme-legacy"
|
|||||||
install "gnome-keyring"
|
install "gnome-keyring"
|
||||||
install "gnome-python2-bonobo"
|
install "gnome-python2-bonobo"
|
||||||
install "gnome-python2-gconf"
|
install "gnome-python2-gconf"
|
||||||
##install "gnome-themes-legacy"
|
|
||||||
install "gnome-themes-standard"
|
install "gnome-themes-standard"
|
||||||
install "gobject-introspection"
|
install "gobject-introspection"
|
||||||
install "groff"
|
install "groff"
|
||||||
install "grub"
|
|
||||||
install "gtk+"
|
install "gtk+"
|
||||||
install "hdparm"
|
install "hdparm"
|
||||||
install "jfsutils"
|
install "jfsutils"
|
||||||
@ -79,15 +109,12 @@ install "lsof"
|
|||||||
install "lvm2-cluster"
|
install "lvm2-cluster"
|
||||||
install "madan-fonts"
|
install "madan-fonts"
|
||||||
install "man-db"
|
install "man-db"
|
||||||
install "memtest86+"
|
|
||||||
install "metacity"
|
install "metacity"
|
||||||
install "mt-st"
|
install "mt-st"
|
||||||
install "mtr"
|
install "mtr"
|
||||||
install "network-manager-netbook"
|
|
||||||
install "nfs-utils"
|
install "nfs-utils"
|
||||||
install "notification-daemon"
|
install "notification-daemon"
|
||||||
install "ntfs-3g"
|
install "ntfs-3g"
|
||||||
install "ntfsprogs"
|
|
||||||
install "openssh-server"
|
install "openssh-server"
|
||||||
install "pciutils"
|
install "pciutils"
|
||||||
install "pciutils-libs"
|
install "pciutils-libs"
|
||||||
@ -125,75 +152,36 @@ install "volume_key-libs"
|
|||||||
install "wget"
|
install "wget"
|
||||||
install "xfsprogs"
|
install "xfsprogs"
|
||||||
install "xorg-x11-drivers"
|
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-ethiopic"
|
||||||
install "xorg-x11-fonts-misc"
|
install "xorg-x11-fonts-misc"
|
||||||
install "xorg-x11-server-Xorg"
|
install "xorg-x11-server-Xorg"
|
||||||
install "xorg-x11-server-utils"
|
install "xorg-x11-server-utils"
|
||||||
|
install "yum-langpacks"
|
||||||
install "${product}-logos"
|
install "${product}-logos"
|
||||||
install "${product}-release"
|
install "${product}-release"
|
||||||
|
|
||||||
## required firmware
|
## required firmware
|
||||||
install "aic94xx-firmware"
|
% if basearch != "s390x":
|
||||||
install "ar9170-firmware"
|
install "aic94xx-firmware"
|
||||||
install "atmel-firmware"
|
install "ar9170-firmware"
|
||||||
install "ipw2100-firmware"
|
install "atmel-firmware"
|
||||||
install "ipw2200-firmware"
|
install "ipw2100-firmware"
|
||||||
install "iwl1000-firmware"
|
install "ipw2200-firmware"
|
||||||
install "iwl3945-firmware"
|
install "iwl1000-firmware"
|
||||||
install "iwl4965-firmware"
|
install "iwl3945-firmware"
|
||||||
install "iwl5000-firmware"
|
install "iwl4965-firmware"
|
||||||
install "iwl5150-firmware"
|
install "iwl5000-firmware"
|
||||||
install "iwl6000-firmware"
|
install "iwl5150-firmware"
|
||||||
install "iwl6050-firmware"
|
install "iwl6000-firmware"
|
||||||
install "ql2100-firmware"
|
install "iwl6000g2b-firmware"
|
||||||
install "ql2200-firmware"
|
install "iwl6050-firmware"
|
||||||
install "ql23xx-firmware"
|
install "ql2100-firmware"
|
||||||
install "ql2400-firmware"
|
install "ql2200-firmware"
|
||||||
install "ql2500-firmware"
|
install "ql23xx-firmware"
|
||||||
install "zd1211-firmware"
|
install "ql2400-firmware"
|
||||||
|
install "ql2500-firmware"
|
||||||
|
install "zd1211-firmware"
|
||||||
|
% endif
|
||||||
|
|
||||||
## required directories
|
## required directories
|
||||||
mkdir "/var/run/dbus"
|
mkdir "/var/run/dbus"
|
||||||
@ -266,7 +254,6 @@ remove "libXv"
|
|||||||
remove "libXvMC"
|
remove "libXvMC"
|
||||||
remove "libXxf86misc"
|
remove "libXxf86misc"
|
||||||
remove "libXxf86vm"
|
remove "libXxf86vm"
|
||||||
remove "libassuan"
|
|
||||||
remove "libasyncns"
|
remove "libasyncns"
|
||||||
remove "libccss"
|
remove "libccss"
|
||||||
remove "libcgroup"
|
remove "libcgroup"
|
||||||
@ -278,11 +265,9 @@ remove "libhbaapi"
|
|||||||
remove "libhbalinux"
|
remove "libhbalinux"
|
||||||
remove "libibverbs"
|
remove "libibverbs"
|
||||||
remove "libmcpp"
|
remove "libmcpp"
|
||||||
remove "libmodman"
|
|
||||||
remove "libmx"
|
remove "libmx"
|
||||||
remove "libnih"
|
remove "libnih"
|
||||||
remove "libpcap"
|
remove "libpcap"
|
||||||
remove "libproxy"
|
|
||||||
remove "librdmacm"
|
remove "librdmacm"
|
||||||
remove "librsvg2"
|
remove "librsvg2"
|
||||||
remove "libselinux-utils"
|
remove "libselinux-utils"
|
||||||
@ -455,6 +440,7 @@ module "st"
|
|||||||
module "sunrpc"
|
module "sunrpc"
|
||||||
module "tcic"
|
module "tcic"
|
||||||
module "ub"
|
module "ub"
|
||||||
|
module "udf"
|
||||||
module "uhci-hcd"
|
module "uhci-hcd"
|
||||||
module "ums-alauda"
|
module "ums-alauda"
|
||||||
module "ums-cypress"
|
module "ums-cypress"
|
||||||
@ -474,6 +460,13 @@ module "xfs"
|
|||||||
module "xts"
|
module "xts"
|
||||||
module "yenta_socket"
|
module "yenta_socket"
|
||||||
|
|
||||||
|
## s390 modules
|
||||||
|
% if basearch == "s390x":
|
||||||
|
module "dasd_eckd_mod"
|
||||||
|
module "dasd_fba_mod"
|
||||||
|
module "dasd_diag_mod"
|
||||||
|
% endif
|
||||||
|
|
||||||
## other removals
|
## other removals
|
||||||
remove --path "/usr/share/doc"
|
remove --path "/usr/share/doc"
|
||||||
remove --path "/usr/share/info"
|
remove --path "/usr/share/info"
|
||||||
@ -640,7 +633,6 @@ remove "coreutils" "/usr/bin/stdbuf"
|
|||||||
remove "coreutils" "/usr/bin/sum"
|
remove "coreutils" "/usr/bin/sum"
|
||||||
remove "coreutils" "/usr/bin/test"
|
remove "coreutils" "/usr/bin/test"
|
||||||
remove "coreutils" "/usr/bin/timeout"
|
remove "coreutils" "/usr/bin/timeout"
|
||||||
remove "coreutils" "/usr/bin/tr"
|
|
||||||
remove "coreutils" "/usr/bin/truncate"
|
remove "coreutils" "/usr/bin/truncate"
|
||||||
remove "coreutils" "/usr/bin/tsort"
|
remove "coreutils" "/usr/bin/tsort"
|
||||||
remove "coreutils" "/usr/bin/unexpand"
|
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/share/hal/*"
|
||||||
remove "ntfs-3g" "/usr/bin/*"
|
remove "ntfs-3g" "/usr/bin/*"
|
||||||
remove "ntfsprogs" "/sbin/*"
|
remove "ntfsprogs" "/sbin/*"
|
||||||
remove "ntfsprogs" "/usr/bin/ntfsck"
|
|
||||||
remove "openldap" "/etc/openldap/*"
|
remove "openldap" "/etc/openldap/*"
|
||||||
remove "openldap" "/usr/${libdir}/libldap_r-*"
|
remove "openldap" "/usr/${libdir}/libldap_r-*"
|
||||||
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 buildstamp import BuildStamp
|
||||||
from treeinfo import TreeInfo
|
from treeinfo import TreeInfo
|
||||||
from discinfo import DiscInfo
|
from discinfo import DiscInfo
|
||||||
|
import images
|
||||||
|
|
||||||
|
|
||||||
ARCHMAPS = {
|
ARCHMAPS = {
|
||||||
@ -66,6 +67,7 @@ ARCHMAPS = {
|
|||||||
"s390": {"base": "s390", "efi": "", "is64": False},
|
"s390": {"base": "s390", "efi": "", "is64": False},
|
||||||
"s390x": {"base": "s390x", "efi": "", "is64": True},
|
"s390x": {"base": "s390x", "efi": "", "is64": True},
|
||||||
"sparc": {"base": "sparc", "efi": "", "is64": False},
|
"sparc": {"base": "sparc", "efi": "", "is64": False},
|
||||||
|
"sparcv9": {"base": "sparc", "efi": "", "is64": False},
|
||||||
"sparc64": {"base": "sparc", "efi": "", "is64": True},
|
"sparc64": {"base": "sparc", "efi": "", "is64": True},
|
||||||
"ia64": {"base": "ia64", "efi": "IA64", "is64": True}
|
"ia64": {"base": "ia64", "efi": "IA64", "is64": True}
|
||||||
}
|
}
|
||||||
@ -162,10 +164,13 @@ class Lorax(BaseLoraxClass):
|
|||||||
|
|
||||||
# do we have all lorax required commands?
|
# do we have all lorax required commands?
|
||||||
self.lcmds = constants.LoraxRequiredCommands()
|
self.lcmds = constants.LoraxRequiredCommands()
|
||||||
|
|
||||||
|
"""
|
||||||
missing = self.lcmds.get_missing()
|
missing = self.lcmds.get_missing()
|
||||||
if missing:
|
if missing:
|
||||||
logger.critical("missing required command: {0}".format(missing))
|
logger.critical("missing required command: {0}".format(missing))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
"""
|
||||||
|
|
||||||
# do we have a proper yum base object?
|
# do we have a proper yum base object?
|
||||||
logger.info("checking yum base object")
|
logger.info("checking yum base object")
|
||||||
@ -296,10 +301,6 @@ class Lorax(BaseLoraxClass):
|
|||||||
logger.info("running depmod")
|
logger.info("running depmod")
|
||||||
self.installtree.run_depmod(kernel)
|
self.installtree.run_depmod(kernel)
|
||||||
|
|
||||||
# create gconf
|
|
||||||
logger.info("creating gconf files")
|
|
||||||
self.installtree.create_gconf()
|
|
||||||
|
|
||||||
# move repos
|
# move repos
|
||||||
logger.info("moving anaconda repos")
|
logger.info("moving anaconda repos")
|
||||||
self.installtree.move_repos()
|
self.installtree.move_repos()
|
||||||
@ -325,12 +326,12 @@ class Lorax(BaseLoraxClass):
|
|||||||
self.outputtree = LoraxOutputTree(self.outputdir, self.installtree,
|
self.outputtree = LoraxOutputTree(self.outputdir, self.installtree,
|
||||||
self.product, self.version)
|
self.product, self.version)
|
||||||
|
|
||||||
self.outputtree.prepare()
|
#self.outputtree.prepare()
|
||||||
self.outputtree.get_isolinux()
|
#self.outputtree.get_isolinux()
|
||||||
self.outputtree.get_memtest()
|
#self.outputtree.get_memtest()
|
||||||
self.outputtree.get_splash()
|
#self.outputtree.get_splash()
|
||||||
self.outputtree.get_msg_files()
|
#self.outputtree.get_msg_files()
|
||||||
self.outputtree.get_grub_conf()
|
#self.outputtree.get_grub_conf()
|
||||||
|
|
||||||
# write .discinfo
|
# write .discinfo
|
||||||
discinfo = DiscInfo(self.workdir, self.release, self.basearch)
|
discinfo = DiscInfo(self.workdir, self.release, self.basearch)
|
||||||
@ -338,6 +339,7 @@ class Lorax(BaseLoraxClass):
|
|||||||
|
|
||||||
shutil.copy2(discinfo.path, self.outputtree.root)
|
shutil.copy2(discinfo.path, self.outputtree.root)
|
||||||
|
|
||||||
|
# move grubefi to workdir
|
||||||
grubefi = joinpaths(self.installtree.root, "boot/efi/EFI/redhat",
|
grubefi = joinpaths(self.installtree.root, "boot/efi/EFI/redhat",
|
||||||
"grub.efi")
|
"grub.efi")
|
||||||
|
|
||||||
@ -347,14 +349,37 @@ class Lorax(BaseLoraxClass):
|
|||||||
else:
|
else:
|
||||||
grubefi = None
|
grubefi = None
|
||||||
|
|
||||||
|
# move grub splash to workdir
|
||||||
splash = joinpaths(self.installtree.root, "boot/grub/",
|
splash = joinpaths(self.installtree.root, "boot/grub/",
|
||||||
"splash.xpm.gz")
|
"splash.xpm.gz")
|
||||||
|
|
||||||
shutil.move(splash, self.workdir)
|
if os.path.isfile(splash):
|
||||||
splash = joinpaths(self.workdir, os.path.basename(splash))
|
shutil.move(splash, self.workdir)
|
||||||
|
splash = joinpaths(self.workdir, os.path.basename(splash))
|
||||||
|
else:
|
||||||
|
splash = None
|
||||||
|
|
||||||
# copy kernels to output directory
|
# 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
|
# get list of not required packages
|
||||||
logger.info("getting 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")
|
logger.info("cleaning up python files")
|
||||||
self.installtree.cleanup_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)
|
# compress install tree (create initrd)
|
||||||
initrds = []
|
logger.info("creating the initrd")
|
||||||
for kernel in self.outputtree.kernels:
|
i.create_initrd(self.libdir)
|
||||||
suffix = ""
|
|
||||||
if kernel.ktype == constants.K_PAE:
|
|
||||||
suffix = "-PAE"
|
|
||||||
elif kernel.ktype == constants.K_XEN:
|
|
||||||
suffix = "-XEN"
|
|
||||||
|
|
||||||
fname = "initrd{0}.img".format(suffix)
|
#initrds = []
|
||||||
|
#for kernel in self.outputtree.kernels:
|
||||||
initrd = DataHolder(fname=fname,
|
# suffix = ""
|
||||||
fpath=joinpaths(self.workdir, fname),
|
# if kernel.ktype == constants.K_PAE:
|
||||||
itype=kernel.ktype)
|
# suffix = "-PAE"
|
||||||
|
# elif kernel.ktype == constants.K_XEN:
|
||||||
logger.info("compressing install tree ({0})".format(kernel.version))
|
# suffix = "-XEN"
|
||||||
success, elapsed = self.installtree.compress(initrd, kernel)
|
#
|
||||||
if not success:
|
# fname = "initrd{0}.img".format(suffix)
|
||||||
logger.error("error while compressing install tree")
|
#
|
||||||
else:
|
# initrd = DataHolder(fname=fname,
|
||||||
logger.info("took {0:.2f} seconds".format(elapsed))
|
# fpath=joinpaths(self.workdir, fname),
|
||||||
|
# itype=kernel.ktype)
|
||||||
initrds.append(initrd)
|
#
|
||||||
|
# logger.info("compressing install tree ({0})".format(kernel.version))
|
||||||
# add kernel and initrd paths to .treeinfo
|
# success, elapsed = self.installtree.compress(initrd, kernel)
|
||||||
section = "images-{0}".format("xen" if suffix else self.basearch)
|
# if not success:
|
||||||
data = {"kernel": "images/pxeboot/{0}".format(kernel.fname)}
|
# logger.error("error while compressing install tree")
|
||||||
treeinfo.add_section(section, data)
|
# else:
|
||||||
data = {"initrd": "images/pxeboot/{0}".format(initrd.fname)}
|
# logger.info("took {0:.2f} seconds".format(elapsed))
|
||||||
treeinfo.add_section(section, data)
|
#
|
||||||
|
# initrds.append(initrd)
|
||||||
# copy initrds to outputtree
|
#
|
||||||
shutil.copy2(initrds[0].fpath, self.outputtree.isolinuxdir)
|
# # add kernel and initrd paths to .treeinfo
|
||||||
|
# section = "images-{0}".format("xen" if suffix else self.basearch)
|
||||||
# create hard link
|
# data = {"kernel": "images/pxeboot/{0}".format(kernel.fname)}
|
||||||
source = joinpaths(self.outputtree.isolinuxdir, initrds[0].fname)
|
# treeinfo.add_section(section, data)
|
||||||
link_name = joinpaths(self.outputtree.pxebootdir, initrds[0].fname)
|
# data = {"initrd": "images/pxeboot/{0}".format(initrd.fname)}
|
||||||
os.link(source, link_name)
|
# treeinfo.add_section(section, data)
|
||||||
|
#
|
||||||
for initrd in initrds[1:]:
|
## copy initrds to outputtree
|
||||||
shutil.copy2(initrd.fpath, self.outputtree.pxebootdir)
|
#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
|
# create efi images
|
||||||
efiboot = None
|
efiboot = None
|
||||||
if grubefi and self.efiarch not in ("IA32",):
|
if grubefi and self.efiarch not in ("IA32",):
|
||||||
kernel = self.outputtree.kernels[0]
|
# create efibootdir
|
||||||
initrd = initrds[0]
|
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
|
# create efiboot image with kernel
|
||||||
logger.info("creating efiboot image with kernel")
|
logger.info("creating efiboot image with kernel")
|
||||||
@ -480,17 +513,19 @@ class Lorax(BaseLoraxClass):
|
|||||||
|
|
||||||
# create boot iso
|
# create boot iso
|
||||||
logger.info("creating boot iso")
|
logger.info("creating boot iso")
|
||||||
bootiso = self.create_bootiso(self.outputtree, efiboot)
|
i.create_boot(efiboot)
|
||||||
if bootiso is None:
|
|
||||||
logger.critical("unable to create boot iso")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
shutil.move(bootiso, self.outputtree.imgdir)
|
#bootiso = self.create_bootiso(self.outputtree, efiboot)
|
||||||
|
#if bootiso is None:
|
||||||
# add the boot.iso
|
# logger.critical("unable to create boot iso")
|
||||||
section = "images-{0}".format(self.basearch)
|
# sys.exit(1)
|
||||||
data = {"boot.iso": "images/{0}".format(os.path.basename(bootiso))}
|
#
|
||||||
treeinfo.add_section(section, data)
|
#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()
|
treeinfo.write()
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ class LoraxRequiredCommands(dict):
|
|||||||
self["MODINFO"] = "modinfo"
|
self["MODINFO"] = "modinfo"
|
||||||
self["MOUNT"] = "mount"
|
self["MOUNT"] = "mount"
|
||||||
self["PARTED"] = "parted"
|
self["PARTED"] = "parted"
|
||||||
|
self["SSHKEYGEN"] = "ssh-keygen"
|
||||||
self["UMOUNT"] = "umount"
|
self["UMOUNT"] = "umount"
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
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 os
|
||||||
import shutil
|
import shutil
|
||||||
import gzip
|
import gzip
|
||||||
|
import lzma
|
||||||
import re
|
import re
|
||||||
import glob
|
import glob
|
||||||
import time
|
import time
|
||||||
@ -102,6 +103,10 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
shutil.move(langtable, joinpaths(self.root, "etc"))
|
shutil.move(langtable, joinpaths(self.root, "etc"))
|
||||||
|
|
||||||
def create_keymaps(self):
|
def create_keymaps(self):
|
||||||
|
if self.basearch in ("s390", "s390x"):
|
||||||
|
# skip on s390
|
||||||
|
return True
|
||||||
|
|
||||||
keymaps = joinpaths(self.root, "etc/keymaps.gz")
|
keymaps = joinpaths(self.root, "etc/keymaps.gz")
|
||||||
|
|
||||||
# look for override
|
# look for override
|
||||||
@ -112,7 +117,7 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
shutil.move(override, keymaps)
|
shutil.move(override, keymaps)
|
||||||
else:
|
else:
|
||||||
# create keymaps
|
# create keymaps
|
||||||
cmd = [joinpaths(self.root, "usr/share/anaconda", "getkeymaps"),
|
cmd = [joinpaths(self.root, "usr/libexec/anaconda", "getkeymaps"),
|
||||||
self.basearch, keymaps, self.root]
|
self.basearch, keymaps, self.root]
|
||||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||||
proc.wait()
|
proc.wait()
|
||||||
@ -346,30 +351,6 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
# move modules out of the tree
|
# move modules out of the tree
|
||||||
shutil.move(moddir, self.workdir)
|
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):
|
def move_repos(self):
|
||||||
src = joinpaths(self.root, "etc/yum.repos.d")
|
src = joinpaths(self.root, "etc/yum.repos.d")
|
||||||
dst = joinpaths(self.root, "etc/anaconda.repos.d")
|
dst = joinpaths(self.root, "etc/anaconda.repos.d")
|
||||||
@ -382,11 +363,24 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
fobj.write(text)
|
fobj.write(text)
|
||||||
|
|
||||||
def misc_tree_modifications(self):
|
def misc_tree_modifications(self):
|
||||||
# replace init with anaconda init
|
if self.basearch in ("s390", "s390x"):
|
||||||
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "init")
|
# copy shutdown
|
||||||
dst = joinpaths(self.root, "sbin", "init")
|
src = joinpaths(self.root, "usr", self.libdir, "anaconda/shutdown")
|
||||||
os.unlink(dst)
|
dst = joinpaths(self.root, "sbin", "shutdown")
|
||||||
shutil.copy2(src, dst)
|
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
|
# init symlinks
|
||||||
target = "/sbin/init"
|
target = "/sbin/init"
|
||||||
@ -398,7 +392,7 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
os.unlink(name)
|
os.unlink(name)
|
||||||
os.symlink("init", name)
|
os.symlink("init", name)
|
||||||
|
|
||||||
for fname in ["runlevel", "shutdown", "telinit"]:
|
for fname in ["runlevel", "telinit"]:
|
||||||
name = joinpaths(self.root, "sbin", fname)
|
name = joinpaths(self.root, "sbin", fname)
|
||||||
os.unlink(name)
|
os.unlink(name)
|
||||||
|
|
||||||
@ -419,11 +413,20 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
[("/apps/metacity/general/button_layout", "string", ":"),
|
[("/apps/metacity/general/button_layout", "string", ":"),
|
||||||
("/apps/metacity/general/action_right_click_titlebar",
|
("/apps/metacity/general/action_right_click_titlebar",
|
||||||
"string", "none"),
|
"string", "none"),
|
||||||
|
("/apps/metacity/general/num_workspaces", "int", "1"),
|
||||||
("/apps/metacity/window_keybindings/close", "string", "disabled"),
|
("/apps/metacity/window_keybindings/close", "string", "disabled"),
|
||||||
("/apps/metacity/global_keybindings/run_command_window_screenshot",
|
("/apps/metacity/global_keybindings/run_command_window_screenshot",
|
||||||
"string", "disabled"),
|
"string", "disabled"),
|
||||||
("/apps/metacity/global_keybindings/run_command_screenshot",
|
("/apps/metacity/global_keybindings/run_command_screenshot",
|
||||||
"string", "disabled"),
|
"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/accessibility", "bool", "true"),
|
||||||
("/desktop/gnome/interface/at-spi-corba", "bool", "true")]
|
("/desktop/gnome/interface/at-spi-corba", "bool", "true")]
|
||||||
|
|
||||||
@ -493,6 +496,35 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
# change permissions
|
# change permissions
|
||||||
chmod_(shadow, 400)
|
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):
|
def get_anaconda_portions(self):
|
||||||
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "loader")
|
src = joinpaths(self.root, "usr", self.libdir, "anaconda", "loader")
|
||||||
dst = joinpaths(self.root, "sbin")
|
dst = joinpaths(self.root, "sbin")
|
||||||
@ -506,7 +538,7 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
dst = joinpaths(self.root, "sbin")
|
dst = joinpaths(self.root, "sbin")
|
||||||
shutil.copy2(src, dst)
|
shutil.copy2(src, dst)
|
||||||
|
|
||||||
def compress(self, initrd, kernel):
|
def compress(self, initrd, kernel, type="xz"):
|
||||||
chdir = lambda: os.chdir(self.root)
|
chdir = lambda: os.chdir(self.root)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
@ -521,9 +553,14 @@ class LoraxInstallTree(BaseLoraxClass):
|
|||||||
stdin=find.stdout, stdout=subprocess.PIPE,
|
stdin=find.stdout, stdout=subprocess.PIPE,
|
||||||
preexec_fn=chdir)
|
preexec_fn=chdir)
|
||||||
|
|
||||||
gzipped = gzip.open(initrd.fpath, "wb")
|
if type == "gzip":
|
||||||
gzipped.write(cpio.stdout.read())
|
compressed = gzip.open(initrd.fpath, "wb")
|
||||||
gzipped.close()
|
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
|
# move modules out of the tree again
|
||||||
shutil.move(joinpaths(self.root, "modules", kernel.version),
|
shutil.move(joinpaths(self.root, "modules", kernel.version),
|
||||||
|
@ -50,6 +50,9 @@ class LoraxTemplate(object):
|
|||||||
lines = map(lambda line: line.strip(), lines)
|
lines = map(lambda line: line.strip(), lines)
|
||||||
lines = filter(lambda line: line, lines)
|
lines = filter(lambda line: line, lines)
|
||||||
|
|
||||||
|
# mako template now returns unicode strings
|
||||||
|
lines = map(lambda line: line.encode("ascii"), lines)
|
||||||
|
|
||||||
# split with shlex
|
# split with shlex
|
||||||
lines = map(shlex.split, lines)
|
lines = map(shlex.split, lines)
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class LoraxOutputTree(BaseLoraxClass):
|
|||||||
self.isolinuxdir = isolinuxdir
|
self.isolinuxdir = isolinuxdir
|
||||||
self.efibootdir = efibootdir
|
self.efibootdir = efibootdir
|
||||||
|
|
||||||
def get_kernels(self):
|
def get_kernels(self, workdir):
|
||||||
self.kernels = []
|
self.kernels = []
|
||||||
|
|
||||||
for n, kernel in enumerate(self.installtree.kernels):
|
for n, kernel in enumerate(self.installtree.kernels):
|
||||||
@ -77,18 +77,21 @@ class LoraxOutputTree(BaseLoraxClass):
|
|||||||
|
|
||||||
kname = "vmlinuz{0}".format(suffix)
|
kname = "vmlinuz{0}".format(suffix)
|
||||||
|
|
||||||
if n == 0:
|
dst = joinpaths(workdir, kname)
|
||||||
# copy main kernel to isolinuxdir
|
shutil.copy2(kernel.fpath, dst)
|
||||||
dst = joinpaths(self.isolinuxdir, kname)
|
|
||||||
shutil.copy2(kernel.fpath, dst)
|
|
||||||
|
|
||||||
# create hard link to main kernel in pxebootdir
|
#if n == 0:
|
||||||
link_name = joinpaths(self.pxebootdir, kname)
|
# # copy main kernel to isolinuxdir
|
||||||
os.link(dst, link_name)
|
# dst = joinpaths(self.isolinuxdir, kname)
|
||||||
else:
|
# shutil.copy2(kernel.fpath, dst)
|
||||||
# copy other kernels to pxebootdir
|
#
|
||||||
dst = joinpaths(self.pxebootdir, kname)
|
# # create hard link to main kernel in pxebootdir
|
||||||
shutil.copy2(kernel.fpath, dst)
|
# 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
|
# change the fname and fpath to new values
|
||||||
self.kernels.append(DataHolder(fname=kname,
|
self.kernels.append(DataHolder(fname=kname,
|
||||||
|
@ -32,6 +32,7 @@ import pwd
|
|||||||
import grp
|
import grp
|
||||||
import glob
|
import glob
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
def joinpaths(*args, **kwargs):
|
def joinpaths(*args, **kwargs):
|
||||||
@ -126,3 +127,11 @@ def remove_dm_dev(dev):
|
|||||||
cmd = ["dmsetup", "remove", dev]
|
cmd = ["dmsetup", "remove", dev]
|
||||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||||
return proc.wait()
|
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)
|
fullpattern = joinpaths(self.installroot, pattern)
|
||||||
count = 0
|
count = 0
|
||||||
for fname in glob.glob(fullpattern):
|
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):
|
if os.path.islink(fname) or os.path.isfile(fname):
|
||||||
os.unlink(fname)
|
os.unlink(fname)
|
||||||
else:
|
else:
|
||||||
@ -130,7 +134,7 @@ class LoraxYumHelper(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def process_transaction(self, skip_broken=True):
|
def process_transaction(self, skip_broken=False):
|
||||||
# skip broken
|
# skip broken
|
||||||
self.ybo.conf.skip_broken = skip_broken
|
self.ybo.conf.skip_broken = skip_broken
|
||||||
self.ybo.buildTransaction()
|
self.ybo.buildTransaction()
|
||||||
|
@ -74,7 +74,11 @@ def main(args):
|
|||||||
|
|
||||||
# parse the arguments
|
# parse the arguments
|
||||||
opts, args = parser.parse_args()
|
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:
|
if opts.showver:
|
||||||
print(version)
|
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