diff --git a/etc/initrd/includes/initrd.common b/etc/initrd/includes/initrd.common
deleted file mode 100644
index c0a74a38..00000000
--- a/etc/initrd/includes/initrd.common
+++ /dev/null
@@ -1,222 +0,0 @@
-# initrd template
-
-# create required directories
-makedir @initrd@/lib
-makedir @initrd@/modules
-makedir @initrd@/firmware
-link @initrd@/lib/modules to ../modules
-link @initrd@/lib/firmware to ../firmware
-makedir @initrd@/sbin
-makedir @initrd@/dev
-makedir @initrd@/etc
-makedir @initrd@/etc/udev/rules.d
-makedir @initrd@/lib/udev/rules.d
-makedir @initrd@/proc
-makedir @initrd@/selinux
-makedir @initrd@/sys
-makedir @initrd@/etc/terminfo/a
-makedir @initrd@/etc/terminfo/d
-makedir @initrd@/etc/terminfo/l
-makedir @initrd@/etc/terminfo/s
-makedir @initrd@/etc/terminfo/v
-makedir @initrd@/etc/terminfo/x
-makedir @initrd@/etc/terminfo/g
-makedir @initrd@/tmp
-makedir @initrd@/usr/libexec
-makedir @initrd@/usr/@libdir@/NetworkManager
-makedir @initrd@/usr/share/dbus-1/system-services
-makedir @initrd@/var/cache/hald
-makedir @initrd@/var/lib/dbus
-makedir @initrd@/var/lib/dhclient
-makedir @initrd@/var/lock/rpm
-makedir @initrd@/var/run
-makedir @initrd@/var/run/dbus
-makedir @initrd@/var/run/hald
-makedir @initrd@/var/run/NetworkManager
-makedir @initrd@/etc/dbus-1/system.d
-makedir @initrd@/etc/modprobe.d
-makedir @initrd@/etc/NetworkManager/dispatcher.d
-makedir @initrd@/@libdir@/dbus-1
-makedir @initrd@/etc/sysconfig/network-scripts
-makedir @initrd@/usr/share/PolicyKit/policy
-makedir @initrd@/etc/PolicyKit
-makedir @initrd@/var/lib/misc
-makedir @initrd@/etc/hal/fdi
-makedir @initrd@/usr/share/hal/fdi
-makedir @initrd@/usr/share/hwdata
-makedir @initrd@/etc/rc.d/init.d
-makedir @initrd@/usr/sbin
-makedir @initrd@/var/run/wpa_supplicant
-
-# set the buildarch
-edit @initrd@/etc/arch text "@buildarch@"
-
-# copy etc stuff
-copy @instroot@ etc/passwd to @initrd@ etc
-chmod @initrd@/etc/passwd mode 0644
-
-copy @instroot@ etc/group to @initrd@ etc
-chmod @initrd@/etc/group mode 0644
-
-copy @instroot@ etc/nsswitch.conf to @initrd@ etc
-chmod @initrd@/etc/nsswitch.conf mode 0644
-
-copy @instroot@ etc/hosts to @initrd@ etc
-chmod @initrd@/etc/hosts mode 0644
-
-# copy mount/umount
-copy @instroot@ bin/mount to @initrd@ sbin
-copy @instroot@ bin/umount to @initrd@ sbin
-copy @instroot@ sbin/mount.* to @initrd@ sbin
-copy @instroot@ sbin/umount.* to @initrd@ sbin
-
-# copy udev
-copy @instroot@ sbin/udevd to @initrd@ sbin
-copy @instroot@ sbin/udevadm to @initrd@ sbin
-link @initrd@/sbin/udevinfo to udevadm
-link @initrd@/sbin/udevsettle to udevadm
-
-# udev rules
-copy @instroot@ etc/udev/udev.conf to @initrd@ etc/udev
-chmod @initrd@/etc/udev/udev.conf mode 0644
-
-copy @instroot@ lib/udev/* to @initrd@ lib/udev
-#chmod @initrd@/lib/udev/* mode 0644
-
-remove @initrd@/lib/udev/rules.d/*persistent*
-remove @initrd@/lib/udev/rules.d/*generator*
-
-copy @instroot@ etc/udev/rules.d/*.rules to @initrd@ etc/udev/rules.d
-chmod @initrd@/etc/udev/rules.d/*.rules mode 0644
-
-# copy bash
-copy @instroot@ bin/bash to @initrd@ sbin
-link @initrd@/sbin/sh to bash
-
-copy @instroot@ sbin/consoletype to @initrd@ sbin
-copy @instroot@ usr/bin/logger to @initrd@ sbin
-
-copy @instroot@ etc/rc.d/init.d/functions to @initrd@ etc/rc.d/init.d
-copy @instroot@ etc/sysconfig/network-scripts/network-functions* to @initrd@ etc/sysconfig/network-scripts
-
-link @initrd@/etc/init.d to /etc/rc.d/init.d
-
-# dhcp and dhcpv6 client daemons and support programs
-copy @instroot@ sbin/dhclient to @initrd@ sbin
-copy @instroot@ sbin/dhclient-script to @initrd@ sbin
-copy @instroot@ sbin/dhcp6c to @initrd@ sbin
-copy @instroot@ sbin/arping to @initrd@ sbin
-copy @instroot@ sbin/ifconfig to @initrd@ sbin
-copy @instroot@ sbin/ip to @initrd@ sbin
-copy @instroot@ bin/ipcalc to @initrd@ sbin
-copy @instroot@ bin/hostname to @initrd@ sbin
-copy @instroot@ sbin/ethtool to @initrd@ sbin
-copy @instroot@ sbin/route to @initrd@ sbin
-touch @initrd@/etc/resolv.conf
-
-# hwdata
-copy @instroot@ usr/share/hwdata/pci.ids to @initrd@ usr/share/hwdata
-copy @instroot@ usr/share/hwdata/usb.ids to @initrd@ usr/share/hwdata
-
-# hal
-copy @instroot@ usr/sbin/hald to @initrd@ sbin
-copy @instroot@ usr/libexec/hald-runner to @initrd@ usr/libexec
-copy @instroot@ usr/libexec/hald-generate-fdi-cache to @initrd@ usr/libexec
-copy @instroot@ usr/libexec/hal*storage* to @initrd@ usr/libexec
-touch @initrd@/var/run/hald.acl-list
-copy @instroot@ usr/share/hal/fdi/* to @initrd@ usr/share/hal/fdi
-copy @instroot@ etc/hal/fdi/* to @initrd@ etc/hal/fdi
-copy @instroot@ etc/dbus-1/system.d/hal.conf to @initrd@ etc/dbus-1/system.d
-
-# policykit
-copy @instroot@ etc/PolicyKit/PolicyKit.conf to @initrd@ etc/PolicyKit
-copy @instroot@ usr/share/dbus-1/system-services/org.freedesktop.PolicyKit.service to @initrd@ usr/share/dbus-1/system-services
-copy @instroot@ usr/share/PolicyKit/policy/org.freedesktop.policykit.policy to @initrd@ usr/share/PolicyKit/policy
-copy @instroot@ var/lib/misc/PolicyKit.reload to @initrd@ var/lib/misc
-
-# dbus
-copy @instroot@ bin/dbus-uuidgen to @initrd@ sbin
-copy @instroot@ bin/dbus-daemon to @initrd@ sbin
-copy @instroot@ etc/dbus-1/system.conf to @initrd@ etc/dbus-1
-copy @instroot@ @libdir@/dbus-1/dbus-daemon-launch-helper to @initrd@ @libdir@/dbus-1
-chown @initrd@/@libdir@/dbus-1/dbus-daemon-launch-helper user root group dbus
-chmod @initrd@/@libdir@/dbus-1/dbus-daemon-launch-helper mode 04750
-
-# wpa_supplicant
-copy @instroot@ usr/sbin/wpa_passphrase to @initrd@ usr/sbin
-copy @instroot@ usr/sbin/wpa_supplicant to @initrd@ usr/sbin
-copy @instroot@ etc/dbus-1/system.d/wpa_supplicant.conf to @initrd@ etc/dbus-1/system.d
-copy @instroot@ etc/wpa_supplicant/wpa_supplicant.conf to @initrd@ etc/wpa_supplicant
-copy @instroot@ usr/share/dbus-1/system-services/fi.epitest.hostap.WPASupplicant.service to @initrd@ usr/share/dbus-1/system-services
-
-# networkmanager
-copy @instroot@ usr/sbin/NetworkManager to @initrd@ usr/sbin
-copy @instroot@ usr/sbin/nm-system-settings to @initrd@ usr/sbin
-copy @instroot@ etc/dbus-1/system.d/nm-*.conf to @initrd@ etc/dbus-1/system.d
-copy @instroot@ etc/dbus-1/system.d/NetworkManager.conf to @initrd@ etc/dbus-1/system.d
-copy @instroot@ etc/NetworkManager/nm-system-settings.conf to @initrd@ etc/NetworkManager
-copy @instroot@ usr/@libdir@/NetworkManager/libnm-settings-plugin-ifcfg-fedora.so to @initrd@ usr/@libdir@/NetworkManager
-copy @instroot@ usr/libexec/nm-* to @initrd@ usr/libexec
-copy @instroot@ usr/share/dbus-1/system-services/org.freedesktop.NetworkManagerSystemSettings.service to @initrd@ usr/share/dbus-1/system-services
-copy @instroot@ usr/share/dbus-1/system-services/org.freedesktop.nm_dispatcher.service to @initrd@ usr/share/dbus-1/system-services
-
-# modprobe
-copy @instroot@ sbin/modprobe to @initrd@ sbin
-copy @instroot@ sbin/insmod to @initrd@ sbin
-copy @instroot@ sbin/rmmod to @initrd@ sbin
-
-# profile
-edit @initrd@/.profile text "PATH=/bin:/usr/bin:/usr/sbin:/mnt/sysimage/sbin:/mnt/sysimage/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin\nexport PATH"
-
-# terminfos
-copy @instroot@ usr/share/terminfo/a/ansi to @initrd@ etc/terminfo/a nolinks
-copy @instroot@ usr/share/terminfo/d/dumb to @initrd@ etc/terminfo/d nolinks
-copy @instroot@ usr/share/terminfo/l/linux to @initrd@ etc/terminfo/l nolinks
-copy @instroot@ usr/share/terminfo/s/screen to @initrd@ etc/terminfo/s nolinks
-copy @instroot@ usr/share/terminfo/v/vt100 to @initrd@ etc/terminfo/v nolinks
-copy @instroot@ usr/share/terminfo/v/vt100-nav to @initrd@ etc/terminfo/v nolinks
-copy @instroot@ usr/share/terminfo/v/vt102 to @initrd@ etc/terminfo/v nolinks
-copy @instroot@ usr/share/terminfo/x/xterm to @initrd@ etc/terminfo/x nolinks
-copy @instroot@ usr/share/terminfo/x/xterm-color to @initrd@ etc/terminfo/x nolinks
-copy @instroot@ usr/share/terminfo/g/gnome to @initrd@ etc/terminfo/g nolinks
-chmod @initrd@/etc/terminfo/*/* mode 0644
-
-# misc
-copy @instroot@ bin/awk to @initrd@ sbin
-copy @instroot@ bin/gawk to @initrd@ sbin
-copy @instroot@ bin/egrep to @initrd@ sbin
-copy @instroot@ bin/fgrep to @initrd@ sbin
-copy @instroot@ bin/grep to @initrd@ sbin
-copy @instroot@ bin/kill to @initrd@ sbin
-copy @instroot@ bin/ln to @initrd@ sbin
-copy @instroot@ bin/readlink to @initrd@ sbin
-copy @instroot@ bin/rm to @initrd@ sbin
-copy @instroot@ bin/rmdir to @initrd@ sbin
-copy @instroot@ bin/sed to @initrd@ sbin
-copy @instroot@ bin/sleep to @initrd@ sbin
-copy @instroot@ bin/touch to @initrd@ sbin
-
-link @initrd@/init to /sbin/init
-link @initrd@/etc/mtab to /proc/mounts
-link @initrd@/bin to sbin
-link @initrd@/var/lib/xkb to ../../tmp
-
-# loader
-copy @instroot@ usr/lib/anaconda-runtime/loader/loader to @initrd@ sbin
-copy @instroot@ usr/lib/anaconda-runtime/loader/loader.tr to @initrd@ etc
-chmod @initrd/etc/loader.tr mode 0644
-
-# indirect dependencies
-copy @instroot@ @libdir@/ld-linux.so.2 to @initrd@ @libdir@
-#copy @instroot@ @libdir@/libcom_err.so.2 to @initrd@ @libdir@
-#copy @instroot@ @libdir@/libdbus-glib-1.so.2 to @initrd@ @libdir@
-#copy @instroot@ @libdir@/libfreebl3.so to @initrd@ @libdir@
-copy @instroot@ @libdir@/libgcc_s.so.1 to @initrd@ @libdir@
-copy @instroot@ @libdir@/libnss_dns.so.2 to @initrd@ @libdir@
-copy @instroot@ @libdir@/libnss_files.so.2 to @initrd@ @libdir@
-copy @instroot@ @libdir@/libsoftokn3.so to @initrd@ @libdir@
-
-copy @instroot@ usr/@libdir@/libsqlite3.so.0 to @initrd@ usr/@libdir@
-
-# langtable
-copy @instroot@ usr/lib/anaconda/lang-table to @initrd@ etc
diff --git a/etc/initrd/initrd.alpha b/etc/initrd/initrd.alpha
deleted file mode 120000
index 7f5d6354..00000000
--- a/etc/initrd/initrd.alpha
+++ /dev/null
@@ -1 +0,0 @@
-initrd.i386
\ No newline at end of file
diff --git a/etc/initrd/initrd.i386 b/etc/initrd/initrd.i386
deleted file mode 100644
index b6c71784..00000000
--- a/etc/initrd/initrd.i386
+++ /dev/null
@@ -1,12 +0,0 @@
-# initrd template
-
-#include includes/initrd.common
-
-# loader
-copy @instroot@ usr/lib/anaconda-runtime/loader/init to @initrd@ sbin/init
-link @initrd@/sbin/reboot to init
-link @initrd@/sbin/halt to init
-link @initrd@/sbin/poweroff to init
-
-# screenfont
-copy @instroot@ usr/lib/anaconda-runtime/screenfont-@buildarch@.gz to @initrd@ etc/screenfont.gz
diff --git a/etc/initrd/initrd.ia64 b/etc/initrd/initrd.ia64
deleted file mode 120000
index 7f5d6354..00000000
--- a/etc/initrd/initrd.ia64
+++ /dev/null
@@ -1 +0,0 @@
-initrd.i386
\ No newline at end of file
diff --git a/etc/initrd/initrd.ppc b/etc/initrd/initrd.ppc
deleted file mode 120000
index 7f5d6354..00000000
--- a/etc/initrd/initrd.ppc
+++ /dev/null
@@ -1 +0,0 @@
-initrd.i386
\ No newline at end of file
diff --git a/etc/initrd/initrd.ppc64 b/etc/initrd/initrd.ppc64
deleted file mode 120000
index 24600f3b..00000000
--- a/etc/initrd/initrd.ppc64
+++ /dev/null
@@ -1 +0,0 @@
-initrd.ppc
\ No newline at end of file
diff --git a/etc/initrd/initrd.s390 b/etc/initrd/initrd.s390
deleted file mode 100644
index cf079699..00000000
--- a/etc/initrd/initrd.s390
+++ /dev/null
@@ -1,54 +0,0 @@
-# initrd template
-
-#include includes/initrd.common
-
-# create required directories
-makedir @initrd@/var/empty/sshd mode 0111
-makedir @initrd@/etc/pam.d
-makedir @initrd@/etc/security
-makedir @initrd@/@libdir@/security
-
-# copy some files
-copy @instroot@ usr/bin/xauth to @initrd@ sbin
-copy @instroot@ usr/sbin/cmsfs* to @initrd@ sbin
-
-copy @instroot@ @libdir@/libpam_misc.so.0.* to @initrd@ @libdir@/libpam_misc.so.0
-copy @instroot@ @libdir@/libwrap*.so* to @initrd@ @libdir@
-
-link @initrd@/var/state/xkb to /tmp
-
-# loader
-copy @instroot@ usr/lib/anaconda-runtime/loader/shutdown to @initrd@ sbin
-copy @instroot@ usr/lib/anaconda-runtime/loader/linuxrc.s390 to @initrd@ sbin/init
-copy @instroot@ usr/lib/anaconda-runtime/loader/lsznet.raw to @initrd@ sbin/lsznet
-copy @instroot@ usr/lib/anaconda-runtime/loader/controlunits.sh @initrd@ sbin/controlunits
-copy @instroot@ usr/sbin/dasdfmt to @initrd@ sbin
-
-# setup shell environment
-edit @initrd@/etc/protocols text "tcp\t6\tTCP\n"
-
-copy @instroot@ @libdir@/security/pam_limits.so to @initrd@ @libdir@/security
-copy @instroot@ @libdir@/security/pam_env.so to @initrd@ @libdir@/security
-copy @instroot@ @libdir@/security/pam_unix.so to @initrd@ @libdir@/security
-copy @instroot@ @libdir@/security/pam_deny.so to @initrd@ @libdir@/security
-
-copy @instroot@ etc/pam.d/other to @initrd@ etc/pam.d
-copy @datadir@ pam.d/login to @initrd@ etc/pam.d/login
-copy @datadir@ pam.d/login to @initrd@ etc/pam.d/sshd
-copy @datadir@ pam.d/login to @initrd@ etc/pam.d/remote
-
-copy @instroot@ etc/security/limits.conf to @initrd@ etc/security
-copy @Instroot@ etc/security/pam_env.conf to @initrd@ etc/security
-
-# generate keys
-makedir @initrd@/etc/ssh mode 0700
-genkey @initrd@/etc/ssh/ssh_host_key type rsa1
-genkey @initrd@/etc/ssh/ssh_host_rsa_key type rsa
-genkey @initrd@/etc/ssh/ssh_host_dsa_key type dsa
-
-copy @datadir@ sshd/sshd_config to @initrd@ etc/ssh/sshd_config
-chmod @initrd@/etc/ssh/sshd_config mode 0600
-
-# copy in the binaries
-copy @instroot@ bin/login to @initrd@ sbin/login
-copy @instroot@ usr/sbin/sshd to @initrd@ sbin/sshd
diff --git a/etc/initrd/initrd.s390x b/etc/initrd/initrd.s390x
deleted file mode 120000
index 07ba502b..00000000
--- a/etc/initrd/initrd.s390x
+++ /dev/null
@@ -1 +0,0 @@
-initrd.s390
\ No newline at end of file
diff --git a/etc/initrd/initrd.sparc b/etc/initrd/initrd.sparc
deleted file mode 120000
index 7f5d6354..00000000
--- a/etc/initrd/initrd.sparc
+++ /dev/null
@@ -1 +0,0 @@
-initrd.i386
\ No newline at end of file
diff --git a/etc/initrd/initrd.x86_64 b/etc/initrd/initrd.x86_64
deleted file mode 120000
index 7f5d6354..00000000
--- a/etc/initrd/initrd.x86_64
+++ /dev/null
@@ -1 +0,0 @@
-initrd.i386
\ No newline at end of file
diff --git a/etc/lorax/config.i386 b/etc/lorax/config.i386
new file mode 100644
index 00000000..3783aada
--- /dev/null
+++ b/etc/lorax/config.i386
@@ -0,0 +1,8 @@
+[lorax]
+
+packages:
+ grub gpart syslinux memtest86+ efibootmgr dmidecode pcmciautils
+ kernel-PAE
+
+initrd_template=templates/initrd/initrd.i386
+scrubs_template=templates/scrubs/scrubs.i386
diff --git a/etc/lorax/config.i586 b/etc/lorax/config.i586
new file mode 120000
index 00000000..744d7dfd
--- /dev/null
+++ b/etc/lorax/config.i586
@@ -0,0 +1 @@
+config.i386
\ No newline at end of file
diff --git a/etc/lorax/config.noarch b/etc/lorax/config.noarch
new file mode 100644
index 00000000..aa95e3bf
--- /dev/null
+++ b/etc/lorax/config.noarch
@@ -0,0 +1,23 @@
+[lorax]
+
+packages:
+ anaconda kernel *firmware* joe gnome-icon-theme fedora-icon-theme
+ xorg-x11-server-Xorg firstaidkit bzip2 busybox selinux-policy-targeted
+ python-imaging hal specspo xorg-x11-fonts-misc xorg-x11-drivers rhpxl
+ ntfs-3g ntfsprogs xfsprogs xfsdump reiserfs-utils gfs2-utils jfsutils
+ nfs-utils btrfs-progs mesa-dri-drivers dogtail rsh rsync prelink
+ smartmontools iscsi-initiator-utils samba-client mtr gtk-nodoka-engine
+ ftp openssh-clients gtk+ gdk-pixbuf madan-fonts lklug-fonts
+ xorg-x11-fonts-ethiopic un-core-fonts-dotum man yum-fedorakmod
+ /etc/gtk-2.0/gtkrc
+
+modules:
+ sunrpc lockd floppy cramfs loop edd pcspkr squashfs
+ ipv6 virtio_pci ohci-hcd uhci-hcd ehci-hcd usbhid mousedev usb-storage
+ sd_mod sr_mod ub appletouch ohci1394 sbp2 fw-ohci fw-sbp2 firewire-sbp2
+ firewire-ohci mmc-block sdhci sdhci-pci ide-cd ide-cd_mod sr_mod sg st
+ sd_mod scsi_mod iscsi_tcp iscsi_ibft fat msdos vfat ext2 ext3 ext4 reiserfs
+ jfs xfs gfs2 cifs nfs fuse btrfs dm-mod dm-zero dm-snapshot dm-mirror
+ dm-multipath dm-round-robin dm-crypt raid0 raid1 raid5 raid6 raid456 raid10
+ linear sha256_generic cbc xts lrw aes_generic crypto_blkcipher crc32c ecb
+ arc4 yenta_socket i82365 tcic pcmcia =scsi =net =drm
diff --git a/etc/lorax/config.s390 b/etc/lorax/config.s390
new file mode 100644
index 00000000..5593f498
--- /dev/null
+++ b/etc/lorax/config.s390
@@ -0,0 +1,11 @@
+[lorax]
+
+packages: s390utils binutils libgcc tcp_wrappers sed net-tools openssh
+ openssh-server coreutils login initscripts portmap pam mount modutils
+ s390utils-cmsfs strace xorg-x11-xauth xorg-x11-libs
+
+modules: zfcp tape390 dasd_diag_mod dasd_eckd_mod dasd_fba_mod dasd_mod
+ ctc netiucv smsgiucv lcs qdio qeth ccwgroup crypto_api xfrm_nalgo
+
+initrd_template=templates/initrd/initrd.s390
+scrubs_template=templates/scrubs/scrubs.s390
diff --git a/etc/lorax/config.s390x b/etc/lorax/config.s390x
new file mode 120000
index 00000000..5c0bf0e5
--- /dev/null
+++ b/etc/lorax/config.s390x
@@ -0,0 +1 @@
+config.s390
\ No newline at end of file
diff --git a/etc/lorax/config.x86_64 b/etc/lorax/config.x86_64
new file mode 120000
index 00000000..744d7dfd
--- /dev/null
+++ b/etc/lorax/config.x86_64
@@ -0,0 +1 @@
+config.i386
\ No newline at end of file
diff --git a/etc/lorax/templates/initrd/includes/initrd b/etc/lorax/templates/initrd/includes/initrd
new file mode 100644
index 00000000..b2fc47b9
--- /dev/null
+++ b/etc/lorax/templates/initrd/includes/initrd
@@ -0,0 +1,242 @@
+## create required directories
+makedirs ${initrd}/lib
+makedirs ${initrd}/modules
+makedirs ${initrd}/firmware
+symlink name ${initrd}/lib/modules target ../modules
+symlink name ${initrd}/lib/firmware target ../firmware
+
+makedirs ${initrd}/sbin
+makedirs ${initrd}/dev
+makedirs ${initrd}/etc
+makedirs ${initrd}/etc/udev/rules.d
+makedirs ${initrd}/lib/udev/rules.d
+makedirs ${initrd}/proc
+makedirs ${initrd}/selinux
+makedirs ${initrd}/sys
+makedirs ${initrd}/etc/terminfo/{a,d,l,s,v,x,g}
+makedirs ${initrd}/tmp
+makedirs ${initrd}/usr/libexec
+makedirs ${initrd}/usr/${libdir}/NetworkManager
+makedirs ${initrd}/usr/share/dbus-1/system-services
+makedirs ${initrd}/var/cache/hald
+makedirs ${initrd}/var/lib/dbus
+makedirs ${initrd}/var/lib/dhclient
+makedirs ${initrd}/var/lock/rpm
+makedirs ${initrd}/var/run
+makedirs ${initrd}/var/run/dbus
+makedirs ${initrd}/var/run/hald
+makedirs ${initrd}/var/run/NetworkManager
+makedirs ${initrd}/etc/dbus-1/system.d
+makedirs ${initrd}/etc/modprobe.d
+makedirs ${initrd}/etc/NetworkManager/dispatcher.d
+makedirs ${initrd}/${libdir}/dbus-1
+makedirs ${initrd}/etc/sysconfig/network-scripts
+makedirs ${initrd}/usr/share/PolicyKit/policy
+makedirs ${initrd}/etc/PolicyKit
+makedirs ${initrd}/var/lib/misc
+makedirs ${initrd}/etc/hal/fdi
+makedirs ${initrd}/usr/share/hal/fdi
+makedirs ${initrd}/usr/share/hwdata
+makedirs ${initrd}/etc/rc.d/init.d
+makedirs ${initrd}/usr/sbin
+makedirs ${initrd}/var/run/wpa_supplicant
+
+## set the buildarch
+edit ${initrd}/etc/arch text "${arch}"
+
+## copy etc stuff
+copy ${instroot} etc/passwd to ${initrd} etc
+chmod ${initrd}/etc/passwd mode 0644
+
+copy ${instroot} etc/group to ${initrd} etc
+chmod ${initrd}/etc/group mode 0644
+
+copy ${instroot} etc/nsswitch.conf to ${initrd} etc
+chmod ${initrd}/etc/nsswitch.conf mode 0644
+
+copy ${instroot} etc/hosts to ${initrd} etc
+chmod ${initrd}/etc/hosts mode 0644
+
+## copy mount/umount
+copy ${instroot} bin/mount to ${initrd} sbin
+copy ${instroot} bin/umount to ${initrd} sbin
+copy ${instroot} sbin/mount.* to ${initrd} sbin
+copy ${instroot} sbin/umount.* to ${initrd} sbin
+
+## copy udev
+copy ${instroot} sbin/udevd to ${initrd} sbin
+copy ${instroot} sbin/udevadm to ${initrd} sbin
+symlink name ${initrd}/sbin/udevinfo target udevadm
+symlink name ${initrd}/sbin/udevsettle target udevadm
+
+## udev rules
+copy ${instroot} etc/udev/udev.conf to ${initrd} etc/udev
+chmod ${initrd}/etc/udev/udev.conf mode 0644
+
+copy ${instroot} lib/udev/* to ${initrd} lib/udev
+##chmod ${initrd}/lib/udev/* mode 0644
+
+remove ${initrd}/lib/udev/rules.d/*persistent*
+remove ${initrd}/lib/udev/rules.d/*generator*
+
+copy ${instroot} etc/udev/rules.d/*.rules to ${initrd} etc/udev/rules.d
+chmod ${initrd}/etc/udev/rules.d/*.rules mode 0644
+
+## copy bash
+copy ${instroot} bin/bash to ${initrd} sbin
+symlink name ${initrd}/sbin/sh target bash
+
+copy ${instroot} sbin/consoletype to ${initrd} sbin
+copy ${instroot} usr/bin/logger to ${initrd} sbin
+
+copy ${instroot} etc/rc.d/init.d/functions to ${initrd} etc/rc.d/init.d
+copy ${instroot} etc/sysconfig/network-scripts/network-functions* to \
+ ${initrd} etc/sysconfig/network-scripts
+
+symlink name ${initrd}/etc/init.d target /etc/rc.d/init.d
+
+## dhcp and dhcpv6 client daemons and support programs
+copy ${instroot} sbin/dhclient to ${initrd} sbin
+copy ${instroot} sbin/dhclient-script to ${initrd} sbin
+copy ${instroot} sbin/dhcp6c to ${initrd} sbin
+copy ${instroot} sbin/arping to ${initrd} sbin
+copy ${instroot} sbin/ifconfig to ${initrd} sbin
+copy ${instroot} sbin/ip to ${initrd} sbin
+copy ${instroot} bin/ipcalc to ${initrd} sbin
+copy ${instroot} bin/hostname to ${initrd} sbin
+copy ${instroot} sbin/ethtool to ${initrd} sbin
+copy ${instroot} sbin/route to ${initrd} sbin
+touch ${initrd}/etc/resolv.conf
+
+## hwdata
+copy ${instroot} usr/share/hwdata/pci.ids to ${initrd} usr/share/hwdata
+copy ${instroot} usr/share/hwdata/usb.ids to ${initrd} usr/share/hwdata
+
+## hal
+copy ${instroot} usr/sbin/hald to ${initrd} sbin
+copy ${instroot} usr/libexec/hald-runner to ${initrd} usr/libexec
+copy ${instroot} usr/libexec/hald-generate-fdi-cache to ${initrd} usr/libexec
+copy ${instroot} usr/libexec/hal*storage* to ${initrd} usr/libexec
+touch ${initrd}/var/run/hald.acl-list
+copy ${instroot} usr/share/hal/fdi/* to ${initrd} usr/share/hal/fdi
+copy ${instroot} etc/hal/fdi/* to ${initrd} etc/hal/fdi
+copy ${instroot} etc/dbus-1/system.d/hal.conf to ${initrd} etc/dbus-1/system.d
+
+## policykit
+copy ${instroot} etc/PolicyKit/PolicyKit.conf to ${initrd} etc/PolicyKit
+copy ${instroot} \
+ usr/share/dbus-1/system-services/org.freedesktop.PolicyKit.service to \
+ ${initrd} usr/share/dbus-1/system-services
+
+copy ${instroot} usr/share/PolicyKit/policy/org.freedesktop.policykit.policy \
+ to ${initrd} usr/share/PolicyKit/policy
+
+copy ${instroot} var/lib/misc/PolicyKit.reload to ${initrd} var/lib/misc
+
+## dbus
+copy ${instroot} bin/dbus-uuidgen to ${initrd} sbin
+copy ${instroot} bin/dbus-daemon to ${initrd} sbin
+copy ${instroot} etc/dbus-1/system.conf to ${initrd} etc/dbus-1
+copy ${instroot} ${libdir}/dbus-1/dbus-daemon-launch-helper to \
+ ${initrd} ${libdir}/dbus-1
+
+chown ${initrd}/${libdir}/dbus-1/dbus-daemon-launch-helper user root group dbus
+chmod ${initrd}/${libdir}/dbus-1/dbus-daemon-launch-helper mode 04750
+
+## wpa_supplicant
+copy ${instroot} usr/sbin/wpa_passphrase to ${initrd} usr/sbin
+copy ${instroot} usr/sbin/wpa_supplicant to ${initrd} usr/sbin
+copy ${instroot} etc/dbus-1/system.d/wpa_supplicant.conf to \
+ ${initrd} etc/dbus-1/system.d
+
+copy ${instroot} etc/wpa_supplicant/wpa_supplicant.conf to \
+ ${initrd} etc/wpa_supplicant
+
+copy ${instroot} \
+ usr/share/dbus-1/system-services/fi.epitest.hostap.WPASupplicant.service \
+ to ${initrd} usr/share/dbus-1/system-services
+
+## networkmanager
+copy ${instroot} usr/sbin/NetworkManager to ${initrd} usr/sbin
+copy ${instroot} usr/sbin/nm-system-settings to ${initrd} usr/sbin
+copy ${instroot} etc/dbus-1/system.d/nm-*.conf to ${initrd} etc/dbus-1/system.d
+copy ${instroot} etc/dbus-1/system.d/NetworkManager.conf to \
+ ${initrd} etc/dbus-1/system.d
+copy ${instroot} etc/NetworkManager/nm-system-settings.conf to \
+ ${initrd} etc/NetworkManager
+copy ${instroot} \
+ usr/${libdir}/NetworkManager/libnm-settings-plugin-ifcfg-fedora.so to \
+ ${initrd} usr/${libdir}/NetworkManager
+copy ${instroot} usr/libexec/nm-* to ${initrd} usr/libexec
+copy ${instroot} usr/share/dbus-1/system-services/org.freedesktop.NetworkManagerSystemSettings.service to ${initrd} usr/share/dbus-1/system-services
+copy ${instroot} usr/share/dbus-1/system-services/org.freedesktop.nm_dispatcher.service to ${initrd} usr/share/dbus-1/system-services
+
+## modprobe
+copy ${instroot} sbin/modprobe to ${initrd} sbin
+copy ${instroot} sbin/insmod to ${initrd} sbin
+copy ${instroot} sbin/rmmod to ${initrd} sbin
+
+## profile
+edit ${initrd}/.profile text "PATH=/bin:/usr/bin:/usr/sbin:/mnt/sysimage/sbin:/mnt/sysimage/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin\nexport PATH"
+
+## terminfos
+copy ${instroot} usr/share/terminfo/a/ansi to ${initrd} etc/terminfo/a \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/d/dumb to ${initrd} etc/terminfo/d \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/l/linux to ${initrd} etc/terminfo/l \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/s/screen to ${initrd} etc/terminfo/s \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/v/vt100 to ${initrd} etc/terminfo/v \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/v/vt100-nav to ${initrd} etc/terminfo/v \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/v/vt102 to ${initrd} etc/terminfo/v \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/x/xterm to ${initrd} etc/terminfo/x \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/x/xterm-color to ${initrd} etc/terminfo/x \
+ nosymlinks
+copy ${instroot} usr/share/terminfo/g/gnome to ${initrd} etc/terminfo/g \
+ nosymlinks
+chmod ${initrd}/etc/terminfo/*/* mode 0644
+
+## misc
+copy ${instroot} bin/awk to ${initrd} sbin
+copy ${instroot} bin/gawk to ${initrd} sbin
+copy ${instroot} bin/egrep to ${initrd} sbin
+copy ${instroot} bin/fgrep to ${initrd} sbin
+copy ${instroot} bin/grep to ${initrd} sbin
+copy ${instroot} bin/kill to ${initrd} sbin
+copy ${instroot} bin/ln to ${initrd} sbin
+copy ${instroot} bin/readlink to ${initrd} sbin
+copy ${instroot} bin/rm to ${initrd} sbin
+copy ${instroot} bin/rmdir to ${initrd} sbin
+copy ${instroot} bin/sed to ${initrd} sbin
+copy ${instroot} bin/sleep to ${initrd} sbin
+copy ${instroot} bin/touch to ${initrd} sbin
+
+symlink name ${initrd}/init target /sbin/init
+symlink name ${initrd}/etc/mtab target /proc/mounts
+symlink name ${initrd}/bin target sbin
+symlink name ${initrd}/var/lib/xkb target ../../tmp
+
+## loader
+copy ${instroot} usr/lib/anaconda-runtime/loader/loader to ${initrd} sbin
+copy ${instroot} usr/lib/anaconda-runtime/loader/loader.tr to ${initrd} etc
+chmod ${initrd}/etc/loader.tr mode 0644
+
+## indirect dependencies
+##copy ${instroot} ${libdir}/ld-linux.so.2 to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libcom_err.so.2 to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libdbus-glib-1.so.2 to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libfreebl3.so to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libgcc_s.so.1 to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libnss_dns.so.2 to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libnss_files.so.2 to ${initrd} ${libdir}
+copy ${instroot} ${libdir}/libsoftokn3.so to ${initrd} ${libdir}
+copy ${instroot} usr/${libdir}/libsqlite3.so.0 to ${initrd} usr/${libdir}
+
+## langtable
+copy ${instroot} usr/lib/anaconda/lang-table to ${initrd} etc
diff --git a/etc/lorax/templates/initrd/initrd.i386 b/etc/lorax/templates/initrd/initrd.i386
new file mode 100644
index 00000000..7e148591
--- /dev/null
+++ b/etc/lorax/templates/initrd/initrd.i386
@@ -0,0 +1,11 @@
+<%include file="includes/initrd" />
+
+## loader
+copy ${instroot} usr/lib/anaconda-runtime/loader/init to ${initrd} sbin/init
+symlink name ${initrd}/sbin/reboot target init
+symlink name ${initrd}/sbin/halt target init
+symlink name ${initrd}/sbin/poweroff target init
+
+## screenfont
+copy ${instroot} usr/lib/anaconda-runtime/screenfont-${arch}.gz to \
+ ${initrd} etc/screenfont.gz
diff --git a/etc/lorax/templates/initrd/initrd.s390 b/etc/lorax/templates/initrd/initrd.s390
new file mode 100644
index 00000000..1093bec8
--- /dev/null
+++ b/etc/lorax/templates/initrd/initrd.s390
@@ -0,0 +1,51 @@
+<%include file="includes/initrd" />
+
+## create required directories
+makedirs ${initrd}/var/empty/sshd mode 0111
+makedirs ${initrd}/etc/security
+makedirs ${initrd}/${libdir}/security
+
+## copy some files
+copy ${instroot} usr/bin/xauth to ${initrd} sbin
+copy ${instroot} usr/sbin/cmsfs* to ${initrd} sbin
+
+copy ${instroot} ${libdir}/libpam_misc.so.0.* to ${initrd} ${libdir}/libpam_misc.so.0
+copy ${instroot} ${libdir}/libwrap*.so* to ${initrd} ${libdir}
+
+symlink name ${initrd}/var/state/xkb target /tmp
+
+## loader
+copy ${instroot} usr/lib/anaconda-runtime/loader/shutdown to ${initrd} sbin
+copy ${instroot} usr/lib/anaconda-runtime/loader/linuxrc.s390 to \
+ ${initrd} sbin/init
+copy ${instroot} usr/lib/anaconda-runtime/loader/lsznet.raw to \
+ ${initrd} sbin/lsznet
+copy ${instroot} usr/lib/anaconda-runtime/loader/controlunits.sh to \
+ ${initrd} sbin/controlunits
+copy ${instroot} usr/sbin/dasdfmt to ${initrd} sbin
+
+## setup shell environment
+edit ${initrd}/etc/protocols text "tcp\t6\tTCP\n"
+
+copy ${instroot} ${libdir}/security/pam_limits.so to \
+ ${initrd} ${libdir}/security
+copy ${instroot} ${libdir}/security/pam_env.so to ${initrd} ${libdir}/security
+copy ${instroot} ${libdir}/security/pam_unix.so to ${initrd} ${libdir}/security
+copy ${instroot} ${libdir}/security/pam_deny.so to ${initrd} ${libdir}/security
+
+copy ${instroot} etc/pam.d/other to ${initrd} etc/pam.d
+
+copy ${instroot} etc/security/limits.conf to ${initrd} etc/security
+copy ${instroot} etc/security/pam_env.conf to ${initrd} etc/security
+
+## generate ssh keys
+makedirs ${initrd}/etc/ssh mode 0700
+gensshkey ${initrd}/etc/ssh/ssh_host_key type rsa1
+gensshkey ${initrd}/etc/ssh/ssh_host_rsa_key type rsa
+gensshkey ${initrd}/etc/ssh/ssh_host_dsa_key type dsa
+
+chmod ${initrd}/etc/ssh/sshd_config mode 0600
+
+## copy in the binaries
+copy ${instroot} bin/login to ${initrd} sbin/login
+copy ${instroot} usr/sbin/sshd to ${initrd} sbin/sshd
diff --git a/etc/lorax/templates/scrubs/scrubs.i386 b/etc/lorax/templates/scrubs/scrubs.i386
new file mode 100644
index 00000000..a35c0ee1
--- /dev/null
+++ b/etc/lorax/templates/scrubs/scrubs.i386
@@ -0,0 +1,103 @@
+## remove unnecessary directories from /
+remove ${instroot}/boot
+remove ${instroot}/dev
+remove ${instroot}/home
+remove ${instroot}/media
+remove ${instroot}/mnt
+remove ${instroot}/opt
+remove ${instroot}/root
+remove ${instroot}/selinux
+remove ${instroot}/srv
+remove ${instroot}/sys
+remove ${instroot}/tmp
+
+## remove directories from /usr
+remove ${instroot}/usr/etc
+remove ${instroot}/usr/games
+remove ${instroot}/usr/include
+remove ${instroot}/usr/kerberos
+remove ${instroot}/usr/local
+remove ${instroot}/usr/tmp
+
+## remove modules and firmware directories
+remove ${instroot}/lib/modules
+remove ${instroot}/lib/firmware
+
+## remove directories from /var
+remove ${instroot}/var/db
+remove ${instroot}/var/empty
+remove ${instroot}/var/games
+remove ${instroot}/var/local
+remove ${instroot}/var/lock
+remove ${instroot}/var/log
+remove ${instroot}/var/mail
+remove ${instroot}/var/nis
+remove ${instroot}/var/opt
+remove ${instroot}/var/preserve
+remove ${instroot}/var/spool
+remove ${instroot}/var/tmp
+remove ${instroot}/var/yp
+
+## remove directories from /lib
+remove ${instroot}/lib/i686
+remove ${instroot}/lib/kbd
+remove ${instroot}/lib/rtkaio
+remove ${instroot}/lib/security
+remove ${instroot}/lib/tls
+remove ${instroot}/lib/xtables
+
+## remove directories from /etc
+remove ${instroot}/etc/ConsoleKit
+remove ${instroot}/etc/X11
+remove ${instroot}/etc/alternatives
+remove ${instroot}/etc/asterisk
+remove ${instroot}/etc/avahi
+remove ${instroot}/etc/blkid
+remove ${instroot}/etc/bonobo*
+remove ${instroot}/etc/chkconfig*
+remove ${instroot}/etc/cron.*
+remove ${instroot}/etc/default
+remove ${instroot}/etc/depmod.d
+remove ${instroot}/etc/dirmngr
+remove ${instroot}/etc/dnsmasq.d
+remove ${instroot}/etc/event.d
+remove ${instroot}/etc/firmware
+remove ${instroot}/etc/firstaidkit
+remove ${instroot}/etc/gconf
+remove ${instroot}/etc/gcrypt
+remove ${instroot}/etc/gnome-vfs*
+remove ${instroot}/etc/gnupg
+remove ${instroot}/etc/gtk
+remove ${instroot}/etc/hotplug
+remove ${instroot}/etc/init.d
+remove ${instroot}/etc/iproute2
+remove ${instroot}/etc/iscsi
+remove ${instroot}/etc/kernel
+remove ${instroot}/etc/ld.so.conf.d
+remove ${instroot}/etc/logrotate.d
+remove ${instroot}/etc/lvm
+remove ${instroot}/etc/makedev.d
+remove ${instroot}/etc/modprobe.d
+remove ${instroot}/etc/netplug*
+remove ${instroot}/etc/ntp
+remove ${instroot}/etc/openldap
+remove ${instroot}/etc/opt
+remove ${instroot}/etc/pam.d
+remove ${instroot}/etc/pki
+remove ${instroot}/etc/pm
+remove ${instroot}/etc/popt.d
+remove ${instroot}/etc/ppp
+remove ${instroot}/etc/prelink.conf.d
+remove ${instroot}/etc/profile.d
+remove ${instroot}/etc/rc?.d
+remove ${instroot}/etc/rwtab.d
+remove ${instroot}/etc/samba
+remove ${instroot}/etc/sasl2
+remove ${instroot}/etc/security
+remove ${instroot}/etc/setuptool.d
+remove ${instroot}/etc/skel
+remove ${instroot}/etc/ssh
+remove ${instroot}/etc/statetab.d
+remove ${instroot}/etc/terminfo
+remove ${instroot}/etc/xdg
+remove ${instroot}/etc/xinetd.d
diff --git a/etc/tree/scrubs.s390 b/etc/lorax/templates/scrubs/scrubs.s390
similarity index 100%
rename from etc/tree/scrubs.s390
rename to etc/lorax/templates/scrubs/scrubs.s390
diff --git a/etc/modules/modules.all b/etc/modules/modules.all
deleted file mode 100644
index b173cbf7..00000000
--- a/etc/modules/modules.all
+++ /dev/null
@@ -1,84 +0,0 @@
-fat
-vfat
-nfs
-sunrpc
-lockd
-floppy
-cramfs
-loop
-edd
-pcspkr
-squashfs
-ipv6
-virtio_pci
-ohci-hcd
-uhci-hcd
-ehci-hcd
-usbhid
-mousedev
-usb-storage
-sd_mod
-sr_mod
-ub
-appletouch
-ohci1394
-sbp2
-fw-ohci
-fw-sbp2
-firewire-sbp2
-firewire-ohci
-mmc-block
-sdhci
-sdhci-pci
-ide-cd
-ide-cd_mod
-sr_mod
-sg
-st
-sd_mod
-scsi_mod
-iscsi_tcp
-iscsi_ibft
-fat
-msdos
-vfat
-ext2
-ext3
-ext4
-reiserfs
-jfs
-xfs
-gfs2
-cifs
-fuse
-btrfs
-dm-mod
-dm-zero
-dm-snapshot
-dm-mirror
-dm-multipath
-dm-round-robin
-dm-crypt
-raid0
-raid1
-raid5
-raid6
-raid456
-raid10
-linear
-sha256_generic
-cbc
-xts
-lrw
-aes_generic
-crypto_blkcipher
-crc32c
-ecb
-arc4
-yenta_socket
-i82365
-tcic
-pcmcia
-=scsi
-=net
-=drm
diff --git a/etc/modules/modules.alpha b/etc/modules/modules.alpha
deleted file mode 100644
index dff84cf7..00000000
--- a/etc/modules/modules.alpha
+++ /dev/null
@@ -1,2 +0,0 @@
-tgafb
-crc32
diff --git a/etc/modules/modules.s390 b/etc/modules/modules.s390
deleted file mode 100644
index 02177798..00000000
--- a/etc/modules/modules.s390
+++ /dev/null
@@ -1,15 +0,0 @@
-zfcp
-tape390
-dasd_diag_mod
-dasd_eckd_mod
-dasd_fba_mod
-dasd_mod
-ctc
-netiucv
-smsgiucv
-lcs
-qdio
-qeth
-ccwgroup
-crypto_api
-xfrm_nalgo
diff --git a/etc/modules/modules.s390x b/etc/modules/modules.s390x
deleted file mode 120000
index a125a962..00000000
--- a/etc/modules/modules.s390x
+++ /dev/null
@@ -1 +0,0 @@
-modules.s390
\ No newline at end of file
diff --git a/etc/packages/packages.all b/etc/packages/packages.all
deleted file mode 100644
index df07843e..00000000
--- a/etc/packages/packages.all
+++ /dev/null
@@ -1,43 +0,0 @@
-joe
-gnome-icon-theme
-fedora-icon-theme
-xorg-x11-server-Xorg
-firstaidkit
-bzip2
-busybox
-selinux-policy-targeted
-python-imaging
-hal
-specspo
-xorg-x11-fonts-misc
-xorg-x11-drivers
-rhpxl
-ntfs-3g
-ntfsprogs
-xfsprogs
-xfsdump
-reiserfs-utils
-gfs2-utils
-jfsutils
-nfs-utils
-btrfs-progs
-mesa-dri-drivers
-dogtail
-rsh
-rsync
-prelink
-smartmontools
-iscsi-initiator-utils
-samba-client
-mtr
-gtk-nodoka-engine
-ftp
-openssh-clients
-gtk+
-gdk-pixbuf
-madan-fonts
-lklug-fonts
-xorg-x11-fonts-ethiopic
-un-core-fonts-dotum
-man
-yum-fedorakmod
\ No newline at end of file
diff --git a/etc/packages/packages.alpha b/etc/packages/packages.alpha
deleted file mode 100644
index 066c6d60..00000000
--- a/etc/packages/packages.alpha
+++ /dev/null
@@ -1 +0,0 @@
-aboot
diff --git a/etc/packages/packages.i386 b/etc/packages/packages.i386
deleted file mode 100644
index c1aa3a2f..00000000
--- a/etc/packages/packages.i386
+++ /dev/null
@@ -1,7 +0,0 @@
-pcmciautils
-grub
-dmidecode
-efibootmgr
-gpart
-syslinux
-memtest86+
\ No newline at end of file
diff --git a/etc/packages/packages.i586 b/etc/packages/packages.i586
deleted file mode 120000
index cd9dd23d..00000000
--- a/etc/packages/packages.i586
+++ /dev/null
@@ -1 +0,0 @@
-packages.i386
\ No newline at end of file
diff --git a/etc/packages/packages.ia64 b/etc/packages/packages.ia64
deleted file mode 100644
index 1e565c1e..00000000
--- a/etc/packages/packages.ia64
+++ /dev/null
@@ -1,3 +0,0 @@
-dmidecode
-efibootmgr
-elilo
diff --git a/etc/packages/packages.ppc b/etc/packages/packages.ppc
deleted file mode 100644
index 1bdc4e13..00000000
--- a/etc/packages/packages.ppc
+++ /dev/null
@@ -1,6 +0,0 @@
-pcmciautils
-pdisk
-yaboot
-hfsutils
-fbset
-ppc64-utils
diff --git a/etc/packages/packages.ppc64 b/etc/packages/packages.ppc64
deleted file mode 120000
index 602b9e1e..00000000
--- a/etc/packages/packages.ppc64
+++ /dev/null
@@ -1 +0,0 @@
-packages.ppc
\ No newline at end of file
diff --git a/etc/packages/packages.s390 b/etc/packages/packages.s390
deleted file mode 100644
index 96c92436..00000000
--- a/etc/packages/packages.s390
+++ /dev/null
@@ -1,19 +0,0 @@
-s390utils
-binutils
-libgcc
-tcp_wrappers
-sed
-net-tools
-openssh
-openssh-server
-coreutils
-login
-initscripts
-portmap
-pam
-mount
-modutils
-s390utils-cmsfs
-strace
-xorg-x11-xauth
-xorg-x11-libs
diff --git a/etc/packages/packages.s390x b/etc/packages/packages.s390x
deleted file mode 120000
index 2ec6ed77..00000000
--- a/etc/packages/packages.s390x
+++ /dev/null
@@ -1 +0,0 @@
-packages.s390
\ No newline at end of file
diff --git a/etc/packages/packages.sparc b/etc/packages/packages.sparc
deleted file mode 100644
index a78741ac..00000000
--- a/etc/packages/packages.sparc
+++ /dev/null
@@ -1,2 +0,0 @@
-tilo
-silo
diff --git a/etc/packages/packages.x86_64 b/etc/packages/packages.x86_64
deleted file mode 120000
index cd9dd23d..00000000
--- a/etc/packages/packages.x86_64
+++ /dev/null
@@ -1 +0,0 @@
-packages.i386
\ No newline at end of file
diff --git a/etc/tree/scrubs.alpha b/etc/tree/scrubs.alpha
deleted file mode 120000
index 782e69b5..00000000
--- a/etc/tree/scrubs.alpha
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.i386
\ No newline at end of file
diff --git a/etc/tree/scrubs.i386 b/etc/tree/scrubs.i386
deleted file mode 100644
index e0205a90..00000000
--- a/etc/tree/scrubs.i386
+++ /dev/null
@@ -1,103 +0,0 @@
-# remove unnecessary directories from /
-remove @instroot@/boot
-remove @instroot@/dev
-remove @instroot@/home
-remove @instroot@/media
-remove @instroot@/mnt
-remove @instroot@/opt
-remove @instroot@/root
-remove @instroot@/selinux
-remove @instroot@/srv
-remove @instroot@/sys
-remove @instroot@/tmp
-
-# remove directories from /usr
-remove @instroot@/usr/etc
-remove @instroot@/usr/games
-remove @instroot@/usr/include
-remove @instroot@/usr/kerberos
-remove @instroot@/usr/local
-remove @instroot@/usr/tmp
-
-# remove modules and firmware directories
-remove @instroot@/lib/modules
-remove @instroot@/lib/firmware
-
-# remove directories from /var
-remove @instroot@/var/db
-remove @instroot@/var/empty
-remove @instroot@/var/games
-remove @instroot@/var/local
-remove @instroot@/var/lock
-remove @instroot@/var/log
-remove @instroot@/var/mail
-remove @instroot@/var/nis
-remove @instroot@/var/opt
-remove @instroot@/var/preserve
-remove @instroot@/var/spool
-remove @instroot@/var/tmp
-remove @instroot@/var/yp
-
-# remove directories from /lib
-remove @instroot@/lib/i686
-remove @instroot@/lib/kbd
-remove @instroot@/lib/rtkaio
-remove @instroot@/lib/security
-remove @instroot@/lib/tls
-remove @instroot@/lib/xtables
-
-# remove directories from /etc
-remove @instroot@/etc/ConsoleKit
-remove @instroot@/etc/X11
-remove @instroot@/etc/alternatives
-remove @instroot@/etc/asterisk
-remove @instroot@/etc/avahi
-remove @instroot@/etc/blkid
-remove @instroot@/etc/bonobo*
-remove @instroot@/etc/chkconfig*
-remove @instroot@/etc/cron.*
-remove @instroot@/etc/default
-remove @instroot@/etc/depmod.d
-remove @instroot@/etc/dirmngr
-remove @instroot@/etc/dnsmasq.d
-remove @instroot@/etc/event.d
-remove @instroot@/etc/firmware
-remove @instroot@/etc/firstaidkit
-remove @instroot@/etc/gconf
-remove @instroot@/etc/gcrypt
-remove @instroot@/etc/gnome-vfs*
-remove @instroot@/etc/gnupg
-remove @instroot@/etc/gtk
-remove @instroot@/etc/hotplug
-remove @instroot@/etc/init.d
-remove @instroot@/etc/iproute2
-remove @instroot@/etc/iscsi
-remove @instroot@/etc/kernel
-remove @instroot@/etc/ld.so.conf.d
-remove @instroot@/etc/logrotate.d
-remove @instroot@/etc/lvm
-remove @instroot@/etc/makedev.d
-remove @instroot@/etc/modprobe.d
-remove @instroot@/etc/netplug*
-remove @instroot@/etc/ntp
-remove @instroot@/etc/openldap
-remove @instroot@/etc/opt
-remove @instroot@/etc/pam.d
-remove @instroot@/etc/pki
-remove @instroot@/etc/pm
-remove @instroot@/etc/popt.d
-remove @instroot@/etc/ppp
-remove @instroot@/etc/prelink.conf.d
-remove @instroot@/etc/profile.d
-remove @instroot@/etc/rc?.d
-remove @instroot@/etc/rwtab.d
-remove @instroot@/etc/samba
-remove @instroot@/etc/sasl2
-remove @instroot@/etc/security
-remove @instroot@/etc/setuptool.d
-remove @instroot@/etc/skel
-remove @instroot@/etc/ssh
-remove @instroot@/etc/statetab.d
-remove @instroot@/etc/terminfo
-remove @instroot@/etc/xdg
-remove @instroot@/etc/xinetd.d
diff --git a/etc/tree/scrubs.ia64 b/etc/tree/scrubs.ia64
deleted file mode 120000
index 782e69b5..00000000
--- a/etc/tree/scrubs.ia64
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.i386
\ No newline at end of file
diff --git a/etc/tree/scrubs.ppc b/etc/tree/scrubs.ppc
deleted file mode 120000
index 782e69b5..00000000
--- a/etc/tree/scrubs.ppc
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.i386
\ No newline at end of file
diff --git a/etc/tree/scrubs.ppc64 b/etc/tree/scrubs.ppc64
deleted file mode 120000
index 66cc7aa3..00000000
--- a/etc/tree/scrubs.ppc64
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.ppc
\ No newline at end of file
diff --git a/etc/tree/scrubs.s390x b/etc/tree/scrubs.s390x
deleted file mode 120000
index 580b924c..00000000
--- a/etc/tree/scrubs.s390x
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.s390
\ No newline at end of file
diff --git a/etc/tree/scrubs.sparc b/etc/tree/scrubs.sparc
deleted file mode 120000
index 782e69b5..00000000
--- a/etc/tree/scrubs.sparc
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.i386
\ No newline at end of file
diff --git a/etc/tree/scrubs.x86_64 b/etc/tree/scrubs.x86_64
deleted file mode 120000
index 782e69b5..00000000
--- a/etc/tree/scrubs.x86_64
+++ /dev/null
@@ -1 +0,0 @@
-scrubs.i386
\ No newline at end of file
diff --git a/src/bin/lorax b/src/bin/lorax
index 94fc3d0c..b98c1477 100755
--- a/src/bin/lorax
+++ b/src/bin/lorax
@@ -2,119 +2,11 @@
#
# lorax
-# lorax executable script
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): David Cantrell
-# Martin Gracik
#
import sys
-import os
-from optparse import OptionParser, OptionGroup
-
-import pylorax
+import pylorax.launcher
if __name__ == "__main__":
- version = "%s 0.1" % (os.path.basename(sys.argv[0]),)
- usage = "%prog -p PRODUCT -v VERSION -r RELEASE -o OUTPUTDIR REPOSITORY"
-
- parser = OptionParser(usage=usage)
-
- def check_dir(option, opt_str, value, parser):
- if os.path.isdir(value):
- setattr(parser.values, option.dest, value)
- else:
- parser.error("'%s' is not a directory" % (value,))
-
-
- # required
- # XXX "options" should not be required
- group = OptionGroup(parser, "Required")
- group.add_option("-p", "--product", help="Product name",
- metavar="STRING")
- group.add_option("-v", "--version", help="Version identifier",
- metavar="STRING")
- group.add_option("-r", "--release", help="Release information or comment",
- metavar="STRING")
- group.add_option("-o", "--output", help="Destination directory",
- metavar="PATHSPEC")
- parser.add_option_group(group)
-
- # optional
- # XXX are all of these used?
- group = OptionGroup(parser, "Optional")
- group.add_option("-d", "--debug", help="Enable debugging messages",
- action="store_true", default=False)
- group.add_option("-t", "--variant", help="Variant name",
- metavar="STRING")
- group.add_option("-b", "--bugurl", help="Bug reporting URL for the product",
- metavar="URL",
- default="your distribution provided bug reporting tool")
- group.add_option("-u", "--updates", help="Directory containing updates",
- metavar="PATHSPEC")
- group.add_option("-m", "--mirrorlist",
- help="Mirror list repository (may be listed multiple times)",
- metavar="REPOSITORY", action="append", default=[])
- group.add_option("-c", "--confdir", help="Path to config files (default: /etc/lorax)",
- metavar="PATHSPEC", action="callback", callback=check_dir,
- type="string", default="/etc/lorax")
- group.add_option("-C", "--cleanup", help="Clean up on exit",
- action="store_true", default=False)
- group.add_option("-V", help="Print version and exit",
- action="store_true", default=False, dest="printver")
- parser.add_option_group(group)
-
- # additional information
- group = OptionGroup(parser, "Additional information",
- "A 'REPOSITORY' specification is a valid yum repository path.\n"
- "See the man page lorax(8) for more information.")
- parser.add_option_group(group)
-
- (opts, args) = parser.parse_args()
-
- if opts.printver:
- print(version)
- sys.exit(0)
-
- if not opts.product or not opts.version or not opts.release or not opts.output:
- parser.error("Missing required argument")
-
- if not args:
- parser.error("Missing repository")
-
- config = pylorax.Config()
- config.set(confdir=opts.confdir,
- debug=opts.debug,
- cleanup=opts.cleanup)
-
- # required
- config.set(product=opts.product,
- version=opts.version,
- release=opts.release,
- outdir=opts.output,
- repos=args)
-
- # optional
- config.set(variant=opts.variant,
- bugurl=opts.bugurl,
- updates=opts.updates,
- mirrorlist=opts.mirrorlist)
-
- lorax = pylorax.Lorax(config=config)
- lorax.run()
+ pylorax.launcher.main(sys.argv)
diff --git a/src/pylorax/__init__.py b/src/pylorax/__init__.py
index d4c9b22e..6f71126d 100644
--- a/src/pylorax/__init__.py
+++ b/src/pylorax/__init__.py
@@ -1,639 +1,595 @@
#
# __init__.py
-# lorax main class
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-# David Cantrell
#
+__VERSION__ = "0.1"
+
import sys
import os
-import tempfile
-import re
-import shutil
import ConfigParser
+import re
+import glob
import time
import datetime
+import shutil
import commands
-from config import Container
-from utils.yumwrapper import Yum
-from utils.fileutils import copy, edit, replace
+import yum
+import yum.callbacks
+import yum.rpmtrans
+import config
import output
-import insttree
-import images
+import ramdisk
+import efi
+import install
+import lcs
-class Config(Container):
+ARCHS64 = ( "x86_64",
+ "s390x",
+ "sparc64" )
- def __init__(self):
- config = ("confdir", "datadir", "tempdir", "debug", "cleanup")
+BASEARCH_MAP = { "i386" : "i386",
+ "i586" : "i386",
+ "sparc64" : "sparc" }
- # options
- required = ("product", "version", "release", "outdir", "repos")
- optional = ("variant", "bugurl", "updates", "mirrorlist")
+EFIARCH_MAP = { "i386" : "IA32",
+ "x86_64" : "X64",
+ "ia64" : "IA64" }
- Container.__init__(self, config + required + optional)
-
- # set defaults
- self.set(confdir="/etc/lorax",
- datadir="/usr/share/lorax",
- tempdir=tempfile.mkdtemp(prefix="lorax.tmp.",
- dir=tempfile.gettempdir()),
- debug=False,
- cleanup=False)
-
- self.set(product="",
- version="",
- release="",
- outdir="",
- repos=[])
-
- self.set(variant="",
- bugurl="",
- updates="",
- mirrorlist=[])
+LIB32 = "lib"
+LIB64 = "lib64"
class LoraxError(Exception):
pass
+
class Lorax(object):
- def __init__(self, config):
- assert isinstance(config, Config) == True
- self.conf = config
+ SETTINGS = ( "colors",
+ "encoding",
+ "debug",
+ "cleanup" )
- # check if we have all required options
- if not self.conf.repos:
- raise LoraxError, "missing required parameter 'repos'"
- if not self.conf.outdir:
- raise LoraxError, "missing required parameter 'outdir'"
- if not self.conf.product:
- raise LoraxError, "missing required parameter 'product'"
- if not self.conf.version:
- raise LoraxError, "missing required parameter 'version'"
- if not self.conf.release:
- raise LoraxError, "missing required parameter 'release'"
+ REQ_PARAMS = ( "product",
+ "version",
+ "release",
+ "outputdir",
+ "tempdir",
+ "installtree" )
- self.yum = None
+ OPT_PARAMS = ( "variant",
+ "bugurl",
+ "updates" )
- # initialize the output objects
- self.so, self.se = output.initialize(verbose=self.conf.debug)
+ def __init__(self, yb, *args, **kwargs):
+ # check if we have root privileges
+ if not os.geteuid() == 0:
+ raise LoraxError("no root privileges")
- def collect_repositories(self):
- repolist = []
+ # check the yumbase object
+ if not isinstance(yb, yum.YumBase):
+ raise LoraxError("not an yumbase object")
- for repospec in self.conf.repos:
- if repospec.startswith("/"):
- repo = "file://%s" % (repospec,)
- self.so.info("Adding local repo: %s" % (repo,))
- repolist.append(repo)
- elif repospec.startswith("http://") or repospec.startswith("ftp://"):
- self.so.info("Adding remote repo: %s" % (repospec,))
- repolist.append(repospec)
- else:
- self.se.warning("Invalid repo path: %s" % (repospec,))
+ # create the yum object
+ self.yum = YumHelper(yb)
- if not repolist:
- return False
- else:
- mainrepo, extrarepos = repolist[0], repolist[1:]
+ # get the config object
+ self.conf = config.LoraxConfig.get()
- self.conf.addAttr(["mainrepo", "extrarepos"])
- self.conf.set(mainrepo=mainrepo, extrarepos=extrarepos)
-
- # remove not needed attributes from config
- self.conf.delAttr("repos")
+ # get the settings first
+ for key in self.SETTINGS:
+ value = kwargs.get(key, None)
+ if value is not None:
+ setattr(self.conf, key, value)
- return True
+ # set up the output
+ self.output = output.Terminal.get()
- def initialize_directories(self):
- # create the temporary directories
- treedir = os.path.join(self.conf.tempdir, "treedir", "install")
- os.makedirs(treedir)
+ output_level = output.INFO
+ if self.conf.debug:
+ output_level = output.DEBUG
- self.so.info("Working directories:")
-
- self.so.indent()
- self.so.info("tempdir = %s" % (self.conf.tempdir,))
- self.so.info("treedir = %s" % (treedir,))
- self.so.unindent()
+ self.output.basic_config(colors=self.conf.colors,
+ encoding=self.conf.encoding,
+ level=output_level)
- self.conf.addAttr("treedir")
- self.conf.set(treedir=treedir)
+ # check and set up the required parameters
+ for key in self.REQ_PARAMS:
+ value = kwargs.get(key, None)
- # create the destination directories
- if not os.path.isdir(self.conf.outdir):
- os.makedirs(self.conf.outdir, mode=0755)
+ if value is None:
+ raise LoraxError("missing required parameter '%s'" % key)
- imagesdir = os.path.join(self.conf.outdir, "images")
- if not os.path.isdir(imagesdir):
- os.makedirs(imagesdir)
+ setattr(self.conf, key, value)
- pxebootdir = os.path.join(imagesdir, "pxeboot")
- if not os.path.isdir(pxebootdir):
- os.makedirs(pxebootdir)
+ # set up the optional parameters
+ for key in self.OPT_PARAMS:
+ setattr(self.conf, key, kwargs.get(key, ""))
- efibootdir = os.path.join(self.conf.outdir, "EFI", "BOOT")
- if not os.path.isdir(efibootdir):
- os.makedirs(efibootdir)
+ # check if the required directories exist
+ if os.path.isdir(self.conf.outputdir):
+ raise LoraxError("output directory '%s' already exist" % \
+ self.conf.outputdir)
- # create the isolinux directory
- isolinuxdir = os.path.join(self.conf.outdir, "isolinux")
- if not os.path.isdir(isolinuxdir):
- os.makedirs(isolinuxdir)
+ if not os.path.isdir(self.conf.tempdir):
+ raise LoraxError("temporary directory '%s' does not exist" % \
+ self.conf.tempdir)
- self.so.info("Destination directories:")
+ if not os.path.isdir(self.conf.installtree):
+ raise LoraxError("install tree directory '%s' does not exist" % \
+ self.conf.installtree)
- self.so.indent()
- self.so.info("outdir = %s" % (self.conf.outdir,))
- self.so.info("imagesdir = %s" % (imagesdir,))
- self.so.info("pxebootdir = %s" % (pxebootdir,))
- self.so.info("efibootdir = %s" % (efibootdir,))
- self.so.info("isolinuxdir = %s" % (isolinuxdir,))
- self.so.unindent()
+ # get the paths
+ self.paths = config.LoraxPaths.get()
- self.conf.addAttr(["imagesdir", "pxebootdir",
- "efibootdir", "isolinuxdir"])
- self.conf.set(imagesdir=imagesdir, pxebootdir=pxebootdir,
- efibootdir=efibootdir, isolinuxdir=isolinuxdir)
-
- def initialize_yum(self):
- yumconf = os.path.join(self.conf.tempdir, "yum.conf")
-
- # create the yum cache directory
- cachedir = os.path.join(self.conf.tempdir, "yumcache")
- os.makedirs(cachedir)
-
- c = ConfigParser.ConfigParser()
-
- # main section
- section = "main"
- data = { "cachedir": cachedir,
- "keepcache": 0,
- "gpgcheck": 0,
- "plugins": 0,
- "reposdir": "",
- "tsflags": "nodocs" }
- c.add_section(section)
- [c.set(section, key, value) for key, value in data.items()]
-
- # main repo
- section = "lorax-repo"
- data = { "name": "lorax repo",
- "baseurl": self.conf.mainrepo,
- "enabled": 1 }
- c.add_section(section)
- [c.set(section, key, value) for key, value in data.items()]
-
- # extra repos
- for n, extra in enumerate(self.conf.extrarepos, start=1):
- section = "lorax-extrarepo-%d" % (n,)
- data = { "name": "lorax extra repo %d" % (n,),
- "baseurl": extra,
- "enabled": 1 }
- c.add_section(section)
- [c.set(section, key, value) for key, value in data.items()]
-
- # mirrorlist repos
- for n, mirror in enumerate(self.conf.mirrorlist, start=1):
- section = "lorax-mirrorlistrepo-%d" % (n,)
- data = { "name": "lorax mirrorlist repo %d" % (n,),
- "mirrorlist": mirror,
- "enabled": 1 }
- c.add_section(section)
- [c.set(section, key, value) for key, value in data.items()]
-
- try:
- f = open(yumconf, "w")
- except IOError as why:
- self.se.error("Unable to write yum.conf file: %s" % (why,))
- return False
- else:
- c.write(f)
- f.close()
-
- self.conf.addAttr("yumconf")
- self.conf.set(yumconf=yumconf)
-
- # remove not needed attributes from config
- self.conf.delAttr(["mainrepo", "extrarepos", "mirrorlist"])
-
- # create the Yum object
- self.yum = Yum(yumconf=self.conf.yumconf, installroot=self.conf.treedir,
- errfile=os.path.join(self.conf.tempdir, "yum.errors"))
-
- return True
-
- def set_architecture(self):
- # get the system architecture
- unamearch = os.uname()[4]
-
- self.conf.addAttr("buildarch")
- self.conf.set(buildarch=unamearch)
-
- # get the anaconda package architecture
- installed, available = self.yum.find("anaconda")
- try:
- self.conf.set(buildarch=available[0].arch)
- except:
- pass
-
- # set basearch
- self.conf.addAttr("basearch")
- self.conf.set(basearch=self.conf.buildarch)
-
- if re.match(r"i.86", self.conf.basearch):
- self.conf.set(basearch="i386")
- elif self.conf.basearch == "sparc64":
- self.conf.set(basearch="sparc")
+ def run(self):
+ # set the target architecture
+ self.output.info(":: setting the build architecture")
+ self.conf.arch = self.get_arch()
+ self.conf.basearch = BASEARCH_MAP.get(self.conf.arch, self.conf.arch)
+ self.conf.efiarch = EFIARCH_MAP.get(self.conf.arch, "")
# set the libdir
- self.conf.addAttr("libdir")
- self.conf.set(libdir="lib")
+ self.conf.libdir = LIB32
+ if self.conf.arch in ARCHS64:
+ self.conf.libdir = LIB64
- # on 64-bit systems, make sure we use lib64 as the lib directory
- if self.conf.buildarch.endswith("64") or self.conf.buildarch == "s390x":
- self.conf.set(libdir="lib64")
+ # read the config files
+ self.output.info(":: reading the configuration files")
+ packages, modules, initrd_template, scrubs_template = self.get_config()
- # set efiarch
- self.conf.addAttr("efiarch")
- self.conf.set(efiarch="")
+ # add the branding
+ packages.add("%s-logos" % self.conf.product.lower())
+ packages.add("%s-release" % self.conf.product.lower())
- if self.conf.buildarch == "i386":
- self.conf.set(efiarch="ia32")
- elif self.conf.buildarch == "x86_64":
- self.conf.set(efiarch="x64")
- elif self.conf.buildarch == "ia64":
- self.conf.set(efiarch="ia64")
+ self.conf.packages = packages
+ self.conf.modules = modules
+ self.conf.initrd_template = initrd_template
+ self.conf.scrubs_template = scrubs_template
+
+ # install packages into the install tree
+ self.output.info(":: installing required packages")
+ for name in packages:
+ if not self.yum.install(name):
+ self.output.warning("no package %s found" % \
+ self.output.format(name, type=output.BOLD))
+
+ self.yum.process_transaction()
+
+ # copy the updates
+ if self.conf.updates and os.path.isdir(self.conf.updates):
+ self.output.info(":: copying updates")
+ utils.scopy(src_root=self.conf.updates, src_path="*",
+ dst_root=self.conf.installtree, dst_path="")
+
+ # get the anaconda runtime directory
+ if os.path.isdir(self.paths.ANACONDA_RUNTIME):
+ self.conf.anaconda_runtime = self.paths.ANACONDA_RUNTIME
+ self.conf.anaconda_boot = self.paths.ANACONDA_BOOT
+ else:
+ self.output.critical("no anaconda runtime directory found")
+ sys.exit(1)
+
+ # get list of the installed kernel files
+ kerneldir = self.paths.BOOTDIR
+ if self.conf.arch == "ia64":
+ kerneldir = self.paths.BOOTDIR_IA64
+
+ kernelfiles = glob.glob(os.path.join(kerneldir, "vmlinuz-*"))
+
+ if not kernelfiles:
+ self.output.critical("no kernel image found")
+ sys.exit(1)
+
+ # create treeinfo, discinfo, and buildstamp
+ self.conf.treeinfo = self.write_treeinfo()
+ self.conf.discinfo = self.write_discinfo()
+ self.conf.buildstamp = self.write_buildstamp()
+
+ # prepare the output directory
+ self.output.info(":: preparing the output directory")
+ ok = self.prepare_output_directory()
+
+ if not ok:
+ self.output.critical("unable to prepare the output directory")
+ sys.exit(1)
+
+ for kernelfile in kernelfiles:
+ kfilename = os.path.basename(kernelfile)
+ m = re.match(r"vmlinuz-(?P.*)", kfilename)
+ if m:
+ self.conf.kernelfile = kernelfile
+ self.conf.kernelver = m.group("ver")
+ else:
+ continue
+
+ self.output.info(":: creating initrd for '%s'" % kfilename)
+
+ # create a temporary directory for the ramdisk tree
+ self.conf.ramdisktree = os.path.join(self.conf.tempdir,
+ "ramdisk-%s" % \
+ self.conf.kernelver)
+
+ utils.makedirs(self.conf.ramdisktree)
+
+ initrd = ramdisk.Ramdisk()
+ kernel_path, initrd_path = initrd.create()
+
+ # copy the kernel and initrd images to the pxeboot directory
+ shutil.copy2(kernel_path, self.conf.pxebootdir)
+ shutil.copy2(initrd_path, self.conf.pxebootdir)
+
+ # if this is a PAE kernel, skip the EFI part
+ if kernel_path.endswith("PAE"):
+ continue
+
+ # copy the kernel and initrd images to the isolinux directory
+ shutil.copy2(kernel_path, self.conf.isolinuxdir)
+ shutil.copy2(initrd_path, self.conf.isolinuxdir)
+
+ # create the efi images
+ self.output.info(":: creating efi images for '%s'" % kfilename)
+
+ efiimages = efi.EFI()
+ eb, ed = efiimages.create(kernel=kernel_path,
+ initrd=initrd_path,
+ kernelpath="/images/pxeboot/vmlinuz",
+ initrdpath="/images/pxeboot/initrd.img")
+
+ self.conf.efiboot = eb
+ self.conf.efidisk = ed
+
+ # copy the efi images to the images directory
+ shutil.copy2(self.conf.efiboot, self.conf.imagesdir)
+ shutil.copy2(self.conf.efidisk, self.conf.imagesdir)
+
+ # create the install image
+ self.output.info(":: creating the install image")
+ i = install.InstallImage()
+ installimg = i.create()
+
+ if installimg is None:
+ self.output.critical("unable to create install image")
+ sys.exit(1)
+
+ shutil.copy2(installimg, self.conf.imagesdir)
+
+ # create the boot iso
+ self.output.info(":: creating the boot iso")
+ bootiso = self.create_boot_iso()
+
+ if bootiso is None:
+ self.output.critical("unable to create boot iso")
+ sys.exit(1)
+
+ shutil.copy2(bootiso, self.conf.imagesdir)
+
+ # copy the treeinfo and discinfo to the output directory
+ shutil.copy2(self.conf.treeinfo, self.conf.outputdir)
+ shutil.copy2(self.conf.discinfo, self.conf.outputdir)
+
+ # cleanup
+ self.cleanup()
+
+ def get_arch(self):
+ # get the architecture of the anaconda package
+ installed, available = self.yum.search(self.paths.ANACONDA_PACKAGE)
+ try:
+ arch = available[0].arch
+ except:
+ # fallback to the system architecture
+ arch = os.uname()[4]
+
+ return arch
+
+ def get_config(self):
+ generic = os.path.join(self.conf.confdir, "config.noarch")
+ specific = os.path.join(self.conf.confdir,
+ "config.%s" % self.conf.arch)
+
+ packages, modules = set(), set()
+ initrd_template, scrubs_template = None, None
+
+ for f in (generic, specific):
+ if not os.path.isfile(f):
+ continue
+
+ c = ConfigParser.ConfigParser()
+ c.read(f)
+
+ if c.has_option("lorax", "packages"):
+ list = c.get("lorax", "packages").split()
+ for name in list:
+ if name.startswith("-"):
+ packages.discard(name)
+ else:
+ packages.add(name)
+
+ if c.has_option("lorax", "modules"):
+ list = c.get("lorax", "modules").split()
+ for name in list:
+ if name.startswith("-"):
+ modules.discard(name)
+ else:
+ modules.add(name)
+
+ if c.has_option("lorax", "initrd_template"):
+ initrd_template = c.get("lorax", "initrd_template")
+ initrd_template = os.path.join(self.conf.confdir,
+ initrd_template)
+
+ if c.has_option("lorax", "scrubs_template"):
+ scrubs_template = c.get("lorax", "scrubs_template")
+ scrubs_template = os.path.join(self.conf.confdir,
+ scrubs_template)
+
+ return packages, modules, initrd_template, scrubs_template
def write_treeinfo(self, discnum=1, totaldiscs=1, packagedir=""):
- outfile = os.path.join(self.conf.outdir, ".treeinfo")
+ outfile = os.path.join(self.conf.tempdir, ".treeinfo")
+
+ variant = self.conf.variant
+ if variant is None:
+ variant = ""
- # don't print anything instead of None, if variant is not specified
- variant = ""
- if self.conf.variant is not None:
- variant = self.conf.variant
-
c = ConfigParser.ConfigParser()
- # general section
section = "general"
- data = { "timestamp": time.time(),
- "family": self.conf.product,
- "version": self.conf.version,
- "arch": self.conf.basearch,
- "variant": variant,
- "discnum": discnum,
- "totaldiscs": totaldiscs,
- "packagedir": packagedir }
- c.add_section(section)
- [c.set(section, key, value) for key, value in data.items()]
+ data = { "timestamp" : time.time(),
+ "family" : self.conf.product,
+ "version" : self.conf.version,
+ "arch" : self.conf.basearch,
+ "variant" : variant,
+ "discnum" : discnum,
+ "totaldiscs" : totaldiscs,
+ "packagedir" : packagedir }
- # images section
- section = "images-%s" % (self.conf.basearch,)
- data = { "kernel": "images/pxeboot/vmlinuz",
- "initrd": "images/pxeboot/initrd.img",
- "boot.iso": "images/boot.iso" }
c.add_section(section)
- [c.set(section, key, value) for key, value in data.items()]
+ map(lambda (key, value): c.set(section, key, value), data.items())
- try:
- f = open(outfile, "w")
- except IOError as why:
- self.se.error("Unable to write .treeinfo file: %s" % (why,))
- return False
- else:
+ section = "images-%s" % self.conf.basearch
+ data = { "kernel" : "images/pxeboot/vmlinuz",
+ "initrd" : "images/pxeboot/initrd.img",
+ "boot.iso" : "images/boot.iso" }
+
+ c.add_section(section)
+ map(lambda (key, value): c.set(section, key, value), data.items())
+
+ with open(outfile, "w") as f:
c.write(f)
- f.close()
-
- return True
+
+ return outfile
def write_discinfo(self, discnum="ALL"):
- outfile = os.path.join(self.conf.outdir, ".discinfo")
+ outfile = os.path.join(self.conf.tempdir, ".discinfo")
- try:
- f = open(outfile, "w")
- except IOError as why:
- self.se.error("Unable to write .discinfo file: %s" % (why,))
- return False
- else:
- f.write("%f\n" % (time.time(),))
- f.write("%s\n" % (self.conf.release,))
- f.write("%s\n" % (self.conf.basearch,))
- f.write("%s\n" % (discnum,))
- f.close()
-
- return True
+ with open(outfile, "w") as f:
+ f.write("%f\n" % time.time())
+ f.write("%s\n" % self.conf.release)
+ f.write("%s\n" % self.conf.basearch)
+ f.write("%s\n" % discnum)
+
+ return outfile
def write_buildstamp(self):
- outfile = os.path.join(self.conf.treedir, ".buildstamp")
+ outfile = os.path.join(self.conf.tempdir, ".buildstamp")
- # make image uuid
now = datetime.datetime.now()
- uuid = "%s.%s" % (now.strftime("%Y%m%d%H%M"), self.conf.buildarch)
+ uuid = "%s.%s" % (now.strftime("%Y%m%d%H%M"), self.conf.arch)
- try:
- f = open(outfile, "w")
- except IOError as why:
- self.se.error("Unable to write .buildstamp file: %s" % (why,))
- return False
- else:
- f.write("%s\n" % (uuid,))
- f.write("%s\n" % (self.conf.product,))
- f.write("%s\n" % (self.conf.version,))
- f.write("%s\n" % (self.conf.bugurl,))
- f.close()
+ with open(outfile, "w") as f:
+ f.write("%s\n" % uuid)
+ f.write("%s\n" % self.conf.product)
+ f.write("%s\n" % self.conf.version)
+ f.write("%s\n" % self.conf.bugurl)
- self.conf.addAttr("buildstamp")
- self.conf.set(buildstamp=outfile)
-
- return True
+ return outfile
def prepare_output_directory(self):
- # write the images/README
- src = os.path.join(self.conf.datadir, "images", "README")
- dst = os.path.join(self.conf.imagesdir, "README")
+ # create the output directory
+ os.mkdir(self.conf.outputdir)
+
+ # create the images directory
+ imagesdir = os.path.join(self.conf.outputdir, "images")
+ utils.mkdir(imagesdir)
+ self.conf.imagesdir = imagesdir
+
+ # write the images/README file
+ src = os.path.join(self.paths.OUTPUTDIR_DATADIR, "images", "README")
+ dst = os.path.join(imagesdir, "README")
shutil.copy2(src, dst)
- replace(dst, r"@PRODUCT@", self.conf.product)
+ utils.replace(dst, r"@PRODUCT@", self.conf.product)
- # write the images/pxeboot/README
- src = os.path.join(self.conf.datadir, "images", "pxeboot", "README")
- dst = os.path.join(self.conf.pxebootdir, "README")
+ # create the pxeboot directory
+ pxebootdir = os.path.join(imagesdir, "pxeboot")
+ utils.mkdir(pxebootdir)
+ self.conf.pxebootdir = pxebootdir
+
+ # write the images/pxeboot/README file
+ src = os.path.join(self.paths.OUTPUTDIR_DATADIR, "images", "pxeboot",
+ "README")
+ dst = os.path.join(pxebootdir, "README")
shutil.copy2(src, dst)
- replace(dst, r"@PRODUCT@", self.conf.product)
+ utils.replace(dst, r"@PRODUCT@", self.conf.product)
- # set up some dir variables for further use
- anacondadir = os.path.join(self.conf.treedir,
- "usr", "lib", "anaconda-runtime")
-
- bootdiskdir = os.path.join(anacondadir, "boot")
- self.conf.addAttr("bootdiskdir")
- self.conf.set(bootdiskdir=bootdiskdir)
+ # create the efiboot directory
+ efibootdir = os.path.join(self.conf.outputdir, "EFI", "BOOT")
+ utils.makedirs(efibootdir)
+ self.conf.efibootdir = efibootdir
- syslinuxdir = os.path.join(self.conf.treedir, "usr", "lib", "syslinux")
- isolinuxbin = os.path.join(syslinuxdir, "isolinux.bin")
+ # create the isolinux directory
+ isolinuxdir = os.path.join(self.conf.outputdir, "isolinux")
+ utils.mkdir(isolinuxdir)
+ self.conf.isolinuxdir = isolinuxdir
- if os.path.isfile(isolinuxbin):
- # copy the isolinux.bin
- shutil.copy2(isolinuxbin, self.conf.isolinuxdir)
+ syslinuxdir = self.paths.SYSLINUXDIR
+ isolinuxbin = self.paths.ISOLINUXBIN
- # copy the syslinux.cfg to isolinux/isolinux.cfg
- isolinuxcfg = os.path.join(self.conf.isolinuxdir, "isolinux.cfg")
- shutil.copy2(os.path.join(bootdiskdir, "syslinux.cfg"), isolinuxcfg)
+ if not os.path.isfile(isolinuxbin):
+ self.output.error("no isolinux binary found")
+ return False
- # set the product and version in isolinux.cfg
- replace(isolinuxcfg, r"@PRODUCT@", self.conf.product)
- replace(isolinuxcfg, r"@VERSION@", self.conf.version)
+ # copy the isolinux.bin
+ shutil.copy2(isolinuxbin, isolinuxdir)
- # set up the label for finding stage2 with a hybrid iso
- replace(isolinuxcfg, r"initrd=initrd.img",
- 'initrd=initrd.img stage2=hd:LABEL="%s"' % (self.conf.product,))
+ # copy the syslinux.cfg to isolinux/isolinux.cfg
+ isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg")
+ shutil.copy2(self.paths.SYSLINUXCFG, isolinuxcfg)
- # copy the grub.conf
- shutil.copy2(os.path.join(bootdiskdir, "grub.conf"),
- self.conf.isolinuxdir)
+ # set the product and version in isolinux.cfg
+ utils.replace(isolinuxcfg, r"@PRODUCT@", self.conf.product)
+ utils.replace(isolinuxcfg, r"@VERSION@", self.conf.version)
- # copy the splash files
- vesasplash = os.path.join(anacondadir, "syslinux-vesa-splash.jpg")
- if os.path.isfile(vesasplash):
- shutil.copy2(vesasplash,
- os.path.join(self.conf.isolinuxdir, "splash.jpg"))
+ # set up the label for finding stage2 with a hybrid iso
+ utils.replace(isolinuxcfg, r"initrd=initrd.img",
+ 'initrd=initrd.img stage2=hd:LABEL="%s"' % \
+ self.conf.product)
- vesamenu = os.path.join(syslinuxdir, "vesamenu.c32")
- shutil.copy2(vesamenu, self.conf.isolinuxdir)
+ # copy the grub.conf
+ dst = os.path.join(isolinuxdir, "grub.conf")
+ shutil.copy2(self.paths.GRUBCONF, dst)
- replace(isolinuxcfg, r"default linux", r"default vesamenu.c32")
- replace(isolinuxcfg, r"prompt 1", r"#prompt 1")
- else:
- splashtools = os.path.join(anacondadir, "splashtools.sh")
- splashlss = os.path.join(bootdiskdir, "splash.lss")
+ utils.replace(dst, "@PRODUCT@", self.conf.product)
+ utils.replace(dst, "@VERSION@", self.conf.version)
- if os.path.isfile(splashtools):
- cmd = "%s %s %s" % (splashtools,
- os.path.join(bootdiskdir, "syslinux-splash.jpg"),
- splashlss)
- out = commands.getoutput(cmd)
+ # copy the splash files
+ if os.path.isfile(self.paths.VESASPLASH):
+ shutil.copy2(self.paths.VESASPLASH,
+ os.path.join(isolinuxdir, "splash.jpg"))
- if os.path.isfile(splashlss):
- shutil.copy2(splashlss, self.conf.isolinuxdir)
+ shutil.copy2(self.paths.VESAMENU, isolinuxdir)
- # copy the .msg files
- for file in os.listdir(bootdiskdir):
- if file.endswith(".msg"):
- shutil.copy2(os.path.join(bootdiskdir, file),
- self.conf.isolinuxdir)
- replace(os.path.join(self.conf.isolinuxdir, file),
- r"@VERSION@", self.conf.version)
+ utils.replace(isolinuxcfg, r"default linux", "default vesamenu.c32")
+ utils.replace(isolinuxcfg, r"prompt 1", "#prompt 1")
- # if present, copy the memtest
- for fname in os.listdir(os.path.join(self.conf.treedir, "boot")):
- if fname.startswith("memtest"):
- src = os.path.join(self.conf.treedir, "boot", fname)
- dst = os.path.join(self.conf.isolinuxdir, "memtest")
- shutil.copy2(src, dst)
-
- text = "label memtest86\n"
- text = text + " menu label ^Memory test\n"
- text = text + " kernel memtest\n"
- text = text + " append -\n"
- edit(isolinuxcfg, text, append=True)
else:
- return False
-
- return True
+ if os.path.isfile(self.paths.SPLASHTOOLS):
+ cmd = "%s %s %s" % (self.paths.SPLASHTOOLS,
+ self.paths.SYSLINUXSPLASH,
+ self.paths.SPLASHLSS)
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
- def create_install_image(self, type="squashfs"):
- installimg = os.path.join(self.conf.imagesdir, "install.img")
+ if os.path.isfile(self.paths.SPLASHLSS):
+ shutil.copy2(self.paths.SPLASHLSS, isolinuxdir)
- if os.path.exists(installimg):
- os.unlink(installimg)
+ # copy the .msg files
+ msgfiles = os.path.join(self.conf.anaconda_boot, "*.msg")
+ for fname in glob.glob(msgfiles):
+ shutil.copy2(fname, isolinuxdir)
+ utils.replace(os.path.join(isolinuxdir, os.path.basename(fname)),
+ r"@VERSION@", self.conf.version)
- if type == "squashfs":
- cmd = "mksquashfs %s %s -all-root -no-fragments -no-progress" \
- % (self.conf.treedir, installimg)
- self.so.debug(cmd)
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.info(output)
- return False
+ # copy the memtest
+ memtest = os.path.join(self.paths.BOOTDIR, "memtest*")
+ for fname in glob.glob(memtest):
+ shutil.copy2(fname, os.path.join(isolinuxdir, "memtest"))
- elif type == "cramfs":
- if self.conf.buildarch == "sparc64":
- crambs = "--blocksize 8192"
- elif self.conf.buildarch == "sparc":
- crambs = "--blocksize 4096"
- else:
- crambs = ""
+ text = """label memtest86
+ menu label ^Memory test
+ kernel memtest
+ append -
- cmd = "mkfs.cramfs %s %s %s" % (crambs, self.conf.treedir,
- installimg)
- self.so.debug(cmd)
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.info(output)
- return False
+"""
- elif type == "ext2":
- # TODO
- return False
-
- # append stage2 to .treeinfo file
- text = "\n[stage2]\n"
- text += "mainimage = %s\n" % (installimg,)
- edit(os.path.join(self.conf.outdir, ".treeinfo"), append=True, text=text)
+ utils.edit(isolinuxcfg, append=True, text=text)
+ break
return True
def create_boot_iso(self):
- bootiso = os.path.join(self.conf.imagesdir, "boot.iso")
+ bootiso = os.path.join(self.conf.tempdir, "boot.iso")
if os.path.exists(bootiso):
os.unlink(bootiso)
- efiboot = os.path.join(self.conf.imagesdir, "efiboot.img")
-
- if os.path.exists(efiboot):
- self.so.info("Found efiboot.img, making an EFI-capable boot.iso")
+ if os.path.exists(self.conf.efiboot):
+ self.output.info(":: creating efi capable boot iso")
efiargs = "-eltorito-alt-boot -e images/efiboot.img -no-emul-boot"
- efigraft = "EFI/BOOT=%s" % (os.path.join(self.conf.outdir,
- "EFI", "BOOT"),)
+ efigraft = "EFI/BOOT=%s" % self.conf.efibootdir
else:
- self.so.info("No efiboot.img found, making BIOS-only boot.iso")
efiargs = ""
efigraft = ""
biosargs = "-b isolinux/isolinux.bin -c isolinux/boot.cat" \
- " -no-emul-boot -boot-load-size 4 -boot-info-table"
- mkisocmd = "mkisofs -v -o %s %s %s -R -J -V %s -T -graft-points" \
- " isolinux=%s images=%s %s" % (bootiso, biosargs, efiargs,
- self.conf.product, self.conf.isolinuxdir, self.conf.imagesdir,
- efigraft)
- self.so.debug(mkisocmd)
- err, out = commands.getstatusoutput(mkisocmd)
- if err:
- self.se.info(out)
- return False
+ " -no-emul-boot -boot-load-size 4 -boot-info-table"
- hybrid = os.path.join("/", "usr", "bin", "isohybrid")
- if os.path.exists(hybrid):
- cmd = "%s %s" % (hybrid, os.path.join(self.conf.imagesdir, "boot.iso"))
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
+ cmd = "%s -v -o %s %s %s -R -J -V %s -T -graft-points" \
+ " isolinux=%s images=%s %s" % (self.paths.MKISOFS, bootiso,
+ biosargs, efiargs,
+ self.conf.product,
+ self.conf.isolinuxdir,
+ self.conf.imagesdir, efigraft)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return None
+
+ if os.path.isfile(self.paths.ISOHYBRID):
+ cmd = "%s %s" % (self.paths.ISOHYBRID, bootiso)
+ err, output = commands.getstatusoutput(cmd)
if err:
- self.se.info(out)
- # XXX is this a problem?
- # should we return false, or just go on?
+ self.output.warning(output)
+
+ return bootiso
+
+ def cleanup(self):
+ if self.conf.cleanup:
+ shutil.rmtree(self.conf.tempdir)
+
+
+class YumHelper(object):
+
+ def __init__(self, yb):
+ self.yb = yb
+
+ def install(self, pattern):
+ try:
+ self.yb.install(name=pattern)
+ except yum.Errors.InstallError:
+ try:
+ self.yb.install(pattern=pattern)
+ except yum.Errors.InstallError:
+ return False
return True
- def clean_up(self):
- if os.path.isdir(self.conf.tempdir):
- shutil.rmtree(self.conf.tempdir, ignore_errors=True)
+ def process_transaction(self):
+ self.yb.resolveDeps()
+ self.yb.buildTransaction()
- def run(self):
- self.so.header(":: Collecting repositories")
- ok = self.collect_repositories()
- if not ok:
- # we have no valid repository to work with
- self.se.error("No valid repository")
- sys.exit(1)
+ cb = yum.callbacks.ProcessTransBaseCallback()
+ rpmcb = RpmCallback()
- self.so.header(":: Initializing directories")
- self.initialize_directories()
+ self.yb.processTransaction(callback=cb, rpmDisplay=rpmcb)
- self.so.header(":: Initializing yum")
- ok = self.initialize_yum()
- if not ok:
- # the yum object could not be initialized
- self.se.error("Unable to initialize the yum object")
- sys.exit(1)
+ self.yb.closeRpmDB()
+ self.yb.close()
- self.so.header(":: Setting the architecture")
- self.set_architecture()
+ def search(self, pattern):
+ pl = self.yb.doPackageLists(patterns=[pattern])
+ return pl.installed, pl.available
- self.so.header(":: Writing the .treeinfo file")
- ok = self.write_treeinfo()
- if not ok:
- # XXX is this a problem?
- pass
- self.so.header(":: Writing the .discinfo file")
- ok = self.write_discinfo()
- if not ok:
- # XXX is this a problem?
- pass
+class RpmCallback(yum.rpmtrans.SimpleCliCallBack):
- self.so.header(":: Writing the .buildstamp file")
- ok = self.write_buildstamp()
- if not ok:
- # XXX is this a problem?
- pass
+ def __init__(self):
+ yum.rpmtrans.SimpleCliCallBack.__init__(self)
+ self.output = output.Terminal.get()
- self.so.header(":: Preparing the install tree")
- tree = insttree.InstallTree(self.conf, self.yum, (self.so, self.se))
- kernelfiles = tree.run()
+ def event(self, package, action, te_current, te_total,
+ ts_current, ts_total):
- if not kernelfiles:
- self.se.error("No kernel image found")
- sys.exit(1)
+ msg = "(%3d/%3d) [%3d%%] %s %s\r" % (ts_current, ts_total,
+ float(te_current) / float(te_total) * 100,
+ self.action[action],
+ self.output.format("%s" % package, type=output.BOLD))
- self.so.header(":: Preparing the output directory")
- ok = self.prepare_output_directory()
- if not ok:
- # XXX there's no isolinux.bin, i guess this is a problem...
- self.se.error("Unable to prepare the output directory")
- sys.exit(1)
-
- self.conf.addAttr(["kernelfile", "kernelver"])
- for kernelfile in kernelfiles:
- # get the kernel version
- m = re.match(r".*vmlinuz-(.*)", kernelfile)
- if m:
- kernelver = m.group(1)
- self.conf.set(kernelfile=kernelfile, kernelver=kernelver)
- else:
- self.se.warning("Invalid kernel filename '%s'" % (kernelfile,))
- continue
-
- self.so.header(":: Creating the initrd image for kernel '%s'" \
- % (os.path.basename(kernelfile),))
- initrd = images.InitRD(self.conf, self.yum, (self.so, self.se))
- initrd.run()
-
- self.so.header(":: Creating the install image")
-
- self.so.info("Scrubbing the install tree")
- tree.scrub()
-
- ok = self.create_install_image()
- if not ok:
- self.se.error("Unable to create the install image")
- sys.exit(1)
-
- self.so.header(":: Creating the boot iso")
- ok = self.create_boot_iso()
- if not ok:
- self.se.error("Unable to create the boot iso")
- sys.exit(1)
-
- if self.conf.cleanup:
- self.so.header(":: Cleaning up")
- self.clean_up()
+ self.output.write(msg)
+ if te_current == te_total:
+ self.output.write("\n")
diff --git a/src/pylorax/_rewrite/scrubs.py b/src/pylorax/_rewrite/scrubs.py
deleted file mode 100644
index af4d9f04..00000000
--- a/src/pylorax/_rewrite/scrubs.py
+++ /dev/null
@@ -1,126 +0,0 @@
-import stat
-import commands
-import pwd
-import grp
-
-class Install(object):
-
- def scrub(self):
- # change tree permissions
- root_uid = pwd.getpwnam('root')[2]
- root_gid = grp.getgrnam('root')[2]
-
- for root, files, dirs in os.walk(self.conf.treedir):
- os.chown(root, root_uid, root_gid)
- os.chmod(root, 0755)
-
- for file in files:
- path = os.path.join(root, file)
- os.chown(path, root_uid, root_gid)
-
- mode = os.stat(path).st_mode
- if (mode & stat.S_IXUSR) or (mode & stat.S_IXGRP) or (mode & stat.S_IXOTH):
- os.chmod(path, 0555)
- else:
- os.chmod(path, 0444)
-
- # create ld.so.conf
- ldsoconf = os.path.join(self.conf.treedir, 'etc', 'ld.so.conf')
- touch(ldsoconf)
-
- procdir = os.path.join(self.conf.treedir, 'proc')
- if not os.path.isdir(procdir):
- os.makedirs(procdir)
- os.system('mount -t proc proc %s' % procdir)
-
- f = open(ldsoconf, 'w')
- f.write('/usr/kerberos/%s\n' % self.conf.libdir)
- f.close()
-
- cwd = os.getcwd()
- os.chdir(self.conf.treedir)
- os.system('/usr/sbin/chroot %s /sbin/ldconfig' % self.conf.treedir)
- os.chdir(cwd)
-
- if self.conf.buildarch not in ('s390', 's390x'):
- # XXX this is not in usr
- rm(os.path.join(self.conf.treedir, 'usr', 'sbin', 'ldconfig'))
-
- # XXX why are we removing this?
- #rm(os.path.join(self.conf.treedir, 'etc', 'ld.so.conf'))
- os.system('umount %s' % procdir)
-
- # make bash link
- # XXX already exists
- #if os.path.isfile(os.path.join(self.conf.treedir, 'bin', 'bash')):
- # rm(os.path.join(self.conf.treedir, 'bin', 'ash'))
- # os.symlink('bash', os.path.join(self.conf.treedir, 'bin', 'sh'))
-
- # make awk link
- # XXX already exists
- #if os.path.isfile(os.path.join(self.conf.treedir, 'bin', 'gawk')):
- # os.symlink('awk', os.path.join(self.conf.treedir, 'bin', 'gawk'))
-
- # remove dirs from usr/lib
- dirs = ('ConsoleKit', 'X11', 'alsa-lib', 'asterisk', 'avahi', 'booty', 'db4.5*', 'enchant', 'games', 'gio', 'gnome-keyring', 'gnome-vfs-2.0',
- 'krb5', 'libglade', 'libxslt-plugins', 'lua', 'notification-daemon*', 'nss', 'openssl', 'orbit-2.0', 'perl5', 'pkgconfig', 'plymouth',
- 'pm-utils', 'pppd', 'pygtk', 'rsyslog', 'samba', 'sasl2', 'sse2', 'syslinux', 'tc', 'tls', 'udev', 'window-manager-settings')
- for dir in dirs:
- rm(os.path.join(self.conf.treedir, 'usr', 'lib', dir))
-
- # remove dirs from usr/share
- dirs = ('GConf', 'NetworkManager', 'aclocal', 'alsa', 'application-registry', 'applications', 'asterisk', 'augeas', 'authconfig', 'avahi',
- 'awk', 'createrepo', 'desktop-directories', 'dict', 'doc', 'dogtail', 'emacs', 'empty', 'enchant', 'file', 'firmware', 'firmware-tools',
- 'firstboot', 'games', 'gnome*', 'gnupg', 'groff', 'gtk-*', 'help', 'i18n', 'info', 'kde*', 'librarian', 'libthai', 'lua',
- 'makebootfat', 'man', 'metacity', 'mime*', 'misc', 'myspell', 'octave', 'omf', 'pkgconfig', 'plymouth', 'pygtk', 'selinux',
- 'setuptool', 'sgml', 'system-config-firewall', 'system-config-network', 'system-config-users', 'tabset', 'tc', 'usermode', 'xml',
- 'xsessions', 'yum-cli', 'magic')
- for dir in dirs:
- rm(os.path.join(self.conf.treedir, 'usr', 'share', dir))
-
- # remove dirs from usr/share/themes
- dirs = ('AgingGorilla', 'Atlanta', 'Bright', 'Clearlooks', 'ClearlooksClassic', 'Crux', 'Default', 'Emacs', 'Esco', 'Glider', 'Glossy',
- 'HighContrast*', 'Industrial', 'Inverted', 'LargePrint', 'LowContrast*', 'Metabox', 'Mist', 'Raleigh', 'Simple', 'ThinIce')
- for dir in dirs:
- rm(os.path.join(self.conf.treedir, 'usr', 'share', 'themes', dir))
-
- # remove dirs from usr/libexec
- dirs = ('awk', 'gcc', 'getconf', 'openssh', 'plymouth')
- for dir in dirs:
- rm(os.path.join(self.conf.treedir, 'usr', 'libexec', dir))
-
- # remove dirs from usr/share/locale
- dirs = ('af_ZA', 'ca_ES', 'cs_CZ', 'de_DE', 'el_GR', 'en', 'en_US', 'es_ES', 'et_EE', 'fa_IR', 'fr_FR', 'he_IL', 'hr_HR', 'it_IT', 'ja_JP',
- 'ko_KR', 'nb_NO', 'nl_NL', 'nso', 'pl_PL', 'pt_PT', 'ru_RU', 'sr', 'sv_SE', 'uk_UA')
- for dir in dirs:
- rm(os.path.join(self.conf.treedir, 'usr', 'share', 'locale'))
-
- # remove dirs from var/cache
- dirs = ('dirmngr', 'fontconfig', 'man', 'yum')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'var', 'cache', dir)), dirs)
-
- # remove dirs from var/lib
- dirs = ('alternatives', 'asterisk', 'authconfig', 'dhclient', 'dhcpv6', 'dirmngr', 'dnsmasq', 'games', 'iscsi', 'nfs', 'ntp', 'plymouth',
- 'rpcbind', 'rpm', 'samba', 'selinux', 'sepolgen', 'stateless', 'udev', 'yum', 'logrotate.status')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'var', 'lib', dir)), dirs)
-
- # remove dirs from var/run
- dirs = ('ConsoleKit', 'NetworkManager', 'asterisk', 'avahi-daemon', 'console', 'dirmngr', 'hald', 'mdadm', 'netreport', 'plymouth',
- 'pm-utils', 'ppp', 'sepermit', 'setrans', 'winbindd', 'wpa_supplicant', 'utmp')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'var', 'run', dir)), dirs)
-
- # remove dirs from usr/share/terminfo
- dirs = ('A', 'E', 'a', 'c', 'd', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'r', 's', 't', 'w')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'usr', 'share', 'terminfo', dir)), dirs)
-
- # remove dirs from usr/share/pixmaps
- dirs = ('redhat', 'splash')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'usr', 'share', 'pixmaps', dir)), dirs)
-
- # remove dirs form usr/share/X11/fonts
- dirs = ('OTF', 'encodings', 'util')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'usr', 'share', 'X11', 'fonts', dir)), dirs)
-
- # remove dirs from usr/lib/python2.5/site-packages
- dirs = ('firmware_addon_dell', 'firmwaretools')
- map(lambda dir: rm(os.path.join(self.conf.treedir, 'usr', 'lib', 'python2.5', 'site-packages', dir)), dirs)
diff --git a/src/pylorax/actions/__init__.py b/src/pylorax/actions/__init__.py
deleted file mode 100644
index 59d52e29..00000000
--- a/src/pylorax/actions/__init__.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# __init__.py
-# actions parser
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import sys
-import os
-
-
-def getActions(verbose=False):
- actions = {}
- root, actions_dir = os.path.split(os.path.dirname(__file__))
-
- sys.path.insert(0, root)
-
- modules = set()
- for filename in os.listdir(os.path.join(root, actions_dir)):
- if filename.endswith(".py") and filename != "__init__.py":
- basename, extension = os.path.splitext(filename)
- modules.add(os.path.join(actions_dir, basename).replace("/", "."))
-
- for module in modules:
- if verbose:
- print("Loading actions from module '%s'" % (module,))
- imported = __import__(module, globals(), locals(), [module], -1)
-
- try:
- commands = getattr(imported, "COMMANDS")
- except AttributeError:
- if verbose:
- print("No actions found")
- continue
- else:
- for command, classname in commands.items():
- if verbose:
- print("Loaded: %s" % classname)
- actions[command] = getattr(imported, classname)
-
- sys.path.pop(0)
-
- return actions
diff --git a/src/pylorax/actions/base.py b/src/pylorax/actions/base.py
deleted file mode 100644
index 245a40ed..00000000
--- a/src/pylorax/actions/base.py
+++ /dev/null
@@ -1,404 +0,0 @@
-#
-# base.py
-# base actions
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import os
-import re
-import pwd
-import grp
-import glob
-
-from pylorax.utils.fileutils import copy, move, remove, touch, edit, replace, chmod
-
-
-# command:action mapping
-# maps a template command to an action class
-# if you want your new action to be supported, you have to include it in this mapping
-COMMANDS = { 'copy': 'Copy',
- 'move': 'Move',
- 'remove': 'Remove',
- 'link': 'Link',
- 'touch': 'Touch',
- 'edit': 'Edit',
- 'replace': 'Replace',
- 'makedir': 'MakeDir',
- 'chmod': 'Chmod',
- 'chown': 'Chown',
- 'genkey': 'GenerateSSHKey' }
-
-
-class LoraxAction(object):
- """Actions base class.
-
- To create your own custom action, subclass this class and override the methods you need.
-
- A valid action has to have a REGEX class variable, which specifies the format of the action
- command line, so the needed parameters can be properly extracted from it.
- All the work should be done in the execute method, which will be called from Lorax.
- At the end, set the success to False, or True depending on the success or failure of your action.
-
- If you need to install some package prior to executing the action, return an install pattern
- with the "install" property. Lorax will get this first, and will try to install the needed
- package.
-
- Don't forget to include a command:action map for your new action in the COMMANDS dictionary.
- Action classes which are not in the COMMANDS dictionary will not be loaded.
-
- You can take a look at some of the builtin actions to get an idea of how to create your
- own actions."""
-
-
- REGEX = r'' # regular expression for extracting the parameters from the command line
-
- def __init__(self):
- if self.__class__ is LoraxAction:
- raise TypeError, 'LoraxAction is an abstract class, cannot be used this way'
-
- self._attrs = {}
- self._attrs['success'] = None # success is None, if the action wasn't executed yet
-
- def __str__(self):
- return '%s: %s' % (self.__class__.__name__, self._attrs)
-
- def execute(self, verbose=False):
- """This method is the main body of the action. Put all the "work" stuff in here."""
- raise NotImplementedError, 'execute method not implemented for LoraxAction class'
-
- @property
- def success(self):
- """Returns if the action's execution was successful or not."""
- return self._attrs['success']
-
- @property
- def install(self):
- """Returns a pattern that needs to be installed, prior to calling the execute method."""
- return None
-
- @property
- def getDeps(self):
- return None
-
-
-##### builtin actions
-
-class Copy(LoraxAction):
-
- REGEX = r'^(?P.*?)\s(?P.*?)\sto\s(?P.*?)\s(?P.*?)(\s(?Pinstall))?(\s(?Pnolinks))?$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['src_root'] = kwargs.get('src_root')
- self._attrs['src_path'] = kwargs.get('src_path')
- self._attrs['dst_root'] = kwargs.get('dst_root')
- self._attrs['dst_path'] = kwargs.get('dst_path')
-
- install = kwargs.get('install', False)
- if install:
- self._attrs['install'] = True
- else:
- self._attrs['install'] = False
-
- nolinks = kwargs.get('nolinks', False)
- if nolinks:
- self._attrs['nolinks'] = True
- else:
- self._attrs['nolinks'] = False
-
- def execute(self, verbose=False):
- copy(src_root=self.src_root, src_path=self.src_path,
- dst_root=self.dst_root, dst_path=self.dst_path,
- nolinks=self.nolinks, ignore_errors=False, verbose=verbose)
- self._attrs['success'] = True
-
- @property
- def src(self):
- path = os.path.join(self._attrs['src_root'], self._attrs['src_path'])
- return os.path.normpath(path)
-
- @property
- def src_root(self):
- return self._attrs['src_root']
-
- @property
- def src_path(self):
- return self._attrs['src_path']
-
- @property
- def dst(self):
- path = os.path.join(self._attrs['dst_root'], self._attrs['dst_path'])
- return os.path.normpath(path)
-
- @property
- def dst_root(self):
- return self._attrs['dst_root']
-
- @property
- def dst_path(self):
- return self._attrs['dst_path']
-
- @property
- def mode(self):
- return self._attrs['mode']
-
- @property
- def install(self):
- if self._attrs['install']:
- return self._attrs['src']
- else:
- return None
-
- @property
- def getDeps(self):
- return self.src
-
- @property
- def nolinks(self):
- return self._attrs['nolinks']
-
-
-class Move(Copy):
- def execute(self, verbose=False):
- move(src_root=self.src_root, src_path=self.src_path,
- dst_root=self.dst_root, dst_path=self.dst_path,
- nolinks=self.nolinks, ignore_errors=False, verbose=verbose)
- self._attrs['success'] = True
-
-
-class Remove(LoraxAction):
-
- REGEX = r'^(?P.*?)$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['filename'] = kwargs.get('filename')
-
- def execute(self, verbose=False):
- remove(self.filename, verbose=verbose)
- self._attrs['success'] = True
-
- @property
- def filename(self):
- return self._attrs['filename']
-
-
-class Link(LoraxAction):
-
- REGEX = r'^(?P.*?)\sto\s(?P.*?)$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['name'] = kwargs.get('name')
- self._attrs['target'] = kwargs.get('target')
-
- def execute(self, verbose=False):
- os.symlink(self.target, self.name)
- self._attrs['success'] = True
-
- @property
- def name(self):
- return self._attrs['name']
-
- @property
- def target(self):
- return self._attrs['target']
-
- @property
- def install(self):
- return self._attrs['target']
-
-
-class Touch(LoraxAction):
-
- REGEX = r'^(?P.*?)$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['filename'] = kwargs.get('filename')
-
- def execute(self, verbose=False):
- touch(filename=self.filename, verbose=verbose)
- self._attrs['success'] = True
-
- @property
- def filename(self):
- return self._attrs['filename']
-
-
-class Edit(Touch):
-
- REGEX = r'^(?P.*?)\stext\s"(?P.*?)"(\s(?Pappend))?$'
-
- def __init__(self, **kwargs):
- Touch.__init__(self, **kwargs)
- self._attrs['text'] = kwargs.get('text')
-
- append = kwargs.get('append', False)
- if append:
- self._attrs['append'] = True
- else:
- self._attrs['append'] = False
-
- def execute(self, verbose=False):
- edit(filename=self.filename, text=self.text, append=self.append, verbose=verbose)
- self._attrs['success'] = True
-
- @property
- def text(self):
- return self._attrs['text']
-
- @property
- def append(self):
- return self._attrs['append']
-
- @property
- def install(self):
- return self._attrs['filename']
-
-
-class Replace(Touch):
-
- REGEX = r'^(?P.*?)\sfind\s"(?P.*?)"\sreplace\s"(?P.*?)"$'
-
- def __init__(self, **kwargs):
- Touch.__init__(self, **kwargs)
- self._attrs['find'] = kwargs.get('find')
- self._attrs['replace'] = kwargs.get('replace')
-
- def execute(self, verbose=False):
- replace(filename=self.filename, find=self.find, replace=self.replace, verbose=verbose)
- self._attrs['success'] = True
-
- @property
- def find(self):
- return self._attrs['find']
-
- @property
- def replace(self):
- return self._attrs['replace']
-
- @property
- def install(self):
- return self._attrs['filename']
-
-
-class MakeDir(LoraxAction):
-
- REGEX = r'^(?P.*?)(\smode\s(?P.*?))?$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['dir'] = kwargs.get('dir')
- self._attrs['mode'] = kwargs.get('mode')
-
- def execute(self, verbose=False):
- if not os.path.isdir(self.dir):
- if self.mode:
- os.makedirs(self.dir, mode=int(self.mode))
- else:
- os.makedirs(self.dir)
- self._attrs['success'] = True
-
- @property
- def dir(self):
- return self._attrs['dir']
-
- @property
- def mode(self):
- return self._attrs['mode']
-
-
-class Chmod(LoraxAction):
-
- REGEX = r'^(?P.*?)\smode\s(?P[0-9]*?)$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['filename'] = kwargs.get('filename')
- self._attrs['mode'] = kwargs.get('mode')
-
- def execute(self, verbose=False):
- chmod(self.filename, self.mode)
- self._attrs['success'] = True
-
- @property
- def filename(self):
- return self._attrs['filename']
-
- @property
- def mode(self):
- return self._attrs['mode']
-
-
-class Chown(LoraxAction):
-
- REGEX = r'^(?P.*?)\suser\s(?P.*?)\sgroup\s(?P.*?)$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['filename'] = kwargs.get('filename')
- self._attrs['user'] = kwargs.get('user')
- self._attrs['group'] = kwargs.get('group')
-
- def execute(self, verbose=False):
- uid = pwd.getpwnam(self.user)[2]
- gid = grp.getgrnam(self.group)[2]
- os.chown(self.filename, uid, gid)
- self._attrs['success'] = True
-
- @property
- def filename(self):
- return self._attrs['filename']
-
- @property
- def user(self):
- return self._attrs['user']
-
- @property
- def group(self):
- return self._attrs['group']
-
-
-class GenerateSSHKey(LoraxAction):
-
- REGEX = r'^(?P.*?)\stype\s(?P.*?)$'
-
- def __init__(self, **kwargs):
- LoraxAction.__init__(self)
- self._attrs['file'] = kwargs.get('file')
- self._attrs['type'] = kwargs.get('type')
-
- def execute(self, verbose=False):
- cmd = "/usr/bin/ssh-keygen -q -t %s -f %s -C '' -N ''" % (self.type, self.file)
- err, output = commands.getstatusoutput(cmd)
-
- if not err:
- os.chmod(self.file, 0600)
- os.chmod(self.file + '.pub', 0644)
-
- self._attrs['success'] = True
-
- @property
- def file(self):
- return self._attrs['file']
-
- @property
- def type(self):
- return self._attrs['type']
diff --git a/src/pylorax/config.py b/src/pylorax/config.py
index aee19a1f..e7ee5a27 100644
--- a/src/pylorax/config.py
+++ b/src/pylorax/config.py
@@ -1,90 +1,191 @@
#
# config.py
-# lorax configuration
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
#
-from misc import seq
+import os
+
+import singleton
+import output
-class Container(object):
+class LoraxConfig(singleton.Singleton):
- def __init__(self, attrs=None):
- self.__dict__["__internal"] = {}
- self.__dict__["__internal"]["attrs"] = set()
+ def __init__(self):
+ self.confdir = "/etc/lorax"
+ self.datadir = "/usr/share/lorax"
- if attrs:
- self.addAttr(attrs)
-
- def __str__(self):
- return str(self.__makeDict())
-
- def __iter__(self):
- return iter(self.__makeDict())
-
- def __getitem__(self, attr):
- self.__checkInternal(attr)
-
- if attr not in self.__dict__:
- raise AttributeError, "object has no attribute '%s'" % attr
-
- return self.__dict__[attr]
+ self.colors = True
+ self.encoding = "utf-8"
+ self.debug = False
+ self.cleanup = False
def __setattr__(self, attr, value):
- raise AttributeError, "you can't do that, use addAttr() and/or set() instead"
+ output.Terminal.get().debug("[%s = %s]" % (attr, value))
+ singleton.Singleton.__setattr__(self, attr, value)
- def __delattr__(self, attr):
- raise AttributeError, "you can't do that, use delAttr() instead"
- def addAttr(self, attrs):
- for attr in filter(lambda attr: attr not in self.__dict__, seq(attrs)):
- self.__checkInternal(attr)
+class LoraxPaths(singleton.Singleton):
- self.__dict__[attr] = None
- self.__dict__["__internal"]["attrs"].add(attr)
+ def __init__(self):
+ self.datadir = LoraxConfig.get().datadir
+ self.installtree = LoraxConfig.get().installtree
- def delAttr(self, attrs):
- for attr in filter(lambda attr: attr in self.__dict__, seq(attrs)):
- self.__checkInternal(attr)
+ @property
+ def ANACONDA_PACKAGE(self): return "anaconda"
- del self.__dict__[attr]
- self.__dict__["__internal"]["attrs"].discard(attr)
+ @property
+ def INITRD_DATADIR(self):
+ return os.path.join(self.datadir, "initrd")
- def set(self, **kwargs):
- unknown = set()
- for attr, value in kwargs.items():
- self.__checkInternal(attr)
+ @property
+ def INSTALLTREE_DATADIR(self):
+ return os.path.join(self.datadir, "installtree")
- if attr in self.__dict__:
- self.__dict__[attr] = value
- else:
- unknown.add(attr)
+ @property
+ def OUTPUTDIR_DATADIR(self):
+ return os.path.join(self.datadir, "outputdir")
- return unknown
+ @property
+ def BOOTDIR(self):
+ return os.path.join(self.installtree, "boot")
- def __makeDict(self):
- d = {}
- for attr in self.__dict__["__internal"]["attrs"]:
- d[attr] = self.__dict__[attr]
+ @property
+ def BOOTDIR_IA64(self):
+ return os.path.join(self.BOOTDIR, "efi", "EFI", "redhat")
- return d
+ @property
+ def ANACONDA_RUNTIME(self):
+ return os.path.join(self.installtree, "usr", "lib", "anaconda-runtime")
- def __checkInternal(self, attr):
- if attr.startswith("__"):
- raise AttributeError, "do not mess with internal objects"
+ @property
+ def ANACONDA_BOOT(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "boot")
+
+ @property
+ def SYSLINUXDIR(self):
+ return os.path.join(self.installtree, "usr", "lib", "syslinux")
+
+ @property
+ def ISOLINUXBIN(self):
+ return os.path.join(self.SYSLINUXDIR, "isolinux.bin")
+
+ @property
+ def SYSLINUXCFG(self):
+ return os.path.join(self.ANACONDA_BOOT, "syslinux.cfg")
+
+ @property
+ def GRUBCONF(self):
+ return os.path.join(self.ANACONDA_BOOT, "grub.conf")
+
+ @property
+ def GRUBEFI(self):
+ return os.path.join(self.BOOTDIR, "efi", "EFI", "redhat", "grub.efi")
+
+ @property
+ def VESASPLASH(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "syslinux-vesa-splash.jpg")
+
+ @property
+ def VESAMENU(self):
+ return os.path.join(self.SYSLINUXDIR, "vesamenu.c32")
+
+ @property
+ def SPLASHTOOLS(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "splashtools.sh")
+
+ @property
+ def SPLASHLSS(self):
+ return os.path.join(self.ANACONDA_BOOT, "splash.lss")
+
+ @property
+ def SYSLINUXSPLASH(self):
+ return os.path.join(self.ANACONDA_BOOT, "syslinux-splash.jpg")
+
+ @property
+ def SPLASHXPM(self):
+ return os.path.join(self.BOOTDIR, "grub", "splash.xpm.gz")
+
+ @property
+ def MODULES_DIR(self):
+ return os.path.join(self.installtree, "lib", "modules",
+ LoraxConfig.get().kernelver)
+
+ @property
+ def MODULES_DEP(self):
+ return os.path.join(self.MODULES_DIR, "modules.dep")
+
+ @property
+ def MODINFO(self): return "/sbin/modinfo"
+
+ @property
+ def MODLIST(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "modlist")
+
+ @property
+ def DEPMOD(self): return "/sbin/depmod"
+
+ @property
+ def GETKEYMAPS(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "getkeymaps")
+
+ @property
+ def LOCALEDEF(self): return "/usr/bin/localedef"
+
+ @property
+ def GENINITRDSZ(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "geninitrdsz")
+
+ @property
+ def REDHAT_EXEC(self):
+ return os.path.join(self.ANACONDA_BOOT, "redhat.exec")
+
+ @property
+ def GENERIC_PRM(self):
+ return os.path.join(self.ANACONDA_BOOT, "generic.prm")
+
+ @property
+ def MKS390CD(self):
+ return os.path.join(self.ANACONDA_RUNTIME, "mk-s390-cdboot")
+
+ @property
+ def MKSQUASHFS(self): return "/sbin/mksquashfs"
+
+ @property
+ def MKCRAMFS(self): return "/sbin/mkfs.cramfs"
+
+ @property
+ def MKISOFS(self): return "/usr/bin/mkisofs"
+
+ @property
+ def MKDOSFS(self): return "/sbin/mkdosfs"
+
+ @property
+ def ISOHYBRID(self): return "/usr/bin/isohybrid"
+
+ @property
+ def SYSTEM_MAP(self):
+ return os.path.join(self.BOOTDIR,
+ "System.map-%s" % LoraxConfig.get().kernelver)
+
+ @property
+ def KEYMAPS_OVERRIDE(self):
+ return os.path.join(self.ANACONDA_RUNTIME,
+ "keymaps-override-%s" % LoraxConfig.get().arch)
+
+ @property
+ def LANGTABLE(self):
+ return os.path.join(self.installtree, "usr", "lib", "anaconda",
+ "lang-table")
+
+ @property
+ def LOCALEPATH(self):
+ return os.path.join(self.installtree, "usr", "share", "locale")
+
+ @property
+ def MANCONFIG(self):
+ return os.path.join(self.installtree, "etc", "man.config")
+
+ @property
+ def FEDORAKMODCONF(self):
+ return os.path.join(self.installtree, "etc", "yum", "pluginconf.d",
+ "fedorakmod.conf")
diff --git a/src/pylorax/efi.py b/src/pylorax/efi.py
new file mode 100644
index 00000000..ef892c90
--- /dev/null
+++ b/src/pylorax/efi.py
@@ -0,0 +1,213 @@
+#
+# efi.py
+#
+
+import sys
+import os
+import shutil
+import tempfile
+import commands
+
+import config
+import output
+import utils
+
+
+class EFI(object):
+
+ def __init__(self):
+ self.conf = config.LoraxConfig.get()
+ self.paths = config.LoraxPaths.get()
+ self.output = output.Terminal.get()
+
+ def create_efiboot(self, kernel=None, initrd=None,
+ kernelpath=None, initrdpath=None):
+
+ # create the temporary efi tree directory
+ efitreedir = tempfile.mkdtemp(prefix="efitree.", dir=self.conf.tempdir)
+
+ # copy kernel and initrd files to efi tree directory
+ if kernel and initrd:
+ shutil.copy2(kernel, os.path.join(efitreedir, "vmlinuz"))
+ shutil.copy2(initrd, os.path.join(efitreedir, "initrd.img"))
+ efikernelpath = "/EFI/BOOT/vmlinuz"
+ efiinitrdpath = "/EFI/BOOT/initrd.img"
+ else:
+ efikernelpath = kernelpath
+ efiinitrdpath = initrdpath
+
+ # copy conf files to efi tree directory
+ utils.scopy(src_root=self.conf.anaconda_boot, src_path="*.conf",
+ dst_root=efitreedir, dst_path="")
+
+ # edit the grub.conf file
+ grubconf = os.path.join(efitreedir, "grub.conf")
+ utils.replace(grubconf, "@PRODUCT@", self.conf.product)
+ utils.replace(grubconf, "@VERSION@", self.conf.version)
+ utils.replace(grubconf, "@KERNELPATH@", efikernelpath)
+ utils.replace(grubconf, "@INITRDPATH@", efiinitrdpath)
+ utils.replace(grubconf, "@SPLASHPATH@", "/EFI/BOOT/splash.xpm.gz")
+
+ # copy grub.efi
+ shutil.copy2(self.paths.GRUBEFI, efitreedir)
+
+ # the first generation mactel machines get the bootloader name wrong
+ if self.conf.efiarch == "IA32":
+ src = os.path.join(efitreedir, "grub.efi")
+ dst = os.path.join(efitreedir, "BOOT.efi")
+ shutil.copy2(src, dst)
+
+ src = os.path.join(efitreedir, "grub.conf")
+ dst = os.path.join(efitreedir, "BOOT.conf")
+ shutil.copy2(src, dst)
+
+ src = os.path.join(efitreedir, "grub.efi")
+ dst = os.path.join(efitreedir, "BOOT%s.efi" % self.conf.efiarch)
+ shutil.move(src, dst)
+
+ src = os.path.join(efitreedir, "grub.conf")
+ dst = os.path.join(efitreedir, "BOOT%s.conf" % self.conf.efiarch)
+ shutil.move(src, dst)
+
+ # copy splash.xpm.gz
+ shutil.copy2(self.paths.SPLASHXPM, efitreedir)
+
+ efiboot = os.path.join(self.conf.tempdir, "efiboot.img")
+ if os.path.isfile(efiboot):
+ os.unlink(efiboot)
+
+ # calculate the size of the efitree directory
+ sizeinbytes = 0
+ for root, dirs, files in os.walk(efitreedir):
+ for file in files:
+ filepath = os.path.join(root, file)
+ sizeinbytes += os.path.getsize(filepath)
+
+ # mkdosfs needs the size in blocks of 1024 bytes
+ size = int(round(sizeinbytes / 1024.0))
+
+ # add 100 blocks for the filesystem overhead
+ size += 100
+
+ cmd = "%s -n ANACONDA -C %s %s > /dev/null" % (self.paths.MKDOSFS,
+ efiboot, size)
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return None
+
+ # mount the efiboot image
+ efibootdir = tempfile.mkdtemp(prefix="efiboot.", dir=self.conf.tempdir)
+
+ cmd = "mount -o loop,shortname=winnt,umask=0777 -t vfat %s %s" % \
+ (efiboot, efibootdir)
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return None
+
+ # copy the files to the efiboot image
+ utils.scopy(src_root=efitreedir, src_path="*",
+ dst_root=efibootdir, dst_path="")
+
+ # unmount the efiboot image
+ cmd = "umount %s" % efibootdir
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+ pass
+
+ # copy the conf files to the output directory
+ if not kernel and not initrd:
+ utils.scopy(src_root=efitreedir, src_path="*.conf",
+ dst_root=self.conf.efibootdir, dst_path="")
+
+ return efiboot
+
+ def create_efidisk(self, efiboot):
+ efidisk = os.path.join(self.conf.tempdir, "efidisk.img")
+ if os.path.isfile(efidisk):
+ os.unlink(efidisk)
+
+ partsize = os.path.getsize(efiboot)
+ disksize = 17408 + partsize + 17408
+ disksize = disksize + (disksize % 512)
+
+ with open(efidisk, "wb") as f:
+ f.truncate(disksize)
+
+ cmd = "losetup -v -f %s | awk '{print $4}'" % efidisk
+ err, loop = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(loop)
+ os.unlink(efidisk)
+ return None
+
+ cmd = 'dmsetup create efiboot --table "0 %s linear %s 0"' % \
+ (disksize / 512, loop)
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ self.remove_loop_dev(loop)
+ os.unlink(efidisk)
+ return None
+
+ cmd = "parted --script /dev/mapper/efiboot " \
+ "mklabel gpt unit b mkpart '\"EFI System Partition\"' " \
+ "fat32 17408 %s set 1 boot on" % (partsize + 17408)
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ self.remove_dm_dev("efiboot")
+ self.remove_loop_dev(loop)
+ os.unlink(efidisk)
+ return None
+
+ with open(efiboot, "rb") as f_from:
+ with open("/dev/mapper/efibootp1", "wb") as f_to:
+ efidata = f_from.read(1024)
+ while efidata:
+ f_to.write(efidata)
+ efidata = f_from.read(1024)
+
+ self.remove_dm_dev("efibootp1")
+ self.remove_dm_dev("efiboot")
+ self.remove_loop_dev(loop)
+
+ return efidisk
+
+ def remove_loop_dev(self, dev):
+ cmd = "losetup -d %s" % dev
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+
+ def remove_dm_dev(self, dev):
+ cmd = "dmsetup remove /dev/mapper/%s" % dev
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+
+ def create(self, kernel=None, initrd=None,
+ kernelpath=None, initrdpath=None):
+
+ # create the efiboot image
+ efiboot = self.create_efiboot(kernel, initrd)
+ if efiboot is None:
+ self.output.critical("unable to create the efiboot image")
+ sys.exit(1)
+
+ # create the efidisk image
+ efidisk = self.create_efidisk(efiboot)
+ if efidisk is None:
+ self.output.critical("unable to create the efidisk image")
+ sys.exit(1)
+
+ # create the efiboot image again
+ efiboot = self.create_efiboot(kernelpath=kernelpath,
+ initrdpath=initrdpath)
+ if efiboot is None:
+ self.output.critical("unable to create the efiboot image")
+ sys.exit(1)
+
+ return efiboot, efidisk
diff --git a/src/pylorax/images.py b/src/pylorax/images.py
deleted file mode 100644
index 34f31eb2..00000000
--- a/src/pylorax/images.py
+++ /dev/null
@@ -1,867 +0,0 @@
-#
-# images.py
-# lorax images manipulation
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import sys
-import os
-import glob
-import shutil
-import commands
-import re
-
-import actions
-import actions.base
-
-from template import Template
-
-from utils.fileutils import copy, remove, touch, edit, replace
-from utils.ldd import LDD
-
-
-class InitRD(object):
-
- def __init__(self, config, yum, output):
- self.conf = config
- self.yum = yum
-
- self.so, self.se = output
-
- def read_template(self):
- # get supported actions
- supported_actions = actions.getActions(verbose=self.conf.debug)
-
- # variables supported in templates
- vars = { "instroot": self.conf.treedir,
- "initrd": self.conf.initrddir,
- "libdir": self.conf.libdir,
- "buildarch": self.conf.buildarch,
- "basearch": self.conf.basearch,
- "confdir" : self.conf.confdir,
- "datadir": self.conf.datadir }
-
- # parse the template file
- initrd_template = os.path.join(self.conf.confdir, "initrd",
- "initrd.%s" % self.conf.buildarch)
-
- self.template = Template()
- self.template.preparse(initrd_template)
- self.template.parse(supported_actions, vars)
-
- def install_required_packages(self):
- packages = set()
- for action in filter(lambda action: action.install, self.template.actions):
- m = re.match(r"%s(.*)" % (self.conf.treedir,), action.install)
- if m:
- packages.add(m.group(1))
-
- for package in packages:
- ok = self.yum.add_package(package)
- if not ok:
- self.se.error("No package '%s' found" % (package,))
-
- self.yum.install()
-
- def get_file_dependencies(self):
- libroots = []
- libroots.append(os.path.join(self.conf.treedir, self.conf.libdir))
- libroots.append(os.path.join(self.conf.treedir, "usr", self.conf.libdir))
-
- # on 64 bit systems, add also normal lib directories
- if self.conf.libdir.endswith("64"):
- libdir = self.conf.libdir[:-2]
- libroots.append(os.path.join(self.conf.treedir, libdir))
- libroots.append(os.path.join(self.conf.treedir, "usr", libdir))
-
- ldd = LDD(libroots)
-
- for action in self.template.actions:
- if action.getDeps:
- [ldd.getDeps(fname) for fname in glob.glob(action.getDeps)]
-
- if ldd.errors:
- # XXX ldd didn't get all the dependencies, what now?
- for filename, error in ldd.errors:
- self.se.error(filename)
- self.se.error(error)
-
- # additional actions that need to be processed
- self._actions = []
-
- # add dependencies to actions, so they are copied too
- for dep in ldd.deps:
- kwargs = {}
- kwargs["src_root"] = self.conf.treedir
- kwargs["src_path"] = dep.replace(self.conf.treedir + "/", "", 1)
- kwargs["dst_root"] = self.conf.initrddir
- kwargs["dst_path"] = os.path.dirname(kwargs["src_path"])
-
- if kwargs["dst_path"].startswith("/"):
- kwargs["dst_path"] = kwargs["dst_path"][1:]
-
- new_action = actions.base.Copy(**kwargs)
- self._actions.append(new_action)
-
- def process_actions(self):
- for action in self.template.actions:
- action.execute()
-
- # process dependencies
- for action in self._actions:
- action.execute()
-
- def create_modinfo(self, moddir, target):
- # XXX why do we need this thing?
- mods = {}
- for root, dirs, files in os.walk(moddir):
- for file in files:
- mods[file] = os.path.join(root, file)
-
- modules = { "scsi_hostadapter" : ["block"],
- "eth" : ["networking"] }
- blacklist = ("floppy", "scsi_mod", "libiscsi")
-
- list = {}
- for modtype in modules:
- list[modtype] = {}
- for file in modules[modtype]:
- try:
- filename = os.path.join(moddir, "modules.%s" % file)
- f = open(filename, "r")
- except IOError as why:
- self.se.error("Unable to open file '%s'" % (filename,))
- continue
- else:
- lines = f.readlines()
- f.close()
-
- for line in lines:
- line = line.strip()
- if line in mods:
- modname, ext = os.path.splitext(line)
- if modname in blacklist:
- continue
-
- cmd = "modinfo -F description %s" % (mods[line],)
- outtext = commands.getoutput(cmd)
-
- desc = outtext.split("\n")[0]
- desc = desc.strip()
- desc = desc[:65]
-
- if not desc:
- desc = "%s driver" % modname
- modinfo = '%s\n\t%s\n\t"%s"\n' % (modname, modtype, desc)
- list[modtype][modname] = modinfo
-
- f = open(target, "a")
- f.write("Version 0\n")
- for type in list:
- modlist = list[type].keys()
- modlist.sort()
- for m in modlist:
- f.write("%s\n" % (list[type][m],))
- f.close()
-
- def get_kernel_modules(self):
- kernelver = self.conf.kernelver
-
- modfiles = []
- modfiles.append(os.path.join(self.conf.confdir, "modules",
- "modules.all"))
- modfiles.append(os.path.join(self.conf.confdir, "modules",
- "modules.%s" % (self.conf.buildarch,)))
-
- src_moddir = os.path.join(self.conf.treedir, "lib", "modules", kernelver)
- dst_moddir = os.path.join(self.conf.initrddir, "lib", "modules", kernelver)
-
- # get the modules from configuration files
- modules = set()
- for file in modfiles:
- if os.path.isfile(file):
- f = open(file, "r")
- lines = f.readlines()
- f.close()
-
- for line in lines:
- line, sep, comment = line.partition("#")
- line = line.strip()
-
- if not line:
- continue
-
- if line.startswith("-"):
- modules.discard(line[1:])
- elif line.startswith("="):
- # expand modules
- group = line[1:]
-
- if group in ("scsi", "ata"):
- path = os.path.join(src_moddir, "modules.block")
- elif group == "net":
- path = os.path.join(src_moddir, "modules.networking")
- else:
- path = os.path.join(src_moddir, "modules.%s" % (group,))
-
- if os.path.isfile(path):
- f = open(path, "r")
- for module in f.readlines():
- module = module.strip()
- module = module.replace(".ko", "")
- modules.add(module)
- f.close()
- else:
- modules.add(line)
-
- # resolve modules dependencies
- depfile = os.path.join(src_moddir, "modules.dep")
- f = open(depfile, "r")
- lines = f.readlines()
- f.close()
-
- changed = True
- while changed:
- for line in lines:
- changed = False
- line = line.strip()
-
- m = re.match(r"^.*/(?P.*)\.ko:(?P.*)$", line)
- modname = m.group("name")
-
- if modname in modules:
- for dep in m.group("deps").split():
- m = re.match(r"^.*/(?P.*)\.ko$", dep)
- depname = m.group("name")
-
- if depname not in modules:
- changed = True
- modules.add(depname)
-
- # copy the modules directory
- copy(src_root=self.conf.treedir,
- src_path=os.path.join("lib", "modules", kernelver),
- dst_root=self.conf.initrddir,
- dst_path=os.path.join("lib", "modules"))
-
- # remove not needed modules
- for root, dirs, files in os.walk(dst_moddir):
- for file in files:
- full_path = os.path.join(root, file)
- name, ext = os.path.splitext(file)
-
- if ext == ".ko":
- if name not in modules:
- remove(full_path)
- else:
- # copy the required firmware
- cmd = "modinfo -F firmware %s" % (full_path,)
- err, output = commands.getstatusoutput(cmd)
-
- for fw in output.split():
- dst = os.path.join(self.conf.initrddir,
- "lib", "firmware", fw)
-
- dir = os.path.dirname(dst)
- if not os.path.exists(dir):
- os.makedirs(dir)
-
- copy(src_root = self.conf.treedir,
- src_path = os.path.join("lib", "firmware", fw),
- dst_root = self.conf.initrddir,
- dst_path = os.path.join("lib", "firmware", fw))
-
- # copy additional firmware
- srcdir = os.path.join(self.conf.treedir, "lib", "firmware")
- dstdir = os.path.join(self.conf.initrddir, "lib", "firmware")
-
- fw = ( ("ipw2100", "ipw2100*"),
- ("ipw2200", "ipw2200*"),
- ("iwl3945", "iwlwifi-3945*"),
- ("iwl4965", "iwlwifi-4965*"),
- ("atmel", "atmel_*.bin"),
- ("zd1211rw", "zd1211"),
- ("qla2xxx", "ql*") )
-
- for module, file in fw:
- if module in modules:
- copy(src_root=self.conf.treedir,
- src_path=os.path.join("lib", "firmware", file),
- dst_root=self.conf.initrddir,
- dst_path=os.path.join("lib", "firmware"))
-
- # compress modules
- cmd = "find -H %s -type f -name *.ko -exec gzip -9 {} \\;" % (dst_moddir,)
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.debug(output)
-
- # create modinfo
- modinfo = os.path.join(self.conf.tempdir, "modinfo")
- self.create_modinfo(src_moddir, modinfo)
-
- modlist = os.path.join(self.conf.treedir,
- "usr", "lib", "anaconda-runtime", "modlist")
-
- target = os.path.join(self.conf.initrddir, "lib", "modules", "module-info")
- cmd = "%s --modinfo-file %s --ignore-missing --modinfo %s > %s" % \
- (modlist, modinfo, " ".join(list(modules)), target)
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.debug(output)
-
- # run depmod
- systemmap = os.path.join(self.conf.treedir, "boot", "System.map-%s" \
- % (kernelver,))
- cmd = "/sbin/depmod -a -F %s -b %s %s" % (systemmap,
- self.conf.initrddir, kernelver)
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.debug(output)
-
- # remove leftovers
- remove(os.path.join(dst_moddir, "modules.*map"))
-
- def trim_pci_ids(self):
- # FIXME remove this function, just copy the original pci.ids file
-
- kernelver = self.conf.kernelver
-
- vendors = set()
- devices = set()
-
- modulesalias = os.path.join(self.conf.treedir,
- "lib", "modules", kernelver, "modules.alias")
- f = open(modulesalias)
- pcitable = f.readlines()
- f.close()
-
- for line in pcitable:
- if not line.startswith("alias pci:"):
- continue
-
- vend = "0x%s" % (line[15:19],)
- vend = vend.upper()
- dev = "0x%s" % (line[24:28],)
- dev = dev.upper()
-
- vendors.add(vend)
- devices.add((vend, dev))
-
- videoaliases = os.path.join(self.conf.treedir,
- "usr", "share", "hwdata", "videoaliases", "*")
- for file in glob.iglob(videoaliases):
- f = open(file)
- pcitable = f.readlines()
- f.close()
-
- for line in pcitable:
- if not line.startswith("alias pcivideo:"):
- continue
-
- vend = "0x%s" % (line[20:24],)
- vend = vend.upper()
- dev = "0x%s" % (line[29:33],)
- dev = dev.upper()
-
- vendors.add(vend)
- devices.add((vend, dev))
-
- # create the pci.ids file
- src = os.path.join(self.conf.treedir, "usr", "share", "hwdata", "pci.ids")
- dst = os.path.join(self.conf.initrddir, "usr", "share", "hwdata", "pci.ids")
-
- input = open(src, "r")
- pcitable = input.readlines()
- input.close()
-
- output = open(dst, "w")
-
- current_vend = 0
- for line in pcitable:
- # skip lines that start with 2 tabs or #
- if line.startswith("\t\t") or line.startswith("#"):
- continue
-
- # skip empty lines
- if line == "\n":
- continue
-
- # end of file
- if line == "ffff Illegal Vendor ID":
- break
-
- if not line.startswith("\t"):
- current_vend = "0x%s" % (line.split()[0],)
- current_vend = current_vend.upper()
- if current_vend in vendors:
- output.write(line)
- continue
-
- dev = "0x%s" % (line.split()[0],)
- dev = dev.upper()
- if (current_vend, dev) in devices:
- output.write(line)
-
- output.close()
-
- def get_keymaps(self):
- anadir = os.path.join(self.conf.treedir, "usr", "lib", "anaconda-runtime")
- override = os.path.join(anadir,
- "keymaps-override-%s" % (self.conf.buildarch,))
-
- if os.path.isfile(override):
- self.so.debug("Found keymap override, using it")
- shutil.copy2(override,
- os.path.join(self.conf.initrddir, "etc", "keymaps.gz"))
- else:
- cmd = "%s %s %s %s" % (os.path.join(anadir, "getkeymaps"),
- self.conf.buildarch,
- os.path.join(self.conf.initrddir, "etc", "keymaps.gz"),
- self.conf.treedir)
-
- err, output = commands.getstatusoutput(cmd)
- if err:
- return False
-
- return True
-
- def create_locales(self):
- os.makedirs(os.path.join(self.conf.initrddir, "usr", "lib", "locale"))
- err, output = commands.getstatusoutput("localedef -c -i en_US -f UTF-8"
- " --prefix %s en_US" % (self.conf.initrddir,))
-
- def create(self, target):
- # copy the .buildstamp file
- shutil.copy2(self.conf.buildstamp, self.conf.initrddir)
-
- cwd = os.getcwd()
- os.chdir(self.conf.initrddir)
-
- cmd = "find . | cpio --quiet -c -o | gzip -9 > %s" % (target,)
- output = commands.getoutput(cmd)
-
- os.chdir(cwd)
-
- def run(self):
- # create the temporary directory for initrd
- initrddir = os.path.join(self.conf.tempdir, "initrddir",
- self.conf.kernelver)
- self.so.info("Creating the temporary initrd directory")
- os.makedirs(initrddir)
- self.conf.addAttr("initrddir")
- self.conf.set(initrddir=initrddir)
-
- self.so.info("Reading the initrd template file")
- self.read_template()
-
- self.so.info("Installing additional packages")
- self.install_required_packages()
-
- self.so.info("Getting required dependencies")
- self.get_file_dependencies()
-
- self.so.info("Copying required files to initrd directory")
- self.process_actions()
-
- self.so.info("Getting required kernel modules")
- self.get_kernel_modules()
-
- self.so.info("Getting the pci.ids file")
- self.trim_pci_ids()
-
- ok = self.get_keymaps()
- if not ok:
- self.se.error("Unable to create the keymaps")
- sys.exit(1)
-
- self.so.info("Creating locales")
- self.create_locales()
-
- f = getattr(self, "run_%s" % (self.conf.buildarch,), None)
- if f:
- f()
-
- def run_i386(self):
- initrd_filename = "initrd.img"
- kernel_filename = "vmlinuz"
-
- if self.conf.kernelfile.endswith("PAE"):
- initrd_filename = "initrd-PAE.img"
- kernel_filename = "vmlinuz-PAE"
-
- text = "[images-xen]\n"
- text += "kernel = images/pxeboot/vmlinuz-PAE\n"
- text += "initrd = images/pxeboot/initrd-PAE.img\n"
- edit(os.path.join(self.conf.outdir, ".treeinfo"),
- append=True, text=text)
-
- self.so.info("Compressing the image file '%s'" % (initrd_filename,))
- self.create(os.path.join(self.conf.pxebootdir, initrd_filename))
-
- self.so.info("Copying the kernel file")
- shutil.copy2(self.conf.kernelfile,
- os.path.join(self.conf.pxebootdir, kernel_filename))
-
- if not self.conf.kernelfile.endswith("PAE"):
- # copy the kernel and initrd to the isolinux directory
- shutil.copy2(self.conf.kernelfile,
- os.path.join(self.conf.isolinuxdir, kernel_filename))
- shutil.copy2(os.path.join(self.conf.pxebootdir, initrd_filename),
- os.path.join(self.conf.isolinuxdir, initrd_filename))
-
- # create the efi images
- efi = EFI(self.conf, (self.so, self.se))
- efi.run(kernelfile=self.conf.kernelfile,
- initrd=os.path.join(self.conf.pxebootdir, initrd_filename),
- kernelpath="/images/pxeboot/vmlinuz",
- initrdpath="/images/pxeboot/initrd.img")
-
- def run_x86_64(self):
- self.run_i386()
-
- def run_s390(self):
- initrd_filename = "initrd.img"
- kernel_filename = "kernel.img"
-
- self.so.info("Compressing the image file '%s'" % (initrd_filename,))
- self.create(os.path.join(self.conf.imagesdir, initrd_filename))
-
- cmd = "ls -l %s | awk '{print $5}'" % \
- (os.path.join(self.conf.imagesdir, initrd_filename),)
- self.so.debug(cmd)
- err, size = commands.getstatusoutput(cmd)
- if err:
- self.se.debug(size)
-
- geninitrdsz = os.path.join(self.conf.treedir, "usr", "lib",
- "anaconda-runtime", "geninitrdsz")
-
- cmd = "%s %s %s" % (geninitrdsz, size,
- os.path.join(self.conf.imagesdir, "initrd.size"))
- self.so.debug(cmd)
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.debug(output)
-
- # copy the kernel file
- shutil.copy2(self.conf.kernelfile,
- os.path.join(self.conf.imagesdir, kernel_filename))
-
- for filename in ("redhat.exec", "generic.prm"):
- shutil.copy2(os.path.join(self.conf.bootdiskdir, filename),
- self.conf.imagesdir)
- shutil.copy2(os.path.join(self.conf.bootdiskdir, filename),
- self.conf.outdir)
-
- mks390cdboot = os.path.join(self.conf.treedir, "usr", "lib",
- "anaconda-runtime", "mk-s390-cdboot")
-
- cmd = "%s -i %s -r %s -p %s -o %s" % (mks390cdboot,
- os.path.join(self.conf.imagesdir, kernel_filename),
- os.path.join(self.conf.imagesdir, initrd_filename),
- os.path.join(self.conf.imagesdir, "generic.prm"),
- os.path.join(self.conf.imagesdir, "cdboot.img"))
- err, output = commands.getstatusoutput(cmd)
- if err:
- self.se.debug(output)
-
- text = "[images-%s" % (self.conf.buildarch,)
- text += "kernel = images/kernel.img"
- text += "initrd = images/initrd.img"
- text += "initrd.size = images/initrd.size"
- text += "generic.prm = images/generic.prm"
- text += "generic.ins = generic.ins"
- text += "cdboot.img = images/cdboot.img"
- edit(os.path.join(self.conf.outdir, ".treeinfo"),
- append=True, text=text)
-
- def run_s390x(self):
- self.run_s390()
-
- def run_alpha(self):
- kerneldir = os.path.join(self.conf.outdir, "kernels")
- if not os.path.isdir(kerneldir):
- os.makedirs(kerneldir)
-
- # XXX check for the jensen kernel file, how can we differentiate it?
- # i don't know the filename...
- if self.conf.kernelfile.endswith("jensen"):
- copy(self.conf.kernelfile,
- os.path.join(kerneldir, "vmlinux.j"))
- else:
- copy(self.conf.kernelfile,
- os.path.join(kerneldir, "vmlinux.gz"))
-
- os.makedirs(os.path.join(self.conf.outdir, "boot"))
- copy(os.path.join(self.conf.bootdiskdir, "bootlx"),
- os.path.join(self.conf.outdir, "boot"))
-
- os.makedirs(os.path.join(self.conf.outdir, "etc"))
- abootconf = os.path.join(self.conf.outdir, "etc", "aboot.conf")
- touch(abootconf)
-
- text = "0:/kernels/vmlinux.gz initrd=/images/initrd.img\n"
- text += "1:/kernels/vmlinux.gz initrd=/images/initrd.img "
- text += "console=ttyS0\n"
- text += "2:/kernels/vmlinux.gz initrd=/images/initrd.img text\n"
- text += "3:/kernels/vmlinux.gz initrd=/images/initrd.img rescue\n"
- edit(abootconf, text=text)
-
- initrd_filename = "initrd.img"
- self.so.info("Compressing the image file '%s'" % (initrd_filename,))
- self.create(os.path.join(self.conf.imagesdir, initrd_filename))
-
- def run_ia64(self):
- raise NotImplementedError
-
- def run_ppc(self):
- raise NotImplementedError
-
- def run_ppc64(self):
- self.run_ppc()
-
-
-class EFI(object):
-
- def __init__(self, config, output):
- self.conf = config
- self.so, self.se = output
-
- # create the temporary efi directory
- tempdir = os.path.join(self.conf.tempdir, "efi")
- if os.path.exists(tempdir):
- remove(tempdir)
- os.makedirs(tempdir)
- self.tempdir = tempdir
-
- def create(self, kernelfile=None, initrd=None, kernelpath=None, initrdpath=None):
- # create the temporary efi tree directory
- efitreedir = os.path.join(self.tempdir, "tree")
- if os.path.exists(efitreedir):
- remove(efitreedir)
- os.makedirs(efitreedir)
-
- # copy kernel and initrd files to efi tree directory
- if kernelfile and initrd:
- shutil.copy2(kernelfile, os.path.join(efitreedir, "vmlinuz"))
- shutil.copy2(initrd, os.path.join(efitreedir, "initrd.img"))
- efikernelpath = os.path.join("/", "EFI", "BOOT", "vmlinuz")
- efiinitrdpath = os.path.join("/", "EFI", "BOOT", "initrd.img")
- else:
- efikernelpath = kernelpath
- efiinitrdpath = initrdpath
-
- # copy conf files to efi tree directory
- copy(src_root=self.conf.bootdiskdir, src_path="*.conf",
- dst_root=efitreedir, dst_path="")
-
- # edit the grub.conf file
- grubconf = os.path.join(efitreedir, "grub.conf")
- replace(grubconf, "@PRODUCT@", self.conf.product)
- replace(grubconf, "@VERSION@", self.conf.version)
- replace(grubconf, "@KERNELPATH@", efikernelpath)
- replace(grubconf, "@INITRDPATH@", efiinitrdpath)
- replace(grubconf, "@SPLASHPATH@", "/EFI/BOOT/splash.xpm.gz")
-
- # copy grub.efi
- src = os.path.join(self.conf.treedir,
- "boot", "efi", "EFI", "redhat", "grub.efi")
- shutil.copy2(src, efitreedir)
-
- # the first generation mactel machines get the bootloader name wrong
- if self.conf.efiarch == "ia32":
- src = os.path.join(efitreedir, "grub.efi")
- dst = os.path.join(efitreedir, "BOOT.efi")
- shutil.copy2(src, dst)
- src = os.path.join(efitreedir, "grub.conf")
- dst = os.path.join(efitreedir, "BOOT.conf")
- shutil.copy2(src, dst)
-
- efiarch = self.conf.efiarch
- if efiarch == "x64":
- efiarch = efiarch.upper()
- elif efiarch == "ia32":
- efiarch = efiarch.upper()
-
- src = os.path.join(efitreedir, "grub.efi")
- dst = os.path.join(efitreedir, "BOOT%s.efi" % (efiarch,))
- shutil.move(src, dst)
- src = os.path.join(efitreedir, "grub.conf")
- dst = os.path.join(efitreedir, "BOOT%s.conf" % (efiarch,))
- shutil.move(src, dst)
-
- # copy splash
- src = os.path.join(self.conf.treedir, "boot", "grub", "splash.xpm.gz")
- shutil.copy2(src, efitreedir)
-
- # calculate the size of the efi image
- cmd = "du -kcs %s | tail -n1 | awk '{print $1}'" % (efitreedir,)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- size = int(out) + 100
-
- efiimage = os.path.join(self.tempdir, "efiboot.img")
- if os.path.exists(efiimage):
- remove(efiimage)
-
- cmd = "mkdosfs -n ANACONDA -C %s %s > /dev/null" % (efiimage, size)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- # mount the efi image
- efiimagedir = os.path.join(self.tempdir, "efiboot.img.d")
- if os.path.exists(efiimagedir):
- remove(efiimagedir)
- os.makedirs(efiimagedir)
-
- cmd = "mount -o loop,shortname=winnt,umask=0777 -t vfat %s %s" % \
- (efiimage, efiimagedir)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- # copy the files to the efi image
- copy(src_root=efitreedir, src_path="*",
- dst_root=efiimagedir, dst_path="")
-
- # unmount the efi image
- cmd = "umount %s" % (efiimagedir,)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
-
- # copy the conf files to the output directory
- if not kernelfile and not initrd:
- copy(src_root=efitreedir, src_path="*.conf",
- dst_root=self.conf.efibootdir, dst_path="")
-
- return efiimage
-
- def create_bootdisk(self, efiimage):
- cmd = "ls -l %s | awk '{print $5}'" % (efiimage,)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- partsize = int(out)
- disksize = 17408 + partsize + 17408
- disksize = disksize + (disksize % 512)
-
- efidiskimg = os.path.join(self.tempdir, "efidisk.img")
- if os.path.exists(efidiskimg):
- remove(efidiskimg)
- touch(efidiskimg)
-
- cmd = "dd if=/dev/zero of=%s count=1 bs=%s" % (efidiskimg, disksize)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- cmd = "losetup -v -f %s | awk '{print $4}'" % (efidiskimg,)
- self.so.debug(cmd)
- err, loop = commands.getstatusoutput(cmd)
- if err:
- self.se.info(loop)
- return False
-
- cmd = "dmsetup create efiboot --table \"0 %s linear %s 0\"" \
- % (disksize / 512, loop)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- cmd = "parted --script /dev/mapper/efiboot" \
- " mklabel gpt unit b mkpart '\"EFI System Partition\"'" \
- " fat32 17408 %s set 1 boot on" % (partsize + 17408,)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- cmd = "dd if=%s of=/dev/mapper/efibootp1" % (efiimage,)
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- cmd = "dmsetup remove /dev/mapper/efibootp1"
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- cmd = "dmsetup remove /dev/mapper/efiboot"
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- cmd = "losetup -d %s" % loop
- self.so.debug(cmd)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self.se.info(out)
- return False
-
- return efidiskimg
-
- def run(self, kernelfile=None, initrd=None, kernelpath=None, initrdpath=None):
- self.so.info("Creating the EFI image file")
- efiimage = self.create(kernelfile, initrd)
-
- if not efiimage:
- sys.exit(1)
-
- self.so.info("Creating the boot disk")
- bootdisk = self.create_bootdisk(efiimage)
-
- if not bootdisk:
- sys.exit(1)
-
- # copy the boot disk file to the output directory
- dst = os.path.join(self.conf.imagesdir, "efidisk.img")
- shutil.copy2(bootdisk, dst)
-
- self.so.info("Creating the second EFI image file")
- efiimage = self.create(kernelpath=kernelpath, initrdpath=initrdpath)
-
- # copy the efi image to the output directory
- dst = os.path.join(self.conf.imagesdir, "efiboot.img")
- shutil.copy2(efiimage, dst)
diff --git a/src/pylorax/install.py b/src/pylorax/install.py
new file mode 100644
index 00000000..e17b8a8b
--- /dev/null
+++ b/src/pylorax/install.py
@@ -0,0 +1,479 @@
+#
+# install.py
+#
+
+import os
+import shutil
+import glob
+import fnmatch
+import re
+import commands
+import pwd
+import grp
+import stat
+
+import config
+import output
+import lcs
+import utils
+
+
+class InstallImage(object):
+
+ def __init__(self):
+ self.conf = config.LoraxConfig.get()
+ self.paths = config.LoraxPaths.get()
+ self.output = output.Terminal.get()
+
+ self.actions = self.get_actions_from_template()
+
+ def get_actions_from_template(self):
+ variables = { "instroot" : self.conf.installtree }
+
+ if self.conf.scrubs_template is not None:
+ template = lcs.TemplateParser(variables)
+ return template.get_actions(self.conf.scrubs_template)
+
+ return []
+
+ def move_shared_files(self):
+ dirs = [os.path.join(self.paths.INSTALLTREE_DATADIR, "noarch"),
+ os.path.join(self.paths.INSTALLTREE_DATADIR, self.conf.arch)]
+
+ self.output.info(":: copying the custom install tree files")
+ for dir in [dir for dir in dirs if os.path.isdir(dir)]:
+ utils.scopy(src_root=dir, src_path="*",
+ dst_root=self.conf.installtree, dst_path="")
+
+ def process_actions(self):
+ for action in self.actions:
+ action.execute()
+
+ # XXX why do we need this?
+ def copy_stubs(self):
+ for file in ("raidstart", "raidstop", "losetup", "list-harddrives",
+ "loadkeys", "mknod", "syslogd"):
+
+ src = os.path.join(self.conf.installtree, "usr", "lib", "anaconda",
+ "%s-stub" % file)
+ dst = os.path.join(self.conf.installtree, "usr", "bin", file)
+ shutil.copy2(src, dst)
+
+ def configure_fedorakmod(self):
+ utils.replace(self.paths.FEDORAKMODCONF,
+ r"installforallkernels = 0", r"installforallkernels = 1")
+
+ # XXX why do we need this?
+ def copy_bootloaders(self):
+ if self.conf.arch in ("i386", "i586", "x86_64"):
+ for f in glob.glob(os.path.join(self.paths.BOOTDIR, "memtest*")):
+ shutil.copy2(f, self.paths.ANACONDA_BOOT)
+
+ elif self.conf.arch == "sparc":
+ for f in glob.glob(os.path.join(self.paths.BOOTDIR, "*.b")):
+ shutil.copy2(f, self.paths.ANACONDA_BOOT)
+
+ elif self.conf.arch in ("ppc", "ppc64"):
+ f = os.path.join(self.paths.BOOTDIR, "efika.forth")
+ shutil.copy2(f, self.paths.ANACONDA_BOOT)
+
+ # XXX alpha stuff should not be needed anymore
+ #elif self.conf.arch == "alpha":
+ # f = os.path.join(self.paths.BOOTDIR, "bootlx")
+ # shutil.copy2(f, self.paths.ANACONDA_BOOT)
+
+ elif self.conf.arch == "ia64":
+ utils.scopy(src_root=self.paths.BOOTDIR_IA64, src_path="*",
+ dst_root=self.paths.ANACONDA_BOOT, dst_dir="")
+
+ # XXX why do we need this?
+ def move_repos(self):
+ src = os.path.join(self.conf.installtree, "etc", "yum.repos.d")
+ dst = os.path.join(self.conf.installtree, "etc", "anaconda.repos.d")
+ shutil.move(src, dst)
+
+ # XXX why do we need this?
+ def move_anaconda_files(self):
+ # move anaconda executable
+ src = os.path.join(self.conf.installtree, "usr", "sbin", "anaconda")
+ dst = os.path.join(self.conf.installtree, "usr", "bin", "anaconda")
+ shutil.move(src, dst)
+
+ # move anaconda libraries
+ dstdir = os.path.join(self.conf.installtree, "usr", self.conf.libdir)
+ utils.scopy(src_root=self.paths.ANACONDA_RUNTIME, src_path="lib*",
+ dst_root=dstdir, dst_path="")
+
+ utils.remove(os.path.join(self.paths.ANACONDA_RUNTIME, "lib*"))
+
+ # XXX this saves 40 MB
+ def create_modules_symlinks(self):
+ utils.mkdir(os.path.join(self.conf.installtree, "modules"))
+ utils.mkdir(os.path.join(self.conf.installtree, "firmware"))
+
+ utils.remove(os.path.join(self.conf.installtree, "lib", "modules"))
+ utils.remove(os.path.join(self.conf.installtree, "lib", "firmware"))
+
+ utils.symlink("/modules",
+ os.path.join(self.conf.installtree, "lib", "modules"))
+ utils.symlink("/firmware",
+ os.path.join(self.conf.installtree, "lib", "firmware"))
+
+ # XXX why do we need this?
+ def fix_man_pages(self):
+ # fix up some links for man page related stuff
+ for file in ("nroff", "groff", "iconv", "geqn", "gtbl", "gpic",
+ "grefer"):
+
+ target = os.path.join("/mnt/sysimage/usr/bin", file)
+ name = os.path.join(self.conf.installtree, "usr", "bin", file)
+
+ if not os.path.isfile(name):
+ utils.symlink(target, name)
+
+ # fix /etc/man.config to point into /mnt/sysimage
+ utils.replace(self.paths.MANCONFIG, r"^MANPATH\s+(\S+)",
+ "MANPATH\t/mnt/sysimage\g<1>")
+ utils.replace(self.paths.MANCONFIG, r"^MANPATH_MAP\s+(\S+)\s+(\S+)",
+ "MANPATH_MAP\t\g<1>\t/mnt/sysimage\g<2>")
+
+ # XXX this saves 2 MB
+ def remove_gtk_stuff(self):
+ # figure out the gtk+ theme to keep
+ gtkrc = os.path.join(self.conf.installtree, "etc", "gtk-2.0", "gtkrc")
+
+ gtk_theme_name = None
+ gtk_engine = None
+ gtk_icon_themes = []
+
+ if os.path.isfile(gtkrc):
+ f = open(gtkrc, "r")
+ lines = f.readlines()
+ f.close()
+
+ for line in lines:
+ line = line.strip()
+ if line.startswith("gtk-theme-name"):
+ gtk_theme_name = line[line.find("=") + 1:]
+ gtk_theme_name = gtk_theme_name.replace('"', "").strip()
+
+ # find the engine for this theme
+ gtkrc = os.path.join(self.conf.installtree, "usr", "share",
+ "themes", gtk_theme_name, "gtk-2.0", "gtkrc")
+ if os.path.isfile(gtkrc):
+ f = open(gtkrc, "r")
+ engine_lines = f.readlines()
+ f.close()
+
+ for engine_l in engine_lines:
+ engine_l = engine_l.strip()
+ if engine_l.find("engine") != -1:
+ gtk_engine = engine_l[engine_l.find('"') + 1:]
+ gtk_engine = gtk_engine.replace('"', "").strip()
+ break
+
+ elif line.startswith("gtk-icon-theme-name"):
+ icon_theme = line[line.find("=") + 1:]
+ icon_theme = icon_theme.replace('"', "").strip()
+ gtk_icon_themes.append(icon_theme)
+
+ # bring in all inherited themes
+ while True:
+ icon_theme_index = os.path.join(self.conf.installtree,
+ "usr", "share", "icons", icon_theme,
+ "index.theme")
+
+ if os.path.isfile(icon_theme_index):
+ inherits = False
+ f = open(icon_theme_index, "r")
+ icon_lines = f.readlines()
+ f.close()
+
+ for icon_l in icon_lines:
+ icon_l = icon_l.strip()
+ if icon_l.startswith("Inherits="):
+ inherits = True
+ icon_theme = icon_l[icon_l.find("=") + 1:]
+ icon_theme = \
+ icon_theme.replace('"', "").strip()
+
+ gtk_icon_themes.append(icon_theme)
+ break
+
+ if not inherits:
+ break
+ else:
+ break
+
+ # remove themes we don't need
+ theme_path = os.path.join(self.conf.installtree, "usr", "share",
+ "themes")
+
+ if os.path.isdir(theme_path):
+ for theme in filter(lambda theme: theme != gtk_theme_name,
+ os.listdir(theme_path)):
+
+ theme = os.path.join(theme_path, theme)
+ shutil.rmtree(theme, ignore_errors=True)
+
+ # remove icons we don't need
+ icon_path = os.path.join(self.conf.installtree, "usr", "share",
+ "icons")
+
+ if os.path.isdir(icon_path):
+ for icon in filter(lambda icon: icon not in gtk_icon_themes,
+ os.listdir(icon_path)):
+
+ icon = os.path.join(icon_path, icon)
+ shutil.rmtree(icon, ignore_errors=True)
+
+ # remove engines we don't need
+ tmp_path = os.path.join(self.conf.installtree, "usr",
+ self.conf.libdir, "gtk-2.0")
+
+ if os.path.isdir(tmp_path):
+ fnames = map(lambda fname: os.path.join(tmp_path, fname,
+ "engines"), os.listdir(tmp_path))
+
+ dnames = filter(lambda fname: os.path.isdir(fname), fnames)
+ for dir in dnames:
+ engines = filter(lambda e: e.find(gtk_engine) == -1,
+ os.listdir(dir))
+ for engine in engines:
+ engine = os.path.join(dir, engine)
+ os.unlink(engine)
+
+ # XXX this saves 5 MB
+ def remove_locales(self):
+ if os.path.isfile(self.paths.LANGTABLE):
+ keep = set()
+
+ with open(self.paths.LANGTABLE, "r") as f:
+ lines = f.readlines()
+
+ for line in lines:
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+
+ fields = line.split("\t")
+
+ dir = os.path.join(self.paths.LOCALEPATH, fields[1])
+ if os.path.isdir(dir):
+ keep.add(fields[1])
+
+ locale = fields[3].split(".")[0]
+ dir = os.path.join(self.paths.LOCALEPATH, locale)
+ if os.path.isdir(dir):
+ keep.add(locale)
+
+ for locale in os.listdir(self.paths.LOCALEPATH):
+ if locale not in keep:
+ path = os.path.join(self.paths.LOCALEPATH, locale)
+ utils.remove(path)
+
+ # XXX this saves 5 MB
+ def remove_unnecessary_files(self):
+ for root, dirs, files in os.walk(self.conf.installtree):
+ for file in files:
+ path = os.path.join(root, file)
+
+ if fnmatch.fnmatch(path, "*.a"):
+ if path.find("kernel-wrapper/wrapper.a") == -1:
+ os.unlink(path)
+
+ if fnmatch.fnmatch(path, "lib*.la"):
+ if path.find("usr/" + self.conf.libdir + "/gtk-2.0") == -1:
+ os.unlink(path)
+
+ if fnmatch.fnmatch(path, "*.py"):
+ if os.path.isfile(path + "o"):
+ os.unlink(path + "o")
+ if os.path.isfile(path + "c"):
+ os.unlink(path + "c")
+
+ utils.symlink("/dev/null", path + "c")
+
+ # remove libunicode-lite
+ utils.remove(os.path.join(self.conf.installtree, "usr",
+ self.conf.libdir, "libunicode-lite*"))
+
+ # XXX this saves 1 MB
+ def remove_python_stuff(self):
+ for fname in ("bsddb", "compiler", "curses", "distutils", "email",
+ "encodings", "hotshot", "idlelib", "test",
+ "doctest.py", "pydoc.py"):
+
+ utils.remove(os.path.join(self.conf.installtree, "usr",
+ self.conf.libdir, "python?.?", fname))
+
+ # XXX the udev package should get fixed,
+ # but for now, we have to fix it ourselves, otherwise we get an error
+ def fix_udev_links(self):
+ # these links are broken by default (at least on i386)
+ for filename in ("udevcontrol", "udevsettle", "udevtrigger"):
+ filename = os.path.join(self.conf.installtree, "sbin", filename)
+ if os.path.islink(filename):
+ os.unlink(filename)
+ os.symlink("udevadm", filename)
+
+ def move_bins(self):
+ # move bin to usr/bin
+ utils.scopy(src_root=self.conf.installtree,
+ src_path=os.path.join("bin", "*"),
+ dst_root=self.conf.installtree,
+ dst_path=os.path.join("usr", "bin"))
+ utils.remove(os.path.join(self.conf.installtree, "bin"))
+
+ # move sbin to /usr/sbin
+ utils.scopy(src_root=self.conf.installtree,
+ src_path=os.path.join("sbin", "*"),
+ dst_root=self.conf.installtree,
+ dst_path=os.path.join("usr", "sbin"))
+ utils.remove(os.path.join(self.conf.installtree, "sbin"))
+
+ # fix broken links
+ brokenlinks = []
+ for dir in ("bin", "sbin"):
+ dir = os.path.join(self.conf.installtree, "usr", dir)
+ for root, dnames, fnames in os.walk(dir):
+ for fname in fnames:
+ fname = os.path.join(root, fname)
+ if os.path.islink(fname) and not os.path.exists(fname):
+ brokenlinks.append(fname)
+
+ for link in brokenlinks:
+ target = os.readlink(link)
+ newtarget = re.sub(r"^\.\./\.\./(bin|sbin)/(.*)$",
+ r"../\g<1>/\g<2>", target)
+
+ if newtarget != target:
+ os.unlink(link)
+ utils.symlink(newtarget, link)
+
+ def create_ld_so_conf(self):
+ ldsoconf = os.path.join(self.conf.installtree, "etc", "ld.so.conf")
+ utils.touch(ldsoconf)
+
+ procdir = os.path.join(self.conf.installtree, "proc")
+ if not os.path.isdir(procdir):
+ utils.mkdir(procdir)
+
+ cmd = "mount -t proc proc %s" % procdir
+ err, output = commands.getstatusoutput(cmd)
+
+ with open(ldsoconf, "w") as f:
+ f.write("/usr/kerberos/%s\n" % self.conf.libdir)
+
+ cwd = os.getcwd()
+ os.chdir(self.conf.installtree)
+
+ # XXX os.chroot does not support exiting from the root
+ cmd = "/usr/sbin/chroot %s /sbin/ldconfig" % self.conf.installtree
+ err, output = commands.getstatusoutput(cmd)
+
+ os.chdir(cwd)
+
+ cmd = "umount %s" % procdir
+ err, output = commands.getstatusoutput(cmd)
+
+ os.unlink(ldsoconf)
+
+ def change_tree_permissions(self):
+ root_uid = pwd.getpwnam("root")[2]
+ root_gid = grp.getgrnam("root")[2]
+
+ for root, dirs, files in os.walk(self.conf.installtree):
+ os.chown(root, root_uid, root_gid)
+ os.chmod(root, 0755)
+
+ for file in files:
+ # skip broken symlinks
+ if not os.path.exists(file):
+ continue
+
+ path = os.path.join(root, file)
+ os.chown(path, root_uid, root_gid)
+
+ mode = os.stat(path).st_mode
+ if (mode & stat.S_IXUSR) or (mode & stat.S_IXGRP) \
+ or (mode & stat.S_IXOTH):
+ os.chmod(path, 0555)
+ else:
+ os.chmod(path, 0444)
+
+ def prepare(self):
+ # copy the .buildstamp
+ shutil.copy2(self.conf.buildstamp, self.conf.installtree)
+
+ self.move_shared_files()
+ self.process_actions()
+
+ self.copy_stubs()
+ self.configure_fedorakmod()
+ self.copy_bootloaders()
+ self.move_repos()
+ self.move_anaconda_files()
+ self.create_modules_symlinks()
+ self.fix_man_pages()
+ self.remove_gtk_stuff()
+ self.remove_locales()
+ self.remove_unnecessary_files()
+ self.remove_python_stuff()
+ self.fix_udev_links()
+ self.move_bins()
+
+ self.create_ld_so_conf()
+ self.change_tree_permissions()
+
+ def create(self, type="squashfs"):
+ self.prepare()
+
+ installimg = os.path.join(self.conf.tempdir, "install.img")
+
+ if os.path.exists(installimg):
+ os.unlink(installimg)
+
+ self.output.info(":: compressing the image file")
+
+ if type == "squashfs":
+ if not os.path.exists(self.paths.MKSQUASHFS):
+ self.output.error("'%s' does not exist" % self.paths.MKSQUASHFS)
+ return None
+
+ cmd = "%s %s %s -all-root -no-fragments -no-progress" % \
+ (self.paths.MKSQUASHFS, self.conf.installtree, installimg)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return None
+
+ elif type == "cramfs":
+ if not os.path.exists(self.paths.MKCRAMFS):
+ self.output.error("'%s' does not exist" % self.paths.MKCRAMFS)
+ return None
+
+ crambs = ""
+ if self.conf.arch == "sparc64":
+ crambs = "--blocksize 8192"
+ elif self.conf.arch == "sparc":
+ crambs = "--blocksize 4096"
+
+ cmd = "%s %s %s %s" % (self.paths.MKCRAMFS, crambs,
+ self.conf.installtree, installimg)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return None
+
+ elif type == "ext2":
+ # TODO
+ raise NotImplementedError
+
+ # edit the .treeinfo
+ text = "[stage2]\nmainimage = images/install.img\n"
+ utils.edit(self.conf.treeinfo, append=True, text=text)
+
+ return installimg
diff --git a/src/pylorax/insttree.py b/src/pylorax/insttree.py
deleted file mode 100644
index 1ca9ba45..00000000
--- a/src/pylorax/insttree.py
+++ /dev/null
@@ -1,551 +0,0 @@
-#
-# instroot.py
-# install root class
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import os
-import glob
-import fnmatch
-import shutil
-import re
-
-from utils.fileutils import copy, move, remove, replace, touch
-
-import actions
-import actions.base
-from template import Template
-
-
-class InstallTree(object):
-
- def __init__(self, config, yum, output):
- self.conf = config
- self.yum = yum
-
- self.so, self.se = output
-
- def get_packages(self):
- required = ["anaconda", "anaconda-runtime", "/etc/gtk-2.0/gtkrc"]
-
- # kernel packages
- required.extend(["kernel", "*firmware*"])
-
- # add the XEN kernel package
- if self.conf.buildarch == "i386":
- required.append("kernel-PAE")
-
- # add the jensen kernel package
- if self.conf.buildarch == "alpha":
- required.append("kernel-jensen")
-
- # get additional packages from the configuration files
- packages_files = []
- packages_files.append(os.path.join(self.conf.confdir, "packages",
- "packages.all")),
- packages_files.append(os.path.join(self.conf.confdir, "packages",
- "packages.%s" % (self.conf.buildarch,)))
-
- packages = set()
- for file in packages_files:
- if os.path.isfile(file):
- try:
- f = open(file, "r")
- except IOError as why:
- self.se.error("Unable to read packages configuration:"
- " %s" % (why,))
- else:
- for line in f.readlines():
- line, sep, comment = line.partition("#")
- line = line.strip()
-
- if not line:
- continue
-
- if line.startswith("-"):
- packages.discard(line[1:])
- else:
- packages.add(line)
-
- f.close()
-
- required.extend(list(packages))
-
- # logos
- required.extend(["%s-logos" % (self.conf.product.lower(),),
- "%s-release" % (self.conf.product.lower(),)])
-
- return required
-
- def add_packages(self, packages):
- for package in packages:
- ok = self.yum.add_package(package)
- if not ok:
- self.se.warning("No package '%s' available" (package,))
-
- def install_packages(self):
- # XXX why do we need this?
- os.symlink(os.path.join("/", "tmp"),
- os.path.join(self.conf.treedir, "var", "lib", "xkb"))
-
- self.yum.install()
-
- def copy_updates(self):
- if self.conf.updates and os.path.isdir(self.conf.updates):
- copy(src_root=self.conf.updates, src_path="*",
- dst_root=self.conf.treedir, dst_path="")
-
- self.conf.delAttr("updates")
-
- def fix_udev_links(self):
- # these links are broken by default (at least on i386)
- for filename in ("udevcontrol", "udevsettle", "udevtrigger"):
- filename = os.path.join(self.conf.treedir, "sbin", filename)
- if os.path.islink(filename):
- os.unlink(filename)
- os.symlink("udevadm", filename)
-
- def remove_modules_broken_links(self):
- # remove build and source links from modules directories
- build = os.path.join(self.conf.treedir, "lib", "modules", "*", "build")
- build_files = glob.glob(build)
-
- source = os.path.join(self.conf.treedir, "lib", "modules", "*", "source")
- source_files = glob.glob(source)
-
- [os.unlink(filename) for filename in build_files + source_files
- if os.path.islink(filename)]
-
- def get_kernelfiles(self):
- kerneldir = os.path.join(self.conf.treedir, "boot")
-
- if self.conf.buildarch == "ia64":
- kerneldir = os.path.join(kerneldir, "efi", "EFI", "redhat")
-
- return glob.glob(os.path.join(kerneldir, "vmlinuz-*"))
-
- def run(self):
- self.so.info("Getting the list of packages")
- packages = self.get_packages()
-
- self.so.info("Running yum")
- self.add_packages(packages)
- self.install_packages()
-
- self.so.info("Copying the updates")
- self.copy_updates()
-
- self.so.info("Fixing udev links")
- self.fix_udev_links()
-
- self.so.info("Removing build and source links in modules directories")
- self.remove_modules_broken_links()
-
- return self.get_kernelfiles()
-
-
- ####################
- ### tree scrubs
-
- def copy_stubs(self):
- for file in ("raidstart", "raidstop", "losetup", "list-harddrives",
- "loadkeys", "mknod", "syslogd"):
-
- src = os.path.join(self.conf.treedir, "usr", "lib", "anaconda",
- "%s-stub" % (file,))
- dst = os.path.join(self.conf.treedir, "usr", "bin", file)
-
- shutil.copy2(src, dst)
-
- def create_dogtail_conf(self):
- dogtailconf = os.path.join(self.conf.datadir, "dogtail", "%gconf.xml")
-
- if os.path.isfile(dogtailconf):
- dst = os.path.join(self.conf.treedir, ".gconf", "desktop", "gnome",
- "interface")
-
- os.makedirs(dst)
- shutil.copy2(dogtailconf, dst)
-
- touch(os.path.join(self.conf.treedir, ".gconf", "desktop",
- "%gconf.xml"))
- touch(os.path.join(self.conf.treedir, ".gconf", "desktop", "gnome",
- "%gconf.xml"))
-
- def create_libuser_conf(self):
- src = os.path.join(self.conf.datadir, "libuser", "libuser.conf")
- dst = os.path.join(self.conf.treedir, "etc", "libuser.conf")
- shutil.copy2(src, dst)
-
- def create_selinux_conf(self):
- if os.path.exists(os.path.join(self.conf.treedir, "etc", "selinux",
- "targeted")):
-
- src = os.path.join(self.conf.datadir, "selinux", "config")
- dst = os.path.join(self.conf.treedir, "etc", "selinux", "config")
- shutil.copy2(src, dst)
-
- def configure_fedorakmod(self):
- fedorakmodconf = os.path.join(self.conf.treedir, "etc", "yum",
- "pluginconf.d", "fedorakmod.conf")
-
- replace(fedorakmodconf, r"\(installforallkernels\) = 0", r"\1 = 1")
-
- def copy_bootloaders(self):
- bootpath = os.path.join(self.conf.treedir, "usr", "lib",
- "anaconda-runtime", "boot")
-
- if not os.path.isdir(bootpath):
- os.makedirs(bootpath)
-
- if self.conf.buildarch in ("i386", "i586", "x86_64"):
- for file in os.listdir(os.path.join(self.conf.treedir, "boot")):
- if file.startswith("memtest"):
- src = os.path.join(self.conf.treedir, "boot", file)
- dst = os.path.join(bootpath, file)
- shutil.copy2(src, dst)
- elif self.conf.buildarch == "sparc":
- for file in os.listdir(os.path.join(self.conf.treedir, "boot")):
- if file.endswith(".b"):
- src = os.path.join(self.conf.treedir, "boot", file)
- dst = os.path.join(bootpath, file)
- shutil.copy2(src, dst)
- elif self.conf.buildarch in ("ppc", "ppc64"):
- src = os.path.join(self.conf.treedir, "boot", "efika.forth")
- shutil.copy2(src, bootpath)
- elif self.conf.buildarch == "alpha":
- src = os.path.join(self.conf.treedir, "boot", "bootlx")
- shutil.copy2(src, bootpath)
- elif self.conf.buildarch == "ia64":
- srcdir = os.path.join(self.conf.treedir, "boot", "efi", "EFI", "redhat")
- copy(src_root=srcdir, src_path="*",
- dst_root=bootpath, dst_dir="")
-
- def move_repos(self):
- src = os.path.join(self.conf.treedir, "etc", "yum.repos.d")
- dst = os.path.join(self.conf.treedir, "etc", "anaconda.repos.d")
- shutil.move(src, dst)
-
- def move_anaconda_files(self):
- # move anaconda executable
- src = os.path.join(self.conf.treedir, "usr", "sbin", "anaconda")
- dst = os.path.join(self.conf.treedir, "usr", "bin", "anaconda")
- shutil.move(src, dst)
-
- # move anaconda libraries
- srcdir = os.path.join(self.conf.treedir, "usr", "lib", "anaconda-runtime")
- dst = os.path.join(self.conf.treedir, "usr", self.conf.libdir)
- move(src_root=srcdir, src_path="lib*",
- dst_root=dst, dst_path="")
-
- def create_debug_directories(self):
- os.makedirs(os.path.join(self.conf.treedir, "usr", "lib", "debug"))
- os.makedirs(os.path.join(self.conf.treedir, "usr", "src", "debug"))
-
- def create_modules_symlinks(self):
- os.makedirs(os.path.join(self.conf.treedir, "modules"))
- os.makedirs(os.path.join(self.conf.treedir, "firmware"))
-
- # XXX are we sure we want to do this?
- remove(os.path.join(self.conf.treedir, "lib", "modules"))
- remove(os.path.join(self.conf.treedir, "lib", "firmware"))
- os.symlink("/modules", os.path.join(self.conf.treedir, "lib", "modules"))
- os.symlink("/firmware", os.path.join(self.conf.treedir, "lib", "firmware"))
-
- def fix_joe_links(self):
- joedir = os.path.join(self.conf.treedir, "etc", "joe")
-
- if os.path.isdir(joedir):
- os.symlink("jpicorc", os.path.join(joedir, "picorc"))
- os.symlink("jpicorc", os.path.join(joedir, "jnanorc"))
- os.symlink("jpicorc", os.path.join(joedir, "nanorc"))
- os.symlink("jmacsrc", os.path.join(joedir, "emacsrc"))
- os.symlink("jmacs", os.path.join(self.conf.treedir, "usr", "bin",
- "emacs"))
- os.symlink("jpico", os.path.join(self.conf.treedir, "usr", "bin",
- "pico"))
- os.symlink("jpico", os.path.join(self.conf.treedir, "usr", "bin",
- "nano"))
-
- def fix_man_pages(self):
- # fix up some links for man page related stuff
- for file in ["nroff", "groff", "iconv", "geqn", "gtbl", "gpic", "grefer"]:
- src = os.path.join("mnt", "sysimage", "usr", "bin", file)
- dst = os.path.join(self.conf.treedir, "usr", "bin", file)
- if not os.path.isfile(dst):
- os.symlink(src, dst)
-
- # fix /etc/man.config to point into /mnt/sysimage
- manconfig = os.path.join(self.conf.treedir, "etc", "man.config")
-
- # don't change MANPATH_MAP lines now
- replace(manconfig, r"^MANPATH[^_MAP][ \t]*", r"&/mnt/sysimage")
- # change MANPATH_MAP lines now
- replace(manconfig, r"^MANPATH_MAP[ \t]*[a-zA-Z0-9/]*[ \t]*",
- r"&/mnt/sysimage")
-
- def remove_gtk_stuff(self):
- # figure out the gtk+ theme to keep
- gtkrc = os.path.join(self.conf.treedir, "etc", "gtk-2.0", "gtkrc")
-
- gtk_theme_name = None
- gtk_engine = None
- gtk_icon_themes = []
-
- if os.path.isfile(gtkrc):
- f = open(gtkrc, "r")
- lines = f.readlines()
- f.close()
-
- for line in lines:
- line = line.strip()
- if line.startswith("gtk-theme-name"):
- gtk_theme_name = line[line.find("=") + 1:]
- gtk_theme_name = gtk_theme_name.replace('"', "").strip()
-
- # find the engine for this theme
- gtkrc = os.path.join(self.conf.treedir, "usr", "share",
- "themes", gtk_theme_name, "gtk-2.0", "gtkrc")
- if os.path.isfile(gtkrc):
- f = open(gtkrc, "r")
- engine_lines = f.readlines()
- f.close()
-
- for engine_line in engine_lines:
- engine_line = engine_line.strip()
- if engine_line.find("engine") != -1:
- gtk_engine = engine_line[engine_line.find('"') + 1:]
- gtk_engine = gtk_engine.replace('"', "").strip()
- break
-
- elif line.startswith("gtk-icon-theme-name"):
- icon_theme = line[line.find("=") + 1:]
- icon_theme = icon_theme.replace('"', "").strip()
- gtk_icon_themes.append(icon_theme)
-
- # bring in all inherited themes
- while True:
- icon_theme_index = os.path.join(self.conf.treedir, "usr",
- "share", "icons", icon_theme, "index.theme")
- if os.path.isfile(icon_theme_index):
- inherits = False
- f = open(icon_theme_index, "r")
- icon_lines = f.readlines()
- f.close()
-
- for icon_line in icon_lines:
- icon_line = icon_line.strip()
- if icon_line.startswith("Inherits="):
- inherits = True
- icon_theme = icon_line[icon_line.find("=") + 1:]
- icon_theme = icon_theme.replace('"', "").strip()
- gtk_icon_themes.append(icon_theme)
- break
-
- if not inherits:
- break
- else:
- break
-
- # remove themes we don't need
- theme_path = os.path.join(self.conf.treedir, "usr", "share", "themes")
- if os.path.isdir(theme_path):
- for theme in filter(lambda theme: theme != gtk_theme_name,
- os.listdir(theme_path)):
-
- theme = os.path.join(theme_path, theme)
- shutil.rmtree(theme, ignore_errors=True)
-
- # remove icons we don't need
- icon_path = os.path.join(self.conf.treedir, "usr", "share", "icons")
- if os.path.isdir(icon_path):
- for icon in filter(lambda icon: icon not in gtk_icon_themes,
- os.listdir(icon_path)):
-
- icon = os.path.join(icon_path, icon)
- shutil.rmtree(icon, ignore_errors=True)
-
- # remove engines we don't need
- tmp_path = os.path.join(self.conf.treedir, "usr", self.conf.libdir,
- "gtk-2.0")
- if os.path.isdir(tmp_path):
- fnames = map(lambda fname: os.path.join(tmp_path, fname, "engines"),
- os.listdir(tmp_path))
- dnames = filter(lambda fname: os.path.isdir(fname), fnames)
- for dir in dnames:
- engines = filter(lambda engine: engine.find(gtk_engine) == -1,
- os.listdir(dir))
- for engine in engines:
- engine = os.path.join(dir, engine)
- os.unlink(engine)
-
- def remove_locales(self):
- langtable = os.path.join(self.conf.treedir, "usr", "lib", "anaconda",
- "lang-table")
- localepath = os.path.join(self.conf.treedir, "usr", "share", "locale")
-
- if os.path.isfile(langtable):
- locales = set()
- all_locales = set()
-
- f = open(langtable, "r")
- lines = f.readlines()
- f.close()
-
- for line in lines:
- line = line.strip()
- if not line or line.startswith("#"):
- continue
-
- fields = line.split("\t")
-
- if os.path.isdir(os.path.join(localepath, fields[1])):
- locales.add(fields[1])
-
- locale = fields[3].split(".")[0]
- if os.path.isdir(os.path.join(localepath, locale)):
- locales.add(locale)
-
- for locale in os.listdir(localepath):
- all_locales.add(locale)
-
- locales_to_remove = list(all_locales.difference(locales))
- for locale in locales_to_remove:
- rmpath = os.path.join(localepath, locale)
- shutil.rmtree(rmpath, ignore_errors=True)
-
- def remove_unnecessary_files(self):
- to_remove = set()
-
- for root, dirs, files in os.walk(self.conf.treedir):
- for file in files:
- path = os.path.join(root, file)
-
- if fnmatch.fnmatch(path, "*.a"):
- if path.find("kernel-wrapper/wrapper.a") == -1:
- to_remove.add(path)
- elif fnmatch.fnmatch(path, "lib*.la"):
- if path.find("usr/" + self.conf.libdir + "/gtk-2.0") == -1:
- to_remove.add(path)
- elif fnmatch.fnmatch(path, "*.py"):
- to_remove.add(path + "o")
-
- try:
- os.unlink(path + "c")
- except OSError:
- pass
-
- os.symlink("/dev/null", path + "c")
-
- for file in to_remove:
- try:
- os.unlink(file)
- except OSError:
- pass
-
- # remove libunicode-lite
- remove(os.path.join(self.conf.treedir, "usr", self.conf.libdir,
- "libunicode-lite*"))
-
- def remove_python_stuff(self):
- for fname in ["bsddb", "compiler", "curses", "distutils", "email",
- "encodings", "hotshot", "idlelib", "test",
- "doctest.py", "pydoc.py"]:
-
- remove(os.path.join(self.conf.treedir, "usr", self.conf.libdir,
- "python?.?", fname))
-
- def move_bins(self):
- # move bin to usr/bin
- move(src_root=self.conf.treedir,
- src_path=os.path.join("bin", "*"),
- dst_root=self.conf.treedir,
- dst_path=os.path.join("usr", "bin"))
- remove(os.path.join(self.conf.treedir, "bin"))
-
- # move sbin to /usr/sbin
- copy(src_root=self.conf.treedir,
- src_path=os.path.join("sbin", "*"),
- dst_root=self.conf.treedir,
- dst_path=os.path.join("usr", "sbin"))
- remove(os.path.join(self.conf.treedir, "sbin"))
-
- # fix broken links
- brokenlinks = []
- for dir in ("bin", "sbin"):
- dir = os.path.join(self.conf.treedir, "usr", dir)
- for root, dnames, fnames in os.walk(dir):
- for fname in fnames:
- fname = os.path.join(root, fname)
- if os.path.islink(fname) and not os.path.exists(fname):
- brokenlinks.append(fname)
-
- for link in brokenlinks:
- target = os.readlink(link)
- newtarget = re.sub(r"^\.\./\.\./(bin|sbin)/(.*)$", "../\g<1>/\g<2>",
- target)
-
- if newtarget != target:
- os.unlink(link)
- os.symlink(newtarget, link)
-
- def process_scrubs_from_template(self):
- # get supported actions
- supported_actions = actions.getActions(verbose=self.conf.debug)
-
- # variables supported in templates
- vars = { "instroot": self.conf.treedir }
-
- # parse the template file
- scrubs = os.path.join(self.conf.confdir, "tree",
- "scrubs.%s" % (self.conf.buildarch,))
-
- if os.path.exists(scrubs):
- self.template = Template()
- self.template.preparse(scrubs)
- self.template.parse(supported_actions, vars)
-
- for action in self.template.actions:
- action.execute()
-
- def scrub(self):
- self.copy_stubs()
- self.create_dogtail_conf()
- self.create_libuser_conf()
- self.create_selinux_conf()
- self.configure_fedorakmod()
-
- self.copy_bootloaders()
- self.move_repos()
- self.move_anaconda_files()
-
- self.create_debug_directories()
- self.create_modules_symlinks()
-
- self.fix_joe_links()
- self.fix_man_pages()
-
- self.remove_gtk_stuff()
- self.remove_locales()
- self.remove_unnecessary_files()
- self.remove_python_stuff()
-
- self.move_bins()
-
- self.process_scrubs_from_template()
diff --git a/src/pylorax/launcher.py b/src/pylorax/launcher.py
new file mode 100644
index 00000000..5e00bbb4
--- /dev/null
+++ b/src/pylorax/launcher.py
@@ -0,0 +1,205 @@
+#
+# launcher.py
+#
+
+from __future__ import print_function
+
+import sys
+import os
+from optparse import OptionParser, OptionGroup
+import tempfile
+import shutil
+import ConfigParser
+
+import yum
+
+import pylorax
+
+
+def main(args):
+ version = "%s %s" % (os.path.basename(args[0]), pylorax.__VERSION__)
+ usage = "%prog -p PRODUCT -v VERSION -r RELEASE -o OUTPUTDIR REPOSITORY"
+
+ parser = OptionParser(usage=usage)
+
+ # required arguments for image creation
+ required = OptionGroup(parser, "required arguments")
+ required.add_option("-p", "--product", help="product name",
+ metavar="STRING")
+ required.add_option("-v", "--version", help="version identifier",
+ metavar="STRING")
+ required.add_option("-r", "--release", help="release information",
+ metavar="STRING")
+ required.add_option("-o", "--outputdir", help="output directory",
+ metavar="PATHSPEC")
+
+ # optional arguments
+ optional = OptionGroup(parser, "optional arguments")
+ optional.add_option("-m", "--mirrorlist",
+ help="mirrorlist repository (may be listed multiple times)",
+ metavar="REPOSITORY", action="append", default=[])
+ optional.add_option("-t", "--variant",
+ help="variant name", metavar="STRING")
+ optional.add_option("-b", "--bugurl",
+ help="bug reporting URL for the product", metavar="URL",
+ default="your distribution provided bug reporting tool")
+ optional.add_option("-u", "--updates",
+ help="directory containing updates", metavar="PATHSPEC")
+
+ # output settings
+ output = OptionGroup(parser, "output settings")
+ output.add_option("--no-colors", help="disable color output",
+ action="store_false", default=True, dest="colors")
+ output.add_option("--encoding", help="set encoding",
+ metavar="STRING", default="utf-8")
+ output.add_option("-d", "--debug", help="enable debugging messages",
+ action="store_true", default=False)
+
+ # lorax settings
+ settings = OptionGroup(parser, "lorax settings")
+ settings.add_option("-c", "--cleanup", help="clean up on exit",
+ action="store_true", default=False)
+
+ # add the option groups to the parser
+ parser.add_option_group(required)
+ parser.add_option_group(optional)
+ parser.add_option_group(output)
+ parser.add_option_group(settings)
+
+ # add the show version option
+ parser.add_option("-V", help="show program's version number and exit",
+ action="store_true", default=False, dest="showver")
+
+ # parse the arguments
+ opts, args = parser.parse_args()
+ repositories = args
+
+ if opts.showver:
+ print(version)
+ sys.exit(0)
+
+ # check for the required arguments
+ if not opts.product or not opts.version or not opts.release \
+ or not opts.outputdir or not repositories:
+ parser.error("missing one or more required arguments")
+
+ # create the temporary directory for lorax
+ tempdir = tempfile.mkdtemp(prefix="lorax.", dir=tempfile.gettempdir())
+
+ # create the yumbase object
+ installtree = os.path.join(tempdir, "installtree")
+ os.mkdir(installtree)
+
+ yumtempdir = os.path.join(tempdir, "yum")
+ os.mkdir(yumtempdir)
+
+ yumconf = create_yumconf(repositories, opts.mirrorlist, yumtempdir)
+ yb = create_yumbase_object(yumconf, installtree)
+
+ if yb is None:
+ print("error: unable to create the yumbase object", file=sys.stderr)
+ shutil.rmtree(tempdir)
+ sys.exit(1)
+
+ # run lorax
+ params = { "product" : opts.product,
+ "version" : opts.version,
+ "release" : opts.release,
+ "outputdir" : opts.outputdir,
+ "tempdir" : tempdir,
+ "installtree" : installtree,
+ "colors" : opts.colors,
+ "encoding" : opts.encoding,
+ "debug" : opts.debug,
+ "cleanup" : opts.cleanup,
+ "variant" : opts.variant,
+ "bugurl" : opts.bugurl,
+ "updates" : opts.updates }
+
+ lorax = pylorax.Lorax(yb, **params)
+ lorax.run()
+
+
+def create_yumconf(repositories, mirrorlists=[], tempdir="/tmp/yum"):
+
+ def sanitize_repo(repo):
+ if repo.startswith("/"):
+ return "file://%s" % repo
+ elif repo.startswith("http://") or repo.startswith("ftp://"):
+ return repo
+ else:
+ return None
+
+ # sanitize the repositories
+ repositories = map(sanitize_repo, repositories)
+
+ # remove invalid repositories
+ repositories = filter(bool, repositories)
+
+ cachedir = os.path.join(tempdir, "cache")
+ if not os.path.isdir(cachedir):
+ os.mkdir(cachedir)
+
+ yumconf = os.path.join(tempdir, "yum.conf")
+ c = ConfigParser.ConfigParser()
+
+ # add the main section
+ section = "main"
+ data = { "cachedir" : cachedir,
+ "keepcache" : 0,
+ "gpgcheck" : 0,
+ "plugins" : 0,
+ "reposdir" : "",
+ "tsflags" : "nodocs" }
+
+ c.add_section(section)
+ map(lambda (key, value): c.set(section, key, value), data.items())
+
+ # add the main repository - the first repository from list
+ section = "lorax-repo"
+ data = { "name" : "lorax repo",
+ "baseurl" : repositories[0],
+ "enabled" : 1 }
+
+ c.add_section(section)
+ map(lambda (key, value): c.set(section, key, value), data.items())
+
+ # add the extra repositories
+ for n, extra in enumerate(repositories[1:], start=1):
+ section = "lorax-extra-repo-%d" % n
+ data = { "name" : "lorax extra repo %d" % n,
+ "baseurl" : extra,
+ "enabled" : 1 }
+
+ c.add_section(section)
+ map(lambda (key, value): c.set(section, key, value), data.items())
+
+ # add the mirrorlists
+ for n, mirror in enumerate(mirrorlists, start=1):
+ section = "lorax-mirrorlist-%d" % n
+ data = { "name" : "lorax mirrorlist %d" % n,
+ "mirrorlist" : mirror,
+ "enabled" : 1 }
+
+ c.add_section(section)
+ map(lambda (key, value): c.set(section, key, value), data.items())
+
+ # write the yumconf file
+ with open(yumconf, "w") as f:
+ c.write(f)
+
+ return yumconf
+
+
+def create_yumbase_object(yumconf, installroot="/"):
+ yb = yum.YumBase()
+
+ yb.preconf.fn = yumconf
+ yb.preconf.root = installroot
+ yb._getConfig()
+
+ yb._getRpmDB()
+ yb._getRepos()
+ yb._getSacks()
+
+ return yb
diff --git a/src/pylorax/lcs/__init__.py b/src/pylorax/lcs/__init__.py
new file mode 100644
index 00000000..7388121a
--- /dev/null
+++ b/src/pylorax/lcs/__init__.py
@@ -0,0 +1,58 @@
+#
+# __init__.py
+#
+
+import sys
+import os
+import re
+
+from mako.template import Template as MakoTemplate
+from mako.lookup import TemplateLookup as MakoTemplateLookup
+
+import actions
+
+
+class TemplateParserError(Exception):
+ pass
+
+
+class TemplateParser(object):
+
+ def __init__(self, variables):
+ self.variables = variables
+ self.actions_map = actions.get_map()
+
+ def get_actions(self, file):
+ template_actions = []
+
+ # we have to set the template lookup directories to ["/"],
+ # otherwise the relative and absolute includes don't work properly
+ lookup = MakoTemplateLookup(directories=["/"])
+ template = MakoTemplate(filename=file, lookup=lookup)
+ s = template.render(**self.variables)
+
+ # concatenate lines ending with "\"
+ #s = re.sub(r"\s*\\\s*\n", " ", s)
+
+ for lineno, line in enumerate(s.splitlines(), start=1):
+ # remove multiple whitespaces
+ line = re.sub(r"\s+", " ", line.strip())
+ if not line:
+ continue
+
+ # get the command
+ command, line = line.split(None, 1)
+ if command not in self.actions_map:
+ raise TemplateParserError("%s: %d: invalid command" % \
+ (file, lineno))
+
+ # create the action object
+ m = re.match(self.actions_map[command].REGEX, line)
+ if m:
+ new_action = self.actions_map[command](**m.groupdict())
+ template_actions.append(new_action)
+ else:
+ raise TemplateParserError("%s: %d: invalid command format" % \
+ (file, lineno))
+
+ return template_actions
diff --git a/src/pylorax/lcs/actions/__init__.py b/src/pylorax/lcs/actions/__init__.py
new file mode 100644
index 00000000..1958643e
--- /dev/null
+++ b/src/pylorax/lcs/actions/__init__.py
@@ -0,0 +1,31 @@
+#
+# __init__.py
+#
+
+import sys
+import os
+
+
+def get_map():
+ actions = {}
+
+ root, actions_dir = os.path.split(os.path.dirname(__file__))
+
+ sys.path.insert(0, root)
+
+ modules = set()
+ for filename in os.listdir(os.path.join(root, actions_dir)):
+ if filename.endswith(".py") and not filename == "__init__.py":
+ basename, extension = os.path.splitext(filename)
+ modules.add(os.path.join(actions_dir, basename).replace("/", "."))
+
+ for module in modules:
+ imported = __import__(module, globals(), locals(), [module], -1)
+
+ commands = getattr(imported, "COMMANDS", {})
+ for command, classname in commands.items():
+ actions[command] = getattr(imported, classname)
+
+ sys.path.pop(0)
+
+ return actions
diff --git a/src/pylorax/lcs/actions/base.py b/src/pylorax/lcs/actions/base.py
new file mode 100644
index 00000000..f90a6751
--- /dev/null
+++ b/src/pylorax/lcs/actions/base.py
@@ -0,0 +1,37 @@
+#
+# base.py
+#
+
+class LCSAction(object):
+ """LCS Action base class.
+
+ To create your own custom action, subclass this class, and override
+ the methods you need.
+
+ A valid action has to have a REGEX class variable, which specifies
+ the format of the action command, so the needed parameters can be
+ properly extracted, and an execute() method, where all the work
+ should be done. This medhod will be called by Lorax.
+
+ Don't forget to include a command : action map for your new action
+ in the COMMANDS dictionary in the beginning of your file.
+ Action classes which are not in the COMMANDS dictionary will not
+ be loaded by Lorax.
+
+ """
+
+ # regular expression for extracting the parameters from the command
+ REGEX = r""
+
+ def __init__(self):
+ if self.__class__ is LCSAction:
+ raise TypeError("LCSAction is an abstract class, " \
+ "cannot be used this way")
+
+ self._attrs = {}
+
+ def __str__(self):
+ return "%s: %s" % (self.__class__.__name__, self._attrs)
+
+ def execute(self):
+ raise NotImplementedError("execute() method not implemented")
diff --git a/src/pylorax/lcs/actions/file.py b/src/pylorax/lcs/actions/file.py
new file mode 100644
index 00000000..c0591796
--- /dev/null
+++ b/src/pylorax/lcs/actions/file.py
@@ -0,0 +1,282 @@
+#
+# file.py
+#
+
+import os
+
+from base import LCSAction
+import pylorax.utils as utils
+
+
+COMMANDS = { "remove" : "Remove",
+ "copy" : "Copy",
+ "symlink" : "SymLink",
+ "touch" : "Touch",
+ "mkdir" : "MkDir",
+ "makedirs" : "MakeDirs",
+ "chown" : "Chown",
+ "chmod" : "Chmod",
+ "edit" : "Edit",
+ "replace" : "Replace" }
+
+
+class Remove(LCSAction):
+
+ REGEX = r"^(?P.*?)$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["filename"] = kwargs.get("filename")
+
+ def execute(self):
+ utils.remove(self.filename)
+
+ @property
+ def filename(self):
+ return self._attrs["filename"]
+
+
+# TODO add the ignore_errors flag
+class Copy(LCSAction):
+
+ REGEX = r"^(?P.*?)\s(?P.*?)\sto\s" \
+ "(?P.*?)\s(?P.*?)" \
+ "(\s(?Pnosymlinks))?$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["src_root"] = kwargs.get("src_root")
+ self._attrs["src_path"] = kwargs.get("src_path")
+ self._attrs["dst_root"] = kwargs.get("dst_root")
+ self._attrs["dst_path"] = kwargs.get("dst_path")
+
+ nosymlinks = kwargs.get("nosymlinks")
+ if nosymlinks is not None:
+ self._attrs["symlinks"] = False
+ else:
+ self._attrs["symlinks"] = True
+
+ def execute(self):
+ utils.dcopy(src_root=self.src_root, src_path=self.src_path,
+ dst_root=self.dst_root, dst_path=self.dst_path,
+ symlinks=self.symlinks)
+
+ @property
+ def src(self):
+ path = os.path.join(self._attrs["src_root"], self._attrs["src_path"])
+ return os.path.normpath(path)
+
+ @property
+ def src_root(self):
+ return self._attrs["src_root"]
+
+ @property
+ def src_path(self):
+ return self._attrs["src_path"]
+
+ @property
+ def dst(self):
+ path = os.path.join(self._attrs["dst_root"], self._attrs["dst_path"])
+ return os.path.normpath(path)
+
+ @property
+ def dst_root(self):
+ return self._attrs["dst_root"]
+
+ @property
+ def dst_path(self):
+ return self._attrs["dst_path"]
+
+ @property
+ def symlinks(self):
+ return self._attrs["symlinks"]
+
+
+class SymLink(LCSAction):
+
+ REGEX = r"^name\s(?P.*?)\starget\s(?P.*?)$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["name"] = kwargs.get("name")
+ self._attrs["target"] = kwargs.get("target")
+
+ def execute(self):
+ utils.symlink(link_name=self.name, link_target=self.target)
+
+ @property
+ def name(self):
+ return self._attrs["name"]
+
+ @property
+ def target(self):
+ return self._attrs["target"]
+
+
+class Touch(LCSAction):
+
+ REGEX = r"^(?P.*?)$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["filename"] = kwargs.get("filename")
+
+ def execute(self):
+ utils.touch(self.filename)
+
+ @property
+ def filename(self):
+ return self._attrs["filename"]
+
+
+class MkDir(LCSAction):
+
+ REGEX = r"^(?P.*?)(\smode\s(?P.*?))?$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["dir"] = kwargs.get("dir")
+
+ mode = kwargs.get("mode")
+ if mode is not None:
+ self._attrs["mode"] = int(mode, 8)
+ else:
+ self._attrs["mode"] = None
+
+ def execute(self):
+ utils.mkdir(self.dir, self.mode)
+
+ @property
+ def dir(self):
+ return self._attrs["dir"]
+
+ @property
+ def mode(self):
+ return self._attrs["mode"]
+
+
+class MakeDirs(MkDir):
+
+ def __init__(self, **kwargs):
+ MkDir.__init__(self, **kwargs)
+
+ def execute(self):
+ utils.makedirs(self.dir, self.mode)
+
+
+class Chown(LCSAction):
+
+ REGEX = r"^(?P.*?)\suser\s(?P.*?)" \
+ "\sgroup\s(?P.*?)(\s(?Precursive))?$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["filename"] = kwargs.get("filename")
+ self._attrs["user"] = kwargs.get("user")
+ self._attrs["group"] = kwargs.get("group")
+
+ recursive = kwargs.get("recursive")
+ if recursive is not None:
+ self._attrs["recursive"] = True
+ else:
+ self._attrs["recursive"] = False
+
+ def execute(self):
+ utils.chown(self.filename, self.user, self.group, self.recursive)
+
+ @property
+ def filename(self):
+ return self._attrs["filename"]
+
+ @property
+ def user(self):
+ return self._attrs["user"]
+
+ @property
+ def group(self):
+ return self._attrs["group"]
+
+ @property
+ def recursive(self):
+ return self._attrs["recursive"]
+
+
+class Chmod(LCSAction):
+
+ REGEX = r"^(?P.*?)\smode\s(?P[0-7]*?)" \
+ "(\s(?Precursive))?$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["filename"] = kwargs.get("filename")
+ self._attrs["mode"] = int(kwargs.get("mode"), 8)
+
+ recursive = kwargs.get("recursive")
+ if recursive is not None:
+ self._attrs["recursive"] = True
+ else:
+ self._attrs["recursive"] = False
+
+ def execute(self):
+ utils.chmod(self.filename, self.mode, self.recursive)
+
+ @property
+ def filename(self):
+ return self._attrs["filename"]
+
+ @property
+ def mode(self):
+ return self._attrs["mode"]
+
+ @property
+ def recursive(self):
+ return self._attrs["recursive"]
+
+
+class Edit(Touch):
+
+ REGEX = r'^(?P.*?)\stext\s"(?P.*?)"' \
+ '(\s(?Pappend))?$'
+
+ def __init__(self, **kwargs):
+ Touch.__init__(self, **kwargs)
+ self._attrs["text"] = kwargs.get("text")
+
+ append = kwargs.get("append")
+ if append is not None:
+ self._attrs["append"] = True
+ else:
+ self._attrs["append"] = False
+
+ def execute(self):
+ utils.edit(self.filename, self.text, self.append)
+
+ @property
+ def text(self):
+ return self._attrs["text"]
+
+ @property
+ def append(self):
+ return self._attrs["append"]
+
+
+class Replace(Touch):
+
+ REGEX = r'^(?P.*?)\sfind\s"(?P.*?)"' \
+ '\sreplace\s"(?P.*?)"$'
+
+ def __init__(self, **kwargs):
+ Touch.__init__(self, **kwargs)
+ self._attrs["find"] = kwargs.get("find")
+ self._attrs["replace"] = kwargs.get("replace")
+
+ def execute(self):
+ utils.replace(self.filename, self.find, self.replace)
+
+ @property
+ def find(self):
+ return self._attrs["find"]
+
+ @property
+ def replace(self):
+ return self._attrs["replace"]
diff --git a/src/pylorax/lcs/actions/ssh.py b/src/pylorax/lcs/actions/ssh.py
new file mode 100644
index 00000000..6e9e617c
--- /dev/null
+++ b/src/pylorax/lcs/actions/ssh.py
@@ -0,0 +1,39 @@
+#
+# ssh.py
+#
+
+import commands
+
+from base import LCSAction
+import pylorax.utils as utils
+
+
+COMMANDS = { "gensshkey" : "GenerateSSHKey" }
+
+
+class GenerateSSHKey(LCSAction):
+
+ REGEX = r"^(?P.*?)\stype\s(?P.*?)$"
+
+ def __init__(self, **kwargs):
+ LCSAction.__init__(self)
+ self._attrs["filename"] = kwargs.get("filename")
+ self._attrs["type"] = kwargs.get("type")
+
+ def execute(self):
+ cmd = "/usr/bin/ssh-keygen -q -t %s -f %s -C '' -N ''" % \
+ (self.type, self.filename)
+
+ err, output = commands.getstatusoutput(cmd)
+
+ if not err:
+ utils.chmod(self.filename, 0600)
+ utils.chmod(self.filename + ".pub", 0644)
+
+ @property
+ def filename(self):
+ return self._attrs["filename"]
+
+ @property
+ def type(self):
+ return self._attrs["type"]
diff --git a/src/pylorax/misc.py b/src/pylorax/misc.py
deleted file mode 100644
index 5a1b4cb4..00000000
--- a/src/pylorax/misc.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# misc.py
-# miscellaneous functions
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import commands
-
-
-def seq(arg):
- if type(arg) not in (type([]), type(())):
- return [arg]
- else:
- return arg
-
-def get_console_size():
- err, output = commands.getstatusoutput("stty size")
- if not err:
- height, width = output.split()
- height, width = int(height), int(width)
- else:
- # set defaults
- height, width = 24, 80
-
- return height, width
diff --git a/src/pylorax/output.py b/src/pylorax/output.py
index 06929d4c..bcd154a0 100644
--- a/src/pylorax/output.py
+++ b/src/pylorax/output.py
@@ -1,35 +1,15 @@
#
# output.py
-# output control
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
#
import sys
+import singleton
-# color codes
+### color codes
C_DEFAULT = "\x1b[39m"
C_RESET = "\x1b[0m"
-C_BOLD = "\x1b[1m"
-C_UNDERLINE = "\x1b[4m"
-
C_BLACK = "\x1b[0;30m"
C_WHITE = "\x1b[1;37m"
C_RED = "\x1b[0;31m"
@@ -39,53 +19,39 @@ C_LIGHTRED = "\x1b[1;31m"
C_LIGHTGREEN = "\x1b[1;32m"
C_LIGHTBLUE = "\x1b[1;34m"
-# font types
+C_BOLD = "\x1b[1m"
+C_UNDERLINE = "\x1b[4m"
+
+### font types
BOLD = 0b01
UNDERLINE = 0b10
+### output levels
+CRITICAL = 50
+ERROR = 40
+WARNING = 30
+INFO = 20
+DEBUG = 10
+NOTSET = 0
-class OutputError(Exception):
- pass
-class Output(object):
+class Terminal(singleton.Singleton):
- def __init__(self, output=sys.stdout, colors=True, encoding="utf-8",
- verbose=False):
+ def __init__(self):
+ self.__colors = True
+ self.__encoding = "utf-8"
+ self.__output_level = INFO
+ self.__indent_level = 0
- self.output = output
- if not hasattr(self.output, "write"):
- raise OutputError, "output does not support write()"
-
- self.is_flushable = hasattr(self.output, "flush")
+ def basic_config(self, colors=None, encoding=None, level=None):
+ if colors is not None:
+ self.__colors = colors
- self.colors = colors
- self.encoding = encoding
- self.verbose = verbose
+ if encoding is not None:
+ self.__encoding = encoding
- self.__indent_level = 0
-
- def write(self, s, color=C_RESET, type=None):
- s = self.format(s, color=color, type=type)
- self.output.write(s)
-
- if self.is_flushable:
- self.output.flush()
-
- def format(self, s, color=C_RESET, type=None):
- s = s.encode(self.encoding)
-
- if self.colors:
- if type is not None and (type & BOLD):
- s = "%s%s" % (C_BOLD, s)
- if type is not None and (type & UNDERLINE):
- s = "%s%s" % (C_UNDERLINE, s)
- s = "%s%s%s" % (color, s, C_RESET)
-
- return s
-
- def writeline(self, s, color=C_RESET, type=None):
- s = "%s%s\n" % (" " * self.__indent_level, s)
- self.write(s, color=color, type=type)
+ if level is not None:
+ self.__output_level = level
def indent(self):
self.__indent_level += 1
@@ -94,31 +60,43 @@ class Output(object):
if self.__indent_level > 0:
self.__indent_level -= 1
- def newline(self):
- self.output.write("\n")
+ def write(self, s, color=C_RESET, type=None, file=sys.stdout):
+ s = self.format(s, color=color, type=type)
+ file.write(s)
+ file.flush()
- def banner(self, s):
- self.writeline(s, color=C_GREEN, type=BOLD)
+ def format(self, s, color=C_RESET, type=None):
+ s = s.encode(self.__encoding)
- def header(self, s):
- self.writeline(s, type=BOLD)
+ if self.__colors:
+ if type is not None and (type & BOLD):
+ s = "%s%s" % (C_BOLD, s)
+ if type is not None and (type & UNDERLINE):
+ s = "%s%s" % (C_UNDERLINE, s)
+ s = "%s%s%s" % (color, s, C_RESET)
- def info(self, s):
- self.writeline(s)
+ return s
- def error(self, s):
- self.writeline(s, color=C_RED, type=BOLD)
+ def writeline(self, s, color=C_RESET, type=None, file=sys.stdout):
+ s = "%s%s" % (" " * self.__indent_level, s)
+ self.write(s + "\n", color=color, type=type, file=file)
- def warning(self, s):
- self.writeline(s, color=C_RED)
+ def critical(self, s, file=sys.stdout):
+ if self.__output_level <= CRITICAL:
+ self.writeline("** critical: %s" % s, file=file)
- def debug(self, s):
- if self.verbose:
- self.writeline(s)
+ def error(self, s, file=sys.stdout):
+ if self.__output_level <= ERROR:
+ self.writeline("** error: %s" % s, file=file)
+ def warning(self, s, file=sys.stdout):
+ if self.__output_level <= WARNING:
+ self.writeline("** warning: %s" % s, file=file)
-def initialize(verbose=False):
- stdout = Output(output=sys.stdout, verbose=verbose)
- stderr = Output(output=sys.stderr, verbose=verbose)
-
- return stdout, stderr
+ def info(self, s, file=sys.stdout):
+ if self.__output_level <= INFO:
+ self.writeline(s, file=file)
+
+ def debug(self, s, file=sys.stdout):
+ if self.__output_level <= DEBUG:
+ self.writeline(s, file=file)
diff --git a/src/pylorax/ramdisk.py b/src/pylorax/ramdisk.py
new file mode 100644
index 00000000..d86e7f89
--- /dev/null
+++ b/src/pylorax/ramdisk.py
@@ -0,0 +1,435 @@
+#
+# ramdisk.py
+#
+
+import sys
+import os
+import glob
+import shutil
+import commands
+import re
+import gzip
+
+import config
+import output
+import lcs
+import utils
+
+
+class Ramdisk(object):
+
+ def __init__(self):
+ # get the config, paths and output objects
+ self.conf = config.LoraxConfig.get()
+ self.paths = config.LoraxPaths.get()
+ self.output = output.Terminal.get()
+
+ self.actions = self.get_actions_from_template()
+
+ def get_actions_from_template(self):
+ variables = { "instroot" : self.conf.installtree,
+ "initrd" : self.conf.ramdisktree,
+ "libdir" : self.conf.libdir,
+ "arch" : self.conf.arch,
+ "basearch" : self.conf.basearch,
+ "confdir" : self.conf.confdir,
+ "datadir" : self.conf.datadir }
+
+ if self.conf.initrd_template is not None:
+ template = lcs.TemplateParser(variables)
+ return template.get_actions(self.conf.initrd_template)
+
+ return []
+
+ # XXX we have to do this, otherwise we get an error, when copying
+ def remove_modules_broken_links(self):
+ # remove build and source links from modules directories
+ build = os.path.join(self.paths.MODULES_DIR, "build")
+ if os.path.islink(build):
+ utils.remove(build)
+
+ source = os.path.join(self.paths.MODULES_DIR, "source")
+ if os.path.islink(source):
+ utils.remove(source)
+
+ def move_shared_files(self):
+ dirs = [os.path.join(self.paths.INITRD_DATADIR, "noarch"),
+ os.path.join(self.paths.INITRD_DATADIR, self.conf.arch)]
+
+ self.output.info(":: copying the custom initrd files")
+ for dir in [dir for dir in dirs if os.path.isdir(dir)]:
+ utils.scopy(src_root=dir, src_path="*",
+ dst_root=self.conf.ramdisktree, dst_path="")
+
+ def process_actions(self):
+ for action in self.actions:
+ action.execute()
+
+ def create_modinfo(self, moddir, target):
+ modules_map = {}
+ for root, dirs, files in os.walk(moddir):
+ for file in files:
+ modules_map[file] = os.path.join(root, file)
+
+ modules = { "scsi_hostadapter" : "block",
+ "eth" : "networking" }
+
+ blacklist = ( "floppy",
+ "scsi_mod",
+ "libiscsi" )
+
+ list = {}
+ for type, file_suffix in modules.items():
+ list[type] = {}
+
+ filename = os.path.join(moddir, "modules.%s" % file_suffix)
+ if not os.path.isfile(filename):
+ continue
+
+ with open(filename, "r") as f:
+ for line in f:
+ line = line.strip()
+
+ if line in modules_map:
+ modname, ext = os.path.splitext(line)
+ if modname in blacklist:
+ continue
+
+ cmd = "%s -F description %s" % (self.paths.MODINFO,
+ modules_map[line])
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+ desc = ""
+ else:
+ desc = output.split("\n")[0]
+ desc = desc.strip()
+ desc = desc[:65]
+
+ if not desc:
+ desc = "%s driver" % modname
+ info = '%s\n\t%s\n\t"%s"\n' % (modname, type, desc)
+ list[type][modname] = info
+
+ with open(target, "w") as f:
+ f.write("Version 0\n")
+ for type in list:
+ modlist = sorted(list[type].keys())
+ for mod in modlist:
+ f.write("%s\n" % list[type][mod])
+
+ def get_kernel_modules(self):
+ src_moddir = self.paths.MODULES_DIR
+ dst_moddir = os.path.join(self.conf.ramdisktree, "lib", "modules",
+ self.conf.kernelver)
+
+ # expand modules
+ modules = set()
+
+ for name in self.conf.modules:
+ if name.startswith("="):
+ group = name[1:]
+
+ if group in ("scsi", "ata"):
+ path = os.path.join(src_moddir, "modules.block")
+ elif group == "net":
+ path = os.path.join(src_moddir, "modules.networking")
+ else:
+ path = os.path.join(src_moddir, "modules.%s" % group)
+
+ if os.path.isfile(path):
+ with open(path, "r") as f:
+ for line in f:
+ module = re.sub(r"\.ko$", "", line.strip())
+ modules.add(module)
+
+ else:
+ modules.add(name)
+
+ # resolve modules dependencies
+ with open(self.paths.MODULES_DEP, "r") as f:
+ lines = map(lambda l: l.strip(), f.readlines())
+
+ modpattern = re.compile(r"^.*/(?P.*)\.ko:(?P.*)$")
+ deppattern = re.compile(r"^.*/(?P.*)\.ko$")
+ changed = True
+
+ while changed:
+ for line in lines:
+ changed = False
+
+ m = modpattern.match(line)
+ modname = m.group("name")
+
+ if modname in modules:
+ # add the dependencies
+ for dep in m.group("deps").split():
+ m = deppattern.match(dep)
+ depname = m.group("name")
+
+ if depname not in modules:
+ changed = True
+ modules.add(depname)
+
+ # copy all modules to the ramdisk tree
+ src_path = src_moddir.replace(self.conf.installtree, "", 1)
+ if src_path.startswith("/"):
+ src_path = src_path[1:]
+
+ dst_path = "lib/modules"
+
+ utils.scopy(src_root=self.conf.installtree, src_path=src_path,
+ dst_root=self.conf.ramdisktree, dst_path=dst_path)
+
+ # remove not needed modules
+ for root, dirs, files in os.walk(dst_moddir):
+ for file in files:
+ full_path = os.path.join(root, file)
+ name, ext = os.path.splitext(file)
+
+ if ext == ".ko":
+ if name not in modules:
+ utils.remove(full_path)
+ else:
+ # get the required firmware
+ cmd = "%s -F firmware %s" % (self.paths.MODINFO,
+ full_path)
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+ continue
+
+ for fw in output.split():
+ dst = os.path.join(self.conf.ramdisktree,
+ "lib", "firmware", fw)
+
+ # create the destination directory
+ dir = os.path.dirname(dst)
+ if not os.path.isdir(dir):
+ utils.makedirs(dir)
+
+ # copy the firmware
+ path = os.path.join("lib", "firmware", fw)
+ utils.scopy(src_root=self.conf.installtree,
+ src_path=path,
+ dst_root=self.conf.ramdisktree,
+ dst_path=path)
+
+ # copy additional firmware
+ fw = [ ("ipw2100", "ipw2100*"),
+ ("ipw2200", "ipw2200*"),
+ ("iwl3945", "iwlwifi-3945*"),
+ ("iwl4965", "iwlwifi-4965*"),
+ ("atmel", "atmel_*.bin"),
+ ("zd1211rw", "zd1211"),
+ ("qla2xxx", "ql*") ]
+
+ for module, file in fw:
+ if module in modules:
+ utils.scopy(src_root=self.conf.installtree,
+ src_path=os.path.join("lib", "firmware", file),
+ dst_root=self.conf.ramdisktree,
+ dst_path=os.path.join("lib", "firmware"))
+
+ # compress modules
+ for root, dirs, files in os.walk(dst_moddir):
+ for file in files:
+ if not file.endswith(".ko"):
+ continue
+
+ kopath = os.path.join(root, file)
+ with open(kopath, "rb") as f:
+ kodata = f.read()
+
+ gzipped = gzip.open(kopath + ".gz", "wb")
+ gzipped.write(kodata)
+ gzipped.close()
+
+ os.unlink(kopath)
+
+ # create modinfo
+ modinfo = os.path.join(self.conf.tempdir, "module-info")
+ self.create_modinfo(src_moddir, modinfo)
+
+ target = os.path.join(self.conf.ramdisktree, "lib", "modules",
+ "module-info")
+
+ cmd = "%s --modinfo-file %s --ignore-missing --modinfo %s > %s" % \
+ (self.paths.MODLIST, modinfo, " ".join(list(modules)), target)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+
+ # run depmod
+ cmd = "%s -a -F %s -b %s %s" % (
+ self.paths.DEPMOD, self.paths.SYSTEM_MAP, self.conf.installtree,
+ self.conf.kernelver)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+
+ # remove leftovers
+ utils.remove(os.path.join(dst_moddir, "modules.*map"))
+
+ def get_keymaps(self):
+ if os.path.isfile(self.paths.KEYMAPS_OVERRIDE):
+ dst = os.path.join(self.conf.ramdisktree, "etc", "keymaps.gz")
+ shutil.copy2(self.paths.KEYMAPS_OVERRIDE, dst)
+ else:
+ cmd = "%s %s %s %s" % (
+ self.paths.GETKEYMAPS, self.conf.arch,
+ os.path.join(self.conf.ramdisktree, "etc", "keymaps.gz"),
+ self.conf.installtree)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return False
+
+ return True
+
+ def create_locales(self):
+ dir = os.path.join(self.conf.ramdisktree, "usr", "lib", "locale")
+ utils.makedirs(dir)
+
+ cmd = "%s -c -i en_US -f UTF-8 --prefix %s en_US" % \
+ (self.paths.LOCALEDEF, self.conf.ramdisktree)
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.error(output)
+ return False
+
+ return True
+
+ def compress(self, filename):
+ self.output.info(":: compressing the image file")
+ cwd = os.getcwd()
+ os.chdir(self.conf.ramdisktree)
+
+ # XXX python cpioarchive does not support writing
+ cpioarchive = filename + ".cpio"
+
+ cmd = "find . | cpio --quiet -c -o > %s" % cpioarchive
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ return False
+
+ os.chdir(cwd)
+
+ with open(cpioarchive, "rb") as f:
+ cpiodata = f.read()
+
+ gzipped = gzip.open(filename, "wb")
+ gzipped.write(cpiodata)
+ gzipped.close()
+
+ os.unlink(cpioarchive)
+
+ return True
+
+ def prepare(self):
+ # copy the .buildstamp file
+ shutil.copy2(self.conf.buildstamp, self.conf.ramdisktree)
+
+ self.remove_modules_broken_links()
+ self.move_shared_files()
+ self.process_actions()
+ self.get_kernel_modules()
+ self.get_keymaps()
+ self.create_locales()
+
+ def create(self):
+ self.prepare()
+
+ f = getattr(self, "create_%s" % self.conf.arch, None)
+ if f:
+ return f()
+
+ def create_i386(self):
+ initrd_filename = "initrd.img"
+ kernel_filename = "vmlinuz"
+
+ if self.conf.kernelfile.endswith("PAE"):
+ initrd_filename = "initrd-PAE.img"
+ kernel_filename = "vmlinuz-PAE"
+
+ text = """[images-xen]
+kernel = images/pxeboot/vmlinuz-PAE
+initrd = images/pxeboot/initrd-PAE.img
+
+"""
+
+ utils.edit(self.conf.treeinfo, append=True, text=text)
+
+ initrd_filename = os.path.join(self.conf.tempdir, initrd_filename)
+ self.compress(initrd_filename)
+
+ kernel_filename = os.path.join(self.conf.tempdir, kernel_filename)
+ shutil.copy2(self.conf.kernelfile, kernel_filename)
+
+ return kernel_filename, initrd_filename
+
+ def create_x86_64(self):
+ return self.create_i386()
+
+ def run_s390(self):
+ initrd_filename = os.path.join(self.conf.tempdir, "initrd.img")
+ self.compress(initrd_filename)
+
+ kernel_filename = os.path.join(self.conf.tempdir, "kernel.img")
+ shutil.copy2(self.conf.kernelfile, kernel_filename)
+
+ cmd = "%s %s %s" % (self.paths.GENINITRDSZ,
+ os.path.getsize(initrd_filename),
+ os.path.join(self.conf.imagesdir, "initrd.size"))
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+
+ for filename in (self.paths.REDHAT_EXEC, self.paths.GENERIC_PRM):
+ shutil.copy2(filename, self.conf.imagesdir)
+ shutil.copy2(filename, self.conf.outputdir)
+
+ cmd = "%s -i %s -r %s -p %s -o %s" % (
+ MKS390CD, kernel_filename, initrd_filename,
+ self.paths.GENERIC_PRM,
+ os.path.join(self.conf.imagesdir, "cdboot.img"))
+
+ err, output = commands.getstatusoutput(cmd)
+ if err:
+ self.output.warning(output)
+
+ text = """[images-%s]
+kernel = images/kernel.img
+initrd = images/initrd.img
+initrd.size = images/initrd.size
+generic.prm = images/generic.prm
+generic.ins = generic.ins
+cdboot.img = images/cdboot.img
+
+""" % self.conf.arch
+
+ utils.edit(self.conf.treeinfo, append=True, text=text)
+
+ return kernel_filename, initrd_filename
+
+ def run_s390x(self):
+ return self.run_s390()
+
+ # XXX this should be removed
+ def run_alpha(self):
+ raise NotImplementedError
+
+ def run_ia64(self):
+ raise NotImplementedError
+
+ def run_ppc(self):
+ raise NotImplementedError
+
+ def run_ppc64(self):
+ raise NotImplementedError
diff --git a/src/pylorax/singleton.py b/src/pylorax/singleton.py
new file mode 100644
index 00000000..fbcf4930
--- /dev/null
+++ b/src/pylorax/singleton.py
@@ -0,0 +1,14 @@
+#
+# singleton.py
+#
+
+class Singleton(object):
+
+ __instance = None
+
+ @classmethod
+ def get(cls):
+ if cls.__instance is None:
+ cls.__instance = cls()
+
+ return cls.__instance
diff --git a/src/pylorax/template.py b/src/pylorax/template.py
deleted file mode 100644
index ce4efb00..00000000
--- a/src/pylorax/template.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-# template.py
-# initrd template class
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import sys
-import os
-import re
-
-
-class TemplateError(Exception):
- pass
-
-class Template(object):
- def __init__(self):
- self._actions = []
-
- self.lines = []
- self.included_files = []
-
- def preparse(self, filename):
- try:
- f = open(filename, 'r')
- except IOError as why:
- sys.stderr.write("ERROR: Unable to open template file '%s': %s\n" % (filename, why))
- return False
- else:
- lines = f.readlines()
- f.close()
-
- self.included_files.append(filename)
-
- for line in lines:
- line = line.strip()
-
- if line.startswith('#include'):
- file_to_include = line.split()[1]
- path = os.path.join(os.path.dirname(filename), file_to_include)
- if path not in self.included_files:
- self.preparse(path)
- else:
- self.lines.append(line)
-
- def parse(self, supported_actions, variables):
- lines = self.lines
-
- # append next line if line ends with '\'
- temp = []
- for line in lines:
- line = line.strip()
- if line.endswith('\\'):
- line = line[:-1]
- line = line.rstrip()
- line = line + ' '
- else:
- line = line + '\n'
- temp.append(line)
- temp = ''.join(temp)
- lines = temp.splitlines()
-
- # check template variables
- for lineno, line in enumerate(lines, start=1):
- for var in filter(lambda var: var not in variables, re.findall(r'@(.*?)@', line)):
- raise TemplateError, "unknown variable '%s' on line %d" % (var, lineno)
-
- # parse the template
- for lineno, line in enumerate(lines, start=1):
- line, sep, comment = line.partition('#')
- if not line:
- continue
-
- # expand variables
- for var, value in variables.items():
- line = re.sub(r'@%s@' % var, value, line)
-
- # get the command
- command, line = line.split(None, 1)
- if command not in supported_actions:
- raise TemplateError, "unknown command '%s' on line %d" % (command, lineno)
-
- # create the action object
- regex = supported_actions[command].REGEX
- m = re.match(regex, line)
- if m:
- new_action = supported_actions[command](**m.groupdict())
- self._actions.append(new_action)
- else:
- # didn't match the regex
- raise TemplateError, "invalid command format '%s' on line %d" % (line, lineno)
-
- return True
-
- @property
- def actions(self):
- return self._actions
-
diff --git a/src/pylorax/utils.py b/src/pylorax/utils.py
new file mode 100644
index 00000000..f8f1594f
--- /dev/null
+++ b/src/pylorax/utils.py
@@ -0,0 +1,405 @@
+#
+# utils.py
+#
+
+import sys
+import os
+import shutil
+import glob
+import fileinput
+import re
+import pwd
+import grp
+import commands
+
+
+def expand_path(path, globs=True):
+ l = []
+
+ m = re.match(r"(?P.*){(?P.*?)}(?P.*)", path)
+ if m:
+ for f in re.split(r"\s*,\s*", m.group("expand")):
+ l.extend(expand_path(m.group("prefix") + f + m.group("suffix"),
+ globs=globs))
+ else:
+ if globs:
+ l.extend(glob.glob(path))
+ else:
+ l.append(path)
+
+ return l
+
+
+def remove(file):
+ for fname in expand_path(file):
+ if os.path.islink(fname) or os.path.isfile(fname):
+ os.unlink(fname)
+ else:
+ shutil.rmtree(fname)
+
+
+def __copy(src_path, dst_path, src_root="/", dst_root="/", symlinks=True,
+ ignore_errors=False, deps=False):
+
+ # ensure that roots end with "/"
+ if not src_root.endswith("/"):
+ src_root = src_root + "/"
+ if not dst_root.endswith("/"):
+ dst_root = dst_root + "/"
+
+ smartcopy = SmartCopy(src_root, dst_root, symlinks, ignore_errors)
+
+ src = os.path.join(src_root, src_path)
+ for fname in expand_path(src):
+ fname = fname.replace(src_root, "", 1)
+ smartcopy.copy(fname, dst_path)
+
+ if deps:
+ smartcopy.get_deps()
+
+ smartcopy.process()
+
+
+def scopy(src_path, dst_path, src_root="/", dst_root="/", symlinks=True,
+ ignore_errors=False):
+
+ __copy(src_path, dst_path, src_root, dst_root, symlinks,
+ ignore_errors, deps=False)
+
+
+def dcopy(src_path, dst_path, src_root="/", dst_root="/", symlinks=True,
+ ignore_errors=False):
+
+ __copy(src_path, dst_path, src_root, dst_root, symlinks,
+ ignore_errors, deps=True)
+
+
+def symlink(link_target, link_name):
+ if os.path.islink(link_name) or os.path.isfile(link_name):
+ os.unlink(link_name)
+
+ os.symlink(link_target, link_name)
+
+
+def touch(file):
+ if os.path.exists(file):
+ os.utime(file, None)
+ else:
+ with open(file, "w") as f:
+ pass
+
+
+def mkdir(dir, mode=None):
+ if mode is None:
+ mode = 0755
+
+ for d in expand_path(dir, globs=False):
+ if not os.path.isdir(d):
+ os.mkdir(d, mode)
+
+
+def makedirs(dir, mode=None):
+ if mode is None:
+ mode = 0755
+
+ for d in expand_path(dir, globs=False):
+ if not os.path.isdir(d):
+ os.makedirs(d, mode)
+
+
+def chown(file, user=None, group=None, recursive=False):
+ # if uid or gid is set to -1, it will not be changed
+ uid = gid = -1
+
+ if user is not None:
+ uid = pwd.getpwnam(user)[2]
+ if group is not None:
+ gid = grp.getgrnam(group)[2]
+
+ for fname in expand_path(file):
+ os.chown(fname, uid, gid)
+
+ if recursive and os.path.isdir(fname):
+ for nested in os.listdir(fname):
+ nested = os.path.join(fname, nested)
+ chown(nested, user, group, recursive)
+
+
+def chmod(file, mode, recursive=False):
+ for fname in expand_path(file):
+ os.chmod(fname, mode)
+
+ if recursive and os.path.isdir(fname):
+ for nested in os.listdir(fname):
+ nested = os.path.join(fname, nested)
+ chmod(nested, mode, recursive)
+
+
+def edit(file, text, append=False):
+ mode = "w"
+ if append:
+ mode = "a"
+
+ with open(file, mode) as f:
+ f.write(text)
+
+
+def replace(file, find, replace):
+ fin = fileinput.input(file, inplace=1)
+
+ for line in fin:
+ line = re.sub(find, replace, line)
+ sys.stdout.write(line)
+
+ fin.close()
+
+
+class SmartCopyError(Exception):
+ pass
+
+
+class SmartCopy(object):
+
+ def __init__(self, src_root="/", dst_root="/", symlinks=True,
+ ignore_errors=False):
+
+ self.src_root = src_root
+ self.dst_root = dst_root
+ self.symlinks = symlinks
+ self.ignore_errors = ignore_errors
+
+ self.linker = Linker(src_root)
+
+ self.clear()
+
+ def clear(self):
+ self.makedirs = []
+ self.copyfiles = set()
+ self.links = set()
+ self.errors = []
+
+ def copy(self, src_path, dst_path):
+ src = os.path.normpath(os.path.join(self.src_root, src_path))
+ dst = os.path.normpath(os.path.join(self.dst_root, dst_path))
+
+ # check if the source exists
+ if not os.path.exists(src):
+ err_msg = "cannot stat '%s': No such file or directory" % src
+ if not self.ignore_errors:
+ raise SmartCopyError(err_msg)
+ else:
+ self.errors.append(err_msg)
+ return # EXIT
+
+ if os.path.isfile(src):
+ self.__copy_file(src_path, dst_path, src, dst)
+ elif os.path.isdir(src):
+ self.__copy_dir(src_path, dst_path, src, dst)
+
+ def __copy_file(self, src_path, dst_path, src, dst):
+ # if destination is an existing directory,
+ # append the source filename to the destination path
+ if os.path.isdir(dst):
+ dst = os.path.join(dst, os.path.basename(src))
+
+ # check if the new destination is still an existing directory
+ if os.path.isdir(dst):
+
+ # do not overwrite a directory with a file
+ err_msg = "cannot overwrite directory '%s' " \
+ "with non-directory" % dst
+ if not self.ignore_errors:
+ raise SmartCopyError(err_msg)
+ else:
+ self.errors.append(err_msg)
+ return # EXIT
+
+ if os.path.islink(src):
+
+ if not self.symlinks:
+ real_src = os.path.realpath(src)
+ self.copyfiles.add((real_src, dst))
+ else:
+ self.__copy_link(src_path, dst_path, src, dst)
+
+ else:
+
+ self.copyfiles.add((src, dst))
+
+ def __copy_dir(self, src_path, dst_path, src, dst):
+ # append the source directory name to the destination path
+ dirname = os.path.basename(src)
+ new_dst = os.path.join(dst, dirname)
+
+ # remove the trailing "/",
+ # to make sure, that we don't try to create "dir" and "dir/"
+ if new_dst.endswith("/"):
+ new_dst = new_dst[:-1]
+
+ if os.path.islink(src):
+
+ if not self.symlinks:
+ real_src = os.path.realpath(src)
+
+ if not os.path.exists(new_dst) and \
+ new_dst not in self.makedirs:
+ self.makedirs.append(new_dst)
+
+ for fname in os.listdir(real_src):
+ fname = os.path.join(real_src, fname)
+ self.copy(fname, new_dst)
+
+ else:
+ self.__copy_link(src_path, dst_path, src, new_dst)
+
+ else:
+
+ # create the destination directory, if it does not exist
+ if not os.path.exists(new_dst) and \
+ new_dst not in self.makedirs:
+ self.makedirs.append(new_dst)
+
+ elif os.path.isfile(new_dst):
+ err_msg = "cannot overwrite file '%s' with a directory" \
+ % new_dst
+ if not self.ignore_errors:
+ raise SmartCopyError(err_msg)
+ else:
+ self.errors.append(err_msg)
+ return # EXIT
+
+ new_dst_path = os.path.join(dst_path, dirname)
+
+ try:
+ fnames = os.listdir(src)
+ except OSError as why:
+ err_msg = "cannot list directory '%s': %s'" % (src, why)
+ if not self.ignore_errors:
+ raise SmartCopyError(err_msg)
+ else:
+ self.errors.append(err_msg)
+ return # EXIT
+
+ for fname in fnames:
+ fname = os.path.join(src_path, fname)
+ self.copy(fname, new_dst_path)
+
+ def __copy_link(self, src_path, dst_path, src, dst):
+ # read the link target
+ link_target = os.readlink(src)
+
+ # get the target source and destination paths
+ target_src_path = os.path.join(os.path.dirname(src_path), link_target)
+ target_dst_dir = os.path.join(dst_path, os.path.dirname(link_target))
+
+ # if the link target is an absolute path,
+ # make sure we copy it relative to the dst_root
+ if target_dst_dir.startswith("/"):
+ target_dst_dir = target_dst_dir[1:]
+
+ # remove the trailing "/"
+ if target_dst_dir.endswith("/"):
+ target_dst_dir = target_dst_dir[:-1]
+
+ # create the destination directory, if it doesn't exist
+ target_dst = os.path.join(self.dst_root, target_dst_dir)
+ if not os.path.exists(target_dst) and \
+ target_dst not in self.makedirs:
+ self.makedirs.append(target_dst)
+
+ # copy the target along with the link
+ self.copy(target_src_path, target_dst_dir)
+
+ # create the symlink named dst, pointing to link_target
+ self.links.add((link_target, dst))
+
+ def get_deps(self):
+ deps = set()
+
+ for src, dst in self.copyfiles:
+ if self.linker.is_elf(src):
+ deps = deps.union(self.linker.get_deps(src))
+
+ for src in deps:
+ src_path = src.replace(self.src_root, "", 1)
+ dst_path = os.path.dirname(src_path)
+
+ # create the destination directory
+ dst_dir = os.path.join(self.dst_root, dst_path)
+ if not os.path.exists(dst_dir) and \
+ dst_dir not in self.makedirs:
+ self.makedirs.append(dst_dir)
+
+ self.copy(src_path, dst_path)
+
+ def process(self):
+ # create required directories
+ map(mkdir, self.makedirs)
+
+ # copy all the files
+
+ # remove the dst, if it is a link to src
+ for src, dst in self.copyfiles:
+ if os.path.realpath(dst) == src:
+ os.unlink(dst)
+
+ map(lambda (src, dst): shutil.copy2(src, dst), self.copyfiles)
+
+ # create symlinks
+ map(lambda (target, name): symlink(target, name), self.links)
+
+
+class LinkerError(Exception):
+ pass
+
+
+class Linker(object):
+
+ LIBDIRS = ( "lib64",
+ "usr/lib64",
+ "lib",
+ "usr/lib" )
+
+ def __init__(self, root="/"):
+ libdirs = map(lambda path: os.path.join(root, path), self.LIBDIRS)
+ libdirs = ":".join(libdirs)
+
+ ld_linux = None
+
+ with open("/usr/bin/ldd", "r") as f:
+ for line in f:
+ m = re.match(r"^RTLDLIST=(?P.*)$", line.strip())
+ if m:
+ ld_linux = m.group("ld_linux")
+ break
+
+ if ld_linux is None:
+ raise LinkerError("unable to find the ld_linux executable")
+
+ self.lddcmd = "LD_LIBRARY_PATH=%s %s --list" % (libdirs, ld_linux)
+ self.pattern = re.compile(r"^[a-zA-Z0-9.-_/]*\s=>\s" \
+ r"(?P[a-zA-Z0-9.-_/]*)" \
+ r"\s\(0x[0-9a-f]*\)$")
+
+ def is_elf(self, file):
+ err, output = commands.getstatusoutput("file --brief %s" % file)
+ if err:
+ raise LinkerError("error getting the file type")
+
+ if not output.startswith("ELF"):
+ return False
+
+ return True
+
+ def get_deps(self, file):
+ err, output = commands.getstatusoutput("%s %s" % (self.lddcmd, file))
+ if err:
+ raise LinkerError("error getting the file dependencies")
+
+ deps = set()
+ for line in output.splitlines():
+ m = self.pattern.match(line.strip())
+ if m:
+ deps.add(m.group("lib"))
+
+ return deps
diff --git a/src/pylorax/utils/fileutils.py b/src/pylorax/utils/fileutils.py
deleted file mode 100644
index a63211d2..00000000
--- a/src/pylorax/utils/fileutils.py
+++ /dev/null
@@ -1,306 +0,0 @@
-#
-# fileutils.py
-# functions for working with files
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import sys
-import os
-import shutil
-import glob
-import fileinput
-import re
-
-
-def normalize(src_root, src_path, dst_root, dst_path):
- src = os.path.join(src_root, src_path)
- dst = os.path.join(dst_root, dst_path)
- src = os.path.normpath(src)
- dst = os.path.normpath(dst)
-
- return src, dst
-
-
-def remove(target, verbose=False):
- for fname in glob.iglob(target):
- if verbose:
- print "removing '%s'" % (fname,)
-
- if os.path.islink(fname) or os.path.isfile(fname):
- os.unlink(fname)
- else:
- shutil.rmtree(fname, ignore_errors=True)
-
-def touch(filename, verbose=False):
- if verbose:
- print "touching '%s'" % (filename,)
-
- if os.path.exists(filename):
- os.utime(filename, None)
- else:
- try:
- f = open(filename, "w")
- except IOError as why:
- print >> sys.stderr, "cannot create '%s': %s" % (filename, why)
- return False
- else:
- f.close()
-
- return True
-
-def copy(src_path, dst_path, src_root="/", dst_root="/",
- nolinks=False, ignore_errors=False, verbose=False):
-
- filecopy = Copy(ignore_errors, verbose)
-
- src = os.path.join(src_root, src_path)
- for fname in glob.iglob(src):
- fname = fname.replace(src_root, "", 1)
-
- if src_path[0] != "/" and fname[0] == "/":
- fname = fname[1:]
-
- filecopy.copy(fname, dst_path, src_root, dst_root, nolinks)
-
- return filecopy.errors
-
-def move(src_path, dst_path, src_root="/", dst_root="/",
- nolinks=False, ignore_errors=False, verbose=False):
-
- errors = copy(src_path, dst_path, src_root, dst_root,
- nolinks, ignore_errors, verbose)
-
- # if everything was copied ok, remove the source
- if not errors:
- src, dst = normalize(src_root, src_path, dst_root, dst_path)
- remove(src, verbose)
-
- return errors
-
-def chmod(target, mode, recursive=False, verbose=False):
- mode = int(mode)
-
- for fname in glob.iglob(target):
- if verbose:
- print "changing permissions on '%s'" % (fname,)
-
- os.chmod(fname, mode)
-
- if recursive and os.path.isdir(fname):
- for nested in os.listdir(fname):
- nested = os.path.join(fname, nested)
- chmod(nested, mode, recursive, verbose)
-
-def edit(filename, text, append=False, verbose=False):
- mode = "w"
- if append:
- mode = "a"
-
- if verbose:
- print "editing '%s'" % (filename,)
-
- try:
- f = open(filename, mode)
- except IOError as why:
- print >> sys.stderr, "cannot edit '%s': %s" % (filename, why)
- return False
- else:
- f.write(text)
- f.close()
-
- return True
-
-def replace(filename, find, replace, verbose=False):
- if verbose:
- print "replacing '%s' for '%s' in '%s'" % (find, replace, filename)
-
- fin = fileinput.input(filename, inplace=1)
- for line in fin:
- line = re.sub(find, replace, line)
- sys.stdout.write(line)
- fin.close()
-
- return True
-
-
-class CopyError(Exception):
- pass
-
-class Copy(object):
- def __init__(self, ignore_errors=False, verbose=False):
- self.Error = CopyError
-
- self.ignore_errors = ignore_errors
- self.verbose = verbose
-
- self.errors = []
-
- def copy(self, src_path, dst_path, src_root="/", dst_root="/", nolinks=False):
- # normalize the source and destination paths
- src, dst = normalize(src_root, src_path, dst_root, dst_path)
-
- # check if the source exists
- if not os.path.exists(src):
- err_msg = "cannot stat '%s': No such file or directory" % (src,)
- if not self.ignore_errors:
- raise self.Error, err_msg
- else:
- print >> sys.stderr, err_msg
- self.errors.append(err_msg)
- return False # EXIT
-
- if os.path.isfile(src):
-
- # if destination is an existing directory, append the source filename
- # to the destination path
- if os.path.isdir(dst):
- dst = os.path.join(dst, os.path.basename(src))
-
- # check if the destination exists
- if os.path.isfile(dst):
-
- # overwrite file
- try:
- if self.verbose:
- print "overwriting '%s'" % (dst,)
- os.unlink(dst)
- except OSError as why:
- err_msg = "cannot overwrite file '%s': %s" % (dst, why)
- if not self.ignore_errors:
- raise self.Error, err_msg
- else:
- print >> sys.stderr, err_msg
- self.errors.append(err_msg)
- return False # EXIT
-
- elif os.path.isdir(dst):
-
- # do not overwrite directory with a file
- err_msg = "cannot overwrite directory '%s' with non-directory" \
- % (dst,)
- if not self.ignore_errors:
- raise self.Error, err_msg
- else:
- print >> sys.stderr, err_msg
- self.errors.append(err_msg)
- return False # EXIT
-
- if os.path.islink(src):
-
- if nolinks:
- self.__copy_file(os.path.realpath(src), dst)
- else:
- self.__copy_link(src_path, dst_path, src_root, dst_root,
- src, dst)
-
- else:
-
- self.__copy_file(src, dst)
-
- elif os.path.isdir(src):
-
- # append the source directory name to the destination path
- dirname = os.path.basename(src)
- new_dst = os.path.join(dst, dirname)
-
- if os.path.islink(src):
-
- if nolinks:
- real_src = os.path.realpath(src)
-
- if not os.path.exists(new_dst):
- os.makedirs(new_dst)
-
- for fname in os.listdir(real_src):
- fname = os.path.join(real_src, fname)
-
- if os.path.isfile(fname):
- self.__copy_file(fname, new_dst)
- else:
- dst = os.path.join(new_dst, os.path.basename(fname))
- shutil.copytree(fname, dst, symlinks=False)
- else:
- self.__copy_link(src_path, dst_path, src_root, dst_root,
- src, new_dst)
-
- else:
-
- # create the destination directory if it does not exist
- if not os.path.exists(new_dst):
- os.makedirs(new_dst)
-
- if os.path.isfile(new_dst):
- err_msg = "cannot overwrite file '%s' with a directory" \
- % (new_dst,)
- if not self.ignore_errors:
- raise self.Error, err_msg
- else:
- print >> sys.stderr, err_msg
- self.errors.append(err_msg)
- return False # EXIT
-
- new_dst_path = os.path.join(dst_path, dirname)
-
- fnames = []
- try:
- fnames = os.listdir(src)
- except OSError as why:
- err_msg = "cannot list directory '%s': %s'" % (src, why)
- if not self.ignore_errors:
- raise self.Error, err_msg
- else:
- print >> sys.stderr, err_msg
- self.errors.append(err_msg)
-
- for fname in fnames:
- fname = os.path.join(src_path, fname)
- self.copy(fname, new_dst_path, src_root, dst_root)
-
- def __copy_file(self, src, dst):
- if self.verbose:
- print "copying '%s' to '%s'" % (src, dst)
-
- try:
- shutil.copy(src, dst)
- except (shutil.Error, IOError) as why:
- err_msg = "cannot copy '%s' to '%s': %s" % (src, dst, why)
- if not self.ignore_errors:
- raise self.Error, err_msg
- else:
- print >> sys.stderr, err_msg
- self.errors.append(err_msg)
-
- def __copy_link(self, src_path, dst_path, src_root, dst_root, src, dst):
- # read the link target
- link_target = os.readlink(src)
-
- # get the target source and destination paths
- target_src_path = os.path.join(os.path.dirname(src_path), link_target)
- target_dst_path = os.path.join(dst_path, os.path.dirname(link_target))
-
- # create the destination directory if it doesn't exist
- target_dst = os.path.join(dst_root, target_dst_path)
- if not os.path.exists(target_dst):
- os.makedirs(target_dst)
-
- # copy the target along with the link
- self.copy(target_src_path, target_dst_path, src_root, dst_root)
-
- # create the symlink named dst, pointing to link_target
- os.symlink(link_target, dst)
diff --git a/src/pylorax/utils/ldd.py b/src/pylorax/utils/ldd.py
deleted file mode 100644
index 10ddd7e3..00000000
--- a/src/pylorax/utils/ldd.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# ldd.py
-# library dependencies
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import os
-import re
-import commands
-
-
-class LDD(object):
-
- def __init__(self, libroots=["/lib", "/usr/lib"]):
- f = open("/usr/bin/ldd", "r")
- for line in f.readlines():
- line = line.strip()
- if line.startswith("RTLDLIST="):
- rtldlist, sep, ld_linux = line.partition("=")
- break
- f.close()
-
- self._lddcmd = "LD_LIBRARY_PATH=%s %s --list" % (":".join(libroots),
- ld_linux)
-
- pattern = r"^([a-zA-Z0-9.]*\s=>\s)(?P[a-zA-Z0-9./-]*)\s\(0x[0-9a-f]*\)$"
- self.pattern = re.compile(pattern)
-
- self._deps = set()
-
- self._errors = []
-
- def is_elf(self, filename):
- cmd = "file --brief %s" % (filename)
- err, out = commands.getstatusoutput(cmd)
- if err:
- return False
-
- if not out.split()[0] == "ELF":
- return False
-
- return True
-
- def getDeps(self, filename):
- # skip no elf files
- if not self.is_elf(filename):
- return
-
- cmd = "%s %s" % (self._lddcmd, filename)
- err, out = commands.getstatusoutput(cmd)
- if err:
- self._errors.append((filename, out))
- return
-
- lines = out.splitlines()
- for line in lines:
- line = line.strip()
-
- m = self.pattern.match(line)
- if m:
- lib = m.group("lib")
- if lib not in self._deps:
- self._deps.add(lib)
- self.getDeps(lib)
-
- @property
- def deps(self):
- return self._deps
-
- @property
- def errors(self):
- return self._errors
diff --git a/src/pylorax/utils/yumwrapper.py b/src/pylorax/utils/yumwrapper.py
deleted file mode 100644
index 53adfdf3..00000000
--- a/src/pylorax/utils/yumwrapper.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# yumwrapper.py
-# yum wrapper
-#
-# Copyright (C) 2009 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 .
-#
-# Red Hat Author(s): Martin Gracik
-#
-
-import sys
-import os
-import yum
-import yum.callbacks
-import yum.rpmtrans
-
-from pylorax.misc import seq, get_console_size
-
-
-class Callback(yum.rpmtrans.SimpleCliCallBack):
-
- def __init__(self):
- yum.rpmtrans.SimpleCliCallBack.__init__(self)
- self.height, self.width = get_console_size()
-
- def event(self, package, action, te_current, te_total, ts_current, ts_total):
- progress = float(te_current) / float(te_total)
- percentage = int(progress * 100)
-
- bar_length = 20
- bar = int(percentage / (100 / bar_length))
-
- total_progress_str = "[%s/%s] " % (ts_current, ts_total)
- package_progress_str = " [%s%s] %3d%%" % ("#" * bar, "-" * (bar_length - bar),
- percentage)
-
- action_str = "%s %s" % (self.action[action], package)
- chars_left = self.width - len(total_progress_str) - len(package_progress_str)
-
- if len(action_str) > chars_left:
- action_str = action_str[:chars_left-3]
- action_str = action_str + "..."
- else:
- action_str = action_str + " " * (chars_left - len(action_str))
-
- msg = total_progress_str + action_str + package_progress_str
-
- sys.stdout.write(msg)
- sys.stdout.write("\r")
-
- if percentage == 100:
- sys.stdout.write("\n")
-
- sys.stdout.flush()
-
-
-class Yum(object):
-
- def __init__(self, yumconf="/etc/yum/yum.conf", installroot="/",
- errfile="/dev/null"):
-
- self.yb = yum.YumBase()
-
- self.yumconf = os.path.abspath(yumconf)
- self.installroot = os.path.abspath(installroot)
- self.errfile = errfile
-
- self.yb.preconf.fn = self.yumconf
- self.yb.preconf.root = self.installroot
- self.yb._getConfig()
-
- self.yb._getRpmDB()
- self.yb._getRepos()
- self.yb._getSacks()
-
- def find(self, patterns):
- pl = self.yb.doPackageLists(patterns=seq(patterns))
- return pl.installed, pl.available
-
- def add_package(self, pattern):
- try:
- self.yb.install(name=pattern)
- except yum.Errors.InstallError:
- # didn't find an exact package name match
- try:
- self.yb.install(pattern=pattern)
- except yum.Errors.InstallError:
- # no package found
- return False
-
- return True
-
- def install(self):
- self.yb.resolveDeps()
- self.yb.buildTransaction()
-
- cb = yum.callbacks.ProcessTransBaseCallback()
- #cb = yum.callbacks.ProcessTransNoOutputCallback()
- rpmcb = Callback()
-
- # XXX ATTENTION! ugly rpm error output hack
- # we redirect the error output from rpm to errfile,
- # so it does not show up in our "nice" output
- # 2 = err descriptor
- standard_err = os.dup(2)
- my_err = open(self.errfile, "a")
- os.dup2(my_err.fileno(), 2)
-
- # now we process the transactions without errors showing up in the output
- self.yb.processTransaction(callback=cb, rpmDisplay=rpmcb)
-
- # and we put the standard error output back, so nobody will notice
- os.dup2(standard_err, 2)
- my_err.close()
-
- self.yb.closeRpmDB()
- self.yb.close()
diff --git a/share/pam.d/login b/usr/share/lorax/initrd/s390/etc/pam.d/login
similarity index 100%
rename from share/pam.d/login
rename to usr/share/lorax/initrd/s390/etc/pam.d/login
diff --git a/usr/share/lorax/initrd/s390/etc/pam.d/remote b/usr/share/lorax/initrd/s390/etc/pam.d/remote
new file mode 100644
index 00000000..5e8d5794
--- /dev/null
+++ b/usr/share/lorax/initrd/s390/etc/pam.d/remote
@@ -0,0 +1,9 @@
+#%PAM-1.0
+auth required pam_env.so
+auth sufficient pam_unix.so likeauth nullok
+auth required pam_deny.so
+account required pam_unix.so
+password sufficient pam_unix.sp nullok use_authtok md5 shadow
+password required pam_deny.so
+session required pam_limits.so
+session required pam_unix.so
diff --git a/usr/share/lorax/initrd/s390/etc/pam.d/sshd b/usr/share/lorax/initrd/s390/etc/pam.d/sshd
new file mode 100644
index 00000000..5e8d5794
--- /dev/null
+++ b/usr/share/lorax/initrd/s390/etc/pam.d/sshd
@@ -0,0 +1,9 @@
+#%PAM-1.0
+auth required pam_env.so
+auth sufficient pam_unix.so likeauth nullok
+auth required pam_deny.so
+account required pam_unix.so
+password sufficient pam_unix.sp nullok use_authtok md5 shadow
+password required pam_deny.so
+session required pam_limits.so
+session required pam_unix.so
diff --git a/share/sshd/sshd_config b/usr/share/lorax/initrd/s390/etc/ssh/sshd_config
similarity index 100%
rename from share/sshd/sshd_config
rename to usr/share/lorax/initrd/s390/etc/ssh/sshd_config
diff --git a/usr/share/lorax/initrd/s390x b/usr/share/lorax/initrd/s390x
new file mode 120000
index 00000000..ba766cae
--- /dev/null
+++ b/usr/share/lorax/initrd/s390x
@@ -0,0 +1 @@
+s390
\ No newline at end of file
diff --git a/src/pylorax/utils/__init__.py b/usr/share/lorax/installtree/noarch/.gconf/desktop/%gconf.xml
similarity index 100%
rename from src/pylorax/utils/__init__.py
rename to usr/share/lorax/installtree/noarch/.gconf/desktop/%gconf.xml
diff --git a/usr/share/lorax/installtree/noarch/.gconf/desktop/gnome/%gconf.xml b/usr/share/lorax/installtree/noarch/.gconf/desktop/gnome/%gconf.xml
new file mode 100644
index 00000000..e69de29b
diff --git a/share/dogtail/%gconf.xml b/usr/share/lorax/installtree/noarch/.gconf/desktop/gnome/interface/%gconf.xml
similarity index 100%
rename from share/dogtail/%gconf.xml
rename to usr/share/lorax/installtree/noarch/.gconf/desktop/gnome/interface/%gconf.xml
diff --git a/share/libuser/libuser.conf b/usr/share/lorax/installtree/noarch/etc/libuser.conf
similarity index 100%
rename from share/libuser/libuser.conf
rename to usr/share/lorax/installtree/noarch/etc/libuser.conf
diff --git a/share/selinux/config b/usr/share/lorax/installtree/noarch/etc/selinux/config
similarity index 100%
rename from share/selinux/config
rename to usr/share/lorax/installtree/noarch/etc/selinux/config
diff --git a/share/images/README b/usr/share/lorax/outputdir/images/README
similarity index 100%
rename from share/images/README
rename to usr/share/lorax/outputdir/images/README
diff --git a/share/images/pxeboot/README b/usr/share/lorax/outputdir/images/pxeboot/README
similarity index 100%
rename from share/images/pxeboot/README
rename to usr/share/lorax/outputdir/images/pxeboot/README