New version

This commit is contained in:
Martin Gracik 2010-02-23 14:20:05 +01:00
parent 492037c54b
commit a4c638f132
51 changed files with 2379 additions and 3589 deletions

View File

@ -1,3 +1,2 @@
David Cantrell <dcantrell@redhat.com>
Martin Gracik <mgracik@redhat.com>
David Cantrell <dcantrell@redhat.com>

View File

@ -1,14 +1,11 @@
# Makefile for lorax
PYTHON ?= /usr/bin/env python
PYTHON ?= /usr/bin/python
DESTDIR ?= /
all:
$(PYTHON) setup.py build
install:
$(PYTHON) setup.py install --root $(DESTDIR)
$(PYTHON) setup.py install
clean:
-rm -rf build
-git clean -d -x -f

4
etc/config.i386 Normal file
View File

@ -0,0 +1,4 @@
[lorax]
packages:
kernel-PAE grub memtest86+

View File

@ -1,15 +1,8 @@
[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 NetworkManager-gnome wget
anaconda kernel *firmware* man hal wget samba-client gfs2-utils nfs-utils
ntfs-3g
modules:
sunrpc lockd floppy cramfs loop edd pcspkr squashfs
@ -21,3 +14,6 @@ modules:
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
initrd_template = templates/initrd.ltmpl
install_template = templates/install.ltmpl

View File

@ -1,8 +0,0 @@
[lorax]
packages:
grub gpart syslinux memtest86+ efibootmgr dmidecode pcmciautils
kernel-PAE
initrd_template=templates/initrd/initrd.i386
scrubs_template=templates/scrubs/scrubs.i386

View File

@ -1 +0,0 @@
config.i386

View File

@ -1 +0,0 @@
config.i386

View File

@ -1,7 +0,0 @@
[lorax]
packages:
pcmciautils pdisk yaboot hfsutils fbset ppc64-utils
initrd_template=templates/initrd/initrd.i386
scrubs_template=templates/scrubs/scrubs.i386

View File

@ -1,10 +0,0 @@
[lorax]
packages:
pcmciautils pdisk yaboot hfsutils fbset ppc64-utils
modules:
spufs viocd gpio_mdio
initrd_template=templates/initrd/initrd.i386
scrubs_template=templates/scrubs/scrubs.i386

View File

@ -1,11 +0,0 @@
[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.i386

View File

@ -1 +0,0 @@
config.s390

View File

@ -1 +0,0 @@
config.i386

View File

@ -1,246 +0,0 @@
## 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/polkit-1/actions
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/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/polkit-1 to ${initrd} etc
copy ${instroot} \
usr/share/dbus-1/system-services/org.freedesktop.PolicyKit1.service to \
${initrd} usr/share/dbus-1/system-services
copy ${instroot} usr/share/polkit-1/actions/org.freedesktop.policykit.policy \
to ${initrd} usr/share/polkit-1/actions
## 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} 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-rh.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} usr/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
## missing files
copy ${instroot} usr/sbin/dmidecode to ${initrd} bin
copy ${instroot} sbin/load_policy to ${initrd} bin
copy ${instroot} sbin/mdadm to ${initrd} bin
copy ${instroot} sbin/mdmon to ${initrd} bin
copy ${instroot} bin/mkdir to ${initrd} bin
copy ${instroot} usr/bin/wget to ${initrd} bin

View File

@ -1,11 +0,0 @@
<%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-${basearch}.gz to \
${initrd} etc/screenfont.gz

View File

@ -1,51 +0,0 @@
<%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

View File

@ -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

214
etc/templates/initrd.ltmpl Normal file
View File

@ -0,0 +1,214 @@
## create modules and firmware symlinks
symlink "lib/modules" "modules"
symlink "lib/firmware" "firmware"
## create required directories
makedirs "sbin"
symlink "sbin" "bin"
makedirs "dev"
makedirs "etc"
makedirs "lib"
makedirs "proc"
makedirs "selinux"
makedirs "sys"
makedirs "tmp"
makedirs "usr"
makedirs "var"
## copy etc stuff
copy "etc/passwd"
copy "etc/group"
copy "etc/hosts"
copy "etc/nsswitch.conf"
## copy mount/umount files
copy "bin/mount"
copy "bin/umount"
copy "sbin/mount.*"
copy "sbin/umount.*"
## copy udev stuff
copy "sbin/udevd"
copy "sbin/udevadm"
symlink "udevadm" "sbin/udevinfo"
symlink "udevadm" "sbin/udevsettle"
## copy udev conf and rules
copy "etc/udev/udev.conf"
copy "lib/udev/*"
remove "lib/udev/rules.d/*persistent*"
remove "lib/udev/rules.d/*generator*"
copy "etc/udev/rules.d/*.rules"
## copy bash
copy "bin/bash"
symlink "bash" "bin/sh"
## other
copy "sbin/consoletype"
copy "usr/bin/logger" "bin"
## copy init functions
copy "etc/rc.d/init.d/functions"
copy "etc/sysconfig/network-scripts/network-functions*"
## create init.d symlink
symlink "/etc/rc.d/init.d" "etc/init.d"
## dhcp client daemons and support programs
copy "sbin/dhclient"
copy "sbin/dhclient-script"
copy "sbin/arping"
copy "sbin/ifconfig"
copy "sbin/ip"
copy "bin/ipcalc"
copy "bin/hostname"
copy "sbin/ethtool"
copy "sbin/route"
touch "etc/resolv.conf"
## hwdata
copy "usr/share/hwdata/pci.ids"
copy "usr/share/hwdata/usb.ids"
## hal
copy "usr/sbin/hald" "sbin"
copy "usr/libexec/hald-runner"
copy "usr/libexec/hald-generate-fdi-cache"
copy "usr/libexec/hal*storage*"
makedirs "var/run"
touch "var/run/hald.acl-list"
copy "usr/share/hal/fdi/*"
copy "etc/hal/fdi/*"
copy "etc/dbus-1/system.d/hal.conf"
## policykit
copy "etc/polkit-1"
copy "usr/share/dbus-1/system-services/org.freedesktop.PolicyKit1.service"
copy "usr/share/polkit-1/actions/org.freedesktop.policykit.policy"
## dbus
copy "bin/dbus-uuidgen"
copy "bin/dbus-daemon"
copy "etc/dbus-1/system.conf"
copy "${libdir}/dbus-1/dbus-daemon-launch-helper"
## wpa_supplicant
copy "usr/sbin/wpa_passphrase"
copy "usr/sbin/wpa_supplicant"
copy "etc/dbus-1/system.d/wpa_supplicant.conf"
copy "etc/wpa_supplicant/wpa_supplicant.conf"
copy "usr/share/dbus-1/system-services/fi.epitest.hostap.WPASupplicant.service"
## networkmanager
copy "usr/sbin/NetworkManager"
copy "etc/dbus-1/system.d/nm-*.conf"
copy "etc/dbus-1/system.d/NetworkManager.conf"
copy "etc/NetworkManager/nm-system-settings.conf"
copy "usr/${libdir}/NetworkManager/libnm-settings-plugin-ifcfg-rh.so"
copy "usr/libexec/nm-*"
copy "usr/share/dbus-1/system-services/org.freedesktop.nm_dispatcher.service"
## modprobe
copy "sbin/modprobe"
copy "sbin/insmod"
copy "sbin/rmmod"
## terminfos
copy "usr/share/terminfo/a/ansi"
copy "usr/share/terminfo/d/dumb"
copy "usr/share/terminfo/l/linux"
copy "usr/share/terminfo/s/screen"
copy "usr/share/terminfo/v/vt100"
copy "usr/share/terminfo/v/vt100-nav"
copy "usr/share/terminfo/v/vt102"
copy "usr/share/terminfo/x/xterm"
copy "usr/share/terminfo/x/xterm-color"
copy "usr/share/terminfo/g/gnome"
## misc
copy "bin/awk"
copy "bin/egrep"
copy "bin/fgrep"
copy "bin/grep"
copy "bin/kill"
copy "bin/ln"
copy "usr/bin/readlink" "bin"
copy "bin/rm"
copy "bin/rmdir"
copy "bin/sed"
copy "bin/sleep"
copy "bin/touch"
copy "usr/sbin/dmidecode" "sbin"
copy "sbin/load_policy"
copy "sbin/mdadm"
copy "sbin/mdmon"
copy "bin/mkdir"
copy "usr/bin/wget" "bin"
## misc symlinks
symlink "/sbin/init" "init"
symlink "/proc/mounts" "etc/mtab"
makedirs "var/lib"
symlink "../../tmp" "var/lib/xkb"
## loader
copy "usr/lib/anaconda-runtime/loader/loader" "sbin"
copy "usr/lib/anaconda-runtime/loader/loader.tr" "etc"
## indirect dependencies
copy "${libdir}/ld-linux.so.2"
copy "${libdir}/libcom_err.so.2"
copy "${libdir}/libgcc_s.so.1"
copy "${libdir}/libnss_dns.so.2"
copy "${libdir}/libnss_files.so.2"
copy "usr/${libdir}/libsqlite3.so.0"
## langtable
copy "usr/lib/anaconda/lang-table" "etc"
## arch bits
edit "etc/arch" "${buildarch}"
## architecture specific code
% if basearch in ("i386",):
copy "usr/lib/anaconda-runtime/loader/init" "sbin"
symlink "init" "sbin/reboot"
symlink "init" "sbin/halt"
symlink "init" "sbin/poweroff"
## screenfont
copy "usr/lib/anaconda-runtime/screenfont-${basearch}.gz" "etc"
rename "etc/screenfont-${basearch}.gz" "etc/screenfont.gz"
% endif
% if basearch in ("s390", "s390x"):
makedirs "etc/ssh"
makedirs "etc/security"
makedirs "${libdir}/security"
makedirs "var/empty/sshd"
symlink "../../tmp" "var/state/xkb"
copy "${libdir}/libpam_misc.so*"
copy "${libdir}/libwrap*.so*"
copy "usr/lib/anaconda-runtime/loader/shutdown" "sbin"
copy "usr/lib/anaconda-runtime/loader/linuxrc.s390" "sbin"
rename "sbin/linuxrc.s390" "sbin/init"
copy "usr/lib/anaconda-runtime/loader/lsznet.raw" "sbin"
rename "sbin/lsznet.raw" "sbin/lsznet"
copy "usr/lib/anaconda-runtime/loader/controlunits.sh" "sbin"
rename "sbin/controlunits.sh" "sbin/controlunits"
copy "${libdir}/security/pam*.so"
copy "etc/pam.d/other"
copy "etc/security/limits.conf"
copy "etc/security/pam_env.conf"
copy "bin/login"
copy "usr/sbin/dasdfmt"
copy "usr/sbin/sshd"
copy "usr/bin/xauth"
copy "usr/sbin/cmsfs*"
% endif

View File

@ -1,32 +1,26 @@
#! /usr/bin/env python
from distutils.core import setup
import glob
import os
from glob import glob
main_etc_files = []
for comp in glob.glob(os.path.join(os.getcwd(), 'etc', '*')):
if os.path.isfile(comp):
main_etc_files.append(comp)
etc_data_files = [(os.path.join(os.path.sep, 'etc', 'lorax'),
main_etc_files)]
data_files = [("/etc/lorax", glob("etc/config.*")),
("/etc/lorax", ["etc/ignore_errors"]),
("/etc/lorax/templates", glob("etc/templates/*"))
]
for comp in glob.glob(os.path.join(os.getcwd(), 'etc', '*')):
if os.path.isdir(comp):
sub_files = glob.glob(os.path.join(comp, '*'))
etc_path = os.path.join(os.path.sep, 'etc', 'lorax', os.path.basename(comp))
etc_data_files.append((etc_path, sub_files))
data_files = [(os.path.join(os.path.sep, 'usr', 'share', 'lorax'),
glob.glob(os.path.join('share', '*')))] + etc_data_files
setup(name='lorax',
version='0.1',
description='Boot image build tool',
author='David Cantrell',
author_email='dcantrell@redhat.com',
license='GPLv2+',
package_dir = {'': 'src'},
packages = ['pylorax'],
scripts = [os.path.join('src', 'bin', 'lorax')],
data_files = data_files
)
setup(name="lorax",
version="0.1",
description="Lorax",
long_description="",
author="Martin Gracik",
author_email="mgracik@redhat.com",
url="http://",
download_url="http://",
license="GPLv2+",
packages=["pylorax"],
package_dir={"" : "src"},
scripts=["src/bin/lorax"],
data_files=data_files
)

120
src/bin/lorax Executable file → Normal file
View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
#! /usr/bin/env python
#
# lorax
# lorax executable script
#
# Copyright (C) 2009 Red Hat, Inc.
#
@ -22,9 +21,122 @@
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
from __future__ import print_function
import sys
import pylorax.launcher
import os
import tempfile
from optparse import OptionParser, OptionGroup
import pylorax
import pylorax.config
from pylorax.yumbase import get_yum_base_object
def main(args):
version = "{0} 0.1".format(os.path.basename(args[0]))
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)
yb = get_yum_base_object(installtree, repositories, opts.mirrorlist,
yumtempdir)
if yb is None:
print("error: unable to create the yumbase object", file=sys.stderr)
shutil.rmtree(tempdir)
sys.exit(1)
# configure lorax
config = pylorax.config.LoraxConfig()
config.colors = opts.colors
config.encoding = opts.encoding
config.debug = opts.debug
# run lorax
params = {"installtree": installtree,
"outputdir": opts.outputdir,
"product": opts.product,
"version": opts.version,
"release": opts.release,
"workdir": tempdir,
"variant": opts.variant,
"bugurl": opts.bugurl,
"updatesdir": opts.updates}
lorax = pylorax.Lorax(yb, **params)
lorax.run()
if __name__ == "__main__":
pylorax.launcher.main(sys.argv)
main(sys.argv)

File diff suppressed because it is too large Load Diff

143
src/pylorax/base.py Normal file
View File

@ -0,0 +1,143 @@
#
# base.py
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
from abc import ABCMeta, abstractmethod
import sys
import os
import shlex
import shutil
import config
import constants
import output
import ltmpl
from sysutils import *
class BaseLoraxClass(object):
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self):
self.conf = config.LoraxConfig()
self.const = constants.LoraxConstants()
self.cmd = constants.LoraxCommands()
self.output = output.LoraxOutput()
def pcritical(self, msg, file=sys.stdout):
self.output.critical(msg, file)
def perror(self, msg, file=sys.stdout):
self.output.error(msg, file)
def pwarning(self, msg, file=sys.stdout):
self.output.warning(msg, file)
def pinfo(self, msg, file=sys.stdout):
self.output.info(msg, file)
def pdebug(self, msg, file=sys.stdout):
self.output.debug(msg, file)
class BaseImageClass(BaseLoraxClass):
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self):
BaseLoraxClass.__init__(self)
self.srctree, self.dsttree = None, None
def parse_template(self, template_file, variables={}):
template = ltmpl.Template()
for lineno, line in template.parse(template_file, variables):
fields = shlex.split(line)
func, args = fields[0], fields[1:]
func = getattr(self, func, None)
if not func:
err = "{0}:{1}: invalid command: {2}"
err = err.format(template_file, lineno, line)
self.perror(err)
else:
try:
msg = "{0}({1})".format(func.__name__, ", ".join(args))
self.pdebug(msg)
func(*args)
except TypeError:
err = "{0}:{1}: invalid command syntax: {2}"
err = err.format(template_file, lineno, line)
self.perror(err)
def makedirs(self, *dirs):
for dir in dirs:
dir = os.path.join(self.dsttree, dir)
makedirs_(dir)
def remove(self, *fnames):
for fname in fnames:
fname = os.path.join(self.dsttree, fname)
remove_(fname)
def symlink(self, link_target, link_name):
link_name = os.path.join(self.dsttree, link_name)
symlink_(link_target, link_name)
def touch(self, fname):
fname = os.path.join(self.dsttree, fname)
touch_(fname)
def chown(self):
# TODO
raise NotImplementedError
def chmod(self):
# TODO
raise NotImplementedError
def replace(self):
# TODO
raise NotImplementedError
def copy(self, fname, target=None):
dstdir = os.path.dirname(fname)
if target:
dstdir = target
if dstdir:
makedirs_(os.path.join(self.dsttree, dstdir))
dcopy_(fname, dstdir, self.srctree, self.dsttree)
def rename(self, fname, target):
fname = os.path.join(self.dsttree, fname)
target = os.path.join(self.dsttree, target)
shutil.move(fname, target)
def edit(self, fname, text):
fname = os.path.join(self.dsttree, fname)
with open(fname, "w") as f:
f.write(text)

View File

@ -1,6 +1,5 @@
#
# config.py
# configuration classes for lorax
#
# Copyright (C) 2009 Red Hat, Inc.
#
@ -20,244 +19,24 @@
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import os
import singleton
from decorators import singleton
import output
class LoraxConfig(singleton.Singleton):
@singleton
class LoraxConfig(object):
def __init__(self):
self.confdir = "/etc/lorax"
self.datadir = "/usr/share/lorax"
# output settings
self.colors = True
self.encoding = "utf-8"
self.debug = False
self.cleanup = False
self.confdir = "/etc/lorax"
self.datadir = "/usr/share/lorax"
self.ignore_errors = "/etc/lorax/ignore_errors"
def __setattr__(self, attr, value):
output.Terminal.get().debug("[%s = %s]" % (attr, value))
singleton.Singleton.__setattr__(self, attr, value)
class LoraxPaths(singleton.Singleton):
def __init__(self):
self.datadir = LoraxConfig.get().datadir
self.installtree = LoraxConfig.get().installtree
@property
def ANACONDA_PACKAGE(self): return "anaconda"
@property
def INITRD_DATADIR(self):
return os.path.join(self.datadir, "initrd")
@property
def INSTALLTREE_DATADIR(self):
return os.path.join(self.datadir, "installtree")
@property
def OUTPUTDIR_DATADIR(self):
return os.path.join(self.datadir, "outputdir")
@property
def BOOTDIR(self):
return os.path.join(self.installtree, "boot")
@property
def BOOTDIR_IA64(self):
return os.path.join(self.BOOTDIR, "efi", "EFI", "redhat")
@property
def ANACONDA_RUNTIME(self):
return os.path.join(self.installtree, "usr", "lib", "anaconda-runtime")
@property
def ANACONDA_BOOT(self):
return os.path.join(self.ANACONDA_RUNTIME, "boot")
@property
def SYSLINUXDIR(self):
return os.path.join(self.installtree, "usr", "share", "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")
@property
def MKZIMAGE(self):
return os.path.join(self.installtree, "usr", "bin", "mkzimage")
@property
def ZIMAGE_STUB(self):
return os.path.join(self.installtree, "usr", "share", "ppc64-utils",
"zImage.stub")
@property
def ZIMAGE_LDS(self):
return os.path.join(self.installtree, "usr", "share", "ppc64-utils",
"zImage.lds")
@property
def WRAPPER(self):
return os.path.join(self.installtree, "usr", "sbin", "wrapper")
@property
def WRAPPER_A_DIR(self):
return os.path.join(self.installtree, "usr", "lib", "kernel-wrapper")
@property
def WRAPPER_A(self):
return os.path.join(self.WRAPPER_A_DIR, "wrapper.a")
@property
def BOOTINFO(self):
return os.path.join(self.ANACONDA_BOOT, "bootinfo.txt")
@property
def EFIKA_FORTH(self):
return os.path.join(self.ANACONDA_BOOT, "efika.forth")
@property
def OFBOOT(self):
return os.path.join(self.ANACONDA_BOOT, "ofboot.b")
@property
def YABOOT(self):
return os.path.join(self.installtree, "usr", "lib", "yaboot", "yaboot")
@property
def ADD_NOTE(self):
return os.path.join(self.installtree, "usr", "lib", "yaboot", "addnote")
@property
def BIARCH_YABOOT(self):
return os.path.join(self.ANACONDA_BOOT, "yaboot.conf.3264")
@property
def IMPLANTISO(self):
return "/usr/bin/implantisomd5"
output.LoraxOutput().debug("[set {0}={1}]".format(attr, value))
object.__setattr__(self, attr, value)

83
src/pylorax/constants.py Normal file
View File

@ -0,0 +1,83 @@
#
# constants.py
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
from os.path import join as pjoin
class LoraxConstants(object):
ROOT_UID = 0
ANACONDA_PACKAGE = "anaconda"
ANACONDA_RUNTIME = "usr/lib/anaconda-runtime"
ANACONDA_BOOTDIR = "usr/lib/anaconda-runtime/boot"
ANACONDA_LOADERDIR = "usr/lib/anaconda-runtime/loader"
BOOTDIR = "boot"
BOOTDIR_IA64 = "boot/efi/EFI/redhat"
EFIDIR = "boot/efi/EFI/redhat"
SPLASH = "boot/grub/splash.xpm.gz"
VESASPLASH = pjoin(ANACONDA_RUNTIME, "syslinux-vesa-splash.jpg")
SYSLINUXSPLASH = pjoin(ANACONDA_BOOTDIR, "syslinux-splash.jpg")
SPLASHTOOLS = pjoin(ANACONDA_RUNTIME, "splashtools.sh")
SPLASHLSS = pjoin(ANACONDA_BOOTDIR, "splash.lss")
VESAMENU = "usr/share/syslinux/vesamenu.c32"
MODDIR = "lib/modules"
FWDIR = "lib/firmware"
MODDEPFILE = "modules.dep"
MODULEINFO = "module-info"
MODLIST = "usr/lib/anaconda-runtime/modlist"
LOCALEDIR = "usr/lib/locale"
LOCALES = "usr/share/locale"
LANGTABLE = "usr/lib/anaconda/lang-table"
ISOLINUXBIN = "usr/share/syslinux/isolinux.bin"
SYSLINUXCFG = "usr/lib/anaconda-runtime/boot/syslinux.cfg"
LDSOCONF = "etc/ld.so.conf"
MANCONF = "etc/man.config"
class LoraxCommands(dict):
def __init__(self):
self["MODINFO"] = "/sbin/modinfo"
self["DEPMOD"] = "/sbin/depmod"
self["LOCALEDEF"] = "/usr/bin/localedef"
self["MKDOSFS"] = "/sbin/mkdosfs"
self["MKSQUASHFS"] = "/sbin/mksquashfs"
self["MKISOFS"] = "/usr/bin/mkisofs"
self["ISOHYBRID"] = "/usr/bin/isohybrid"
self["LOSETUP"] = "/sbin/losetup"
self["DMSETUP"] = "/sbin/dmsetup"
self["AWK"] = "/usr/bin/awk"
self["MOUNT"] = "/bin/mount"
self["UMOUNT"] = "/bin/umount"
self["LDCONFIG"] = "/sbin/ldconfig"
self["PARTED"] = "/sbin/parted"
def __getattr__(self, attr):
return self[attr]

View File

@ -1,6 +1,5 @@
#
# singleton.py
# singleton base class
# decorators.py
#
# Copyright (C) 2009 Red Hat, Inc.
#
@ -20,13 +19,12 @@
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
class Singleton(object):
def singleton(cls):
instances = {}
__instance = None
def get_instance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
@classmethod
def get(cls):
if cls.__instance is None:
cls.__instance = cls()
return cls.__instance
return get_instance

View File

@ -1,236 +0,0 @@
#
# efi.py
# class for creating efi images
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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
dstdir = os.path.join(efibootdir, "EFI", "BOOT")
utils.makedirs(dstdir)
utils.scopy(src_root=efitreedir, src_path="*",
dst_root=dstdir, 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 and splash.xpm.gz 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="")
shutil.copy2(self.paths.SPLASHXPM, self.conf.efibootdir)
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

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

@ -0,0 +1,865 @@
#
# images.py
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import sys
import os
import re
import shutil
import gzip
import commands
import tempfile
import math
import glob
import fnmatch
from base import BaseImageClass
from sysutils import *
class InitRD(BaseImageClass):
def __init__(self, installtree, modules, template_file, workdir="/tmp"):
BaseImageClass.__init__(self)
self.installtree = installtree
self.modules = modules
self.template_file = template_file
self.workdir = workdir
self.srctree = self.installtree.rootdir
self.dsttree = None
def create(self):
for kernel in self.installtree.kernels:
msg = ":: creating the initrd image for <b>{0}</b>"
msg = msg.format(kernel.filename)
self.pinfo(msg)
# prepare the working environment
self.pinfo("preparing the work environment")
self.prepare(kernel)
# get the kernel modules
self.pinfo("getting the kernel modules")
self.get_kernel_modules(kernel, self.modules)
# get keymaps
self.pinfo("creating keymaps")
ok = self.get_keymaps()
if not ok:
self.perror("could not create keymaps")
continue
# create locales
self.pinfo("creating locales")
ok = self.create_locales()
if not ok:
self.perror("could not create locales")
continue
# parse the template file
self.pinfo("parsing the template")
variables = {"buildarch": self.conf.buildarch,
"basearch": self.conf.basearch,
"libdir": self.conf.libdir}
self.parse_template(self.template_file, variables)
# create the initrd file
self.pinfo("compressing the initrd image file")
initrdfile = self.compress(kernel)
if not initrdfile:
self.perror("could not create the initrd image file")
continue
yield (kernel, initrdfile)
def prepare(self, kernel):
# create the initrd working directory
dir = os.path.join(self.workdir, "initrd-{0}".format(kernel.version))
if os.path.isdir(dir):
shutil.rmtree(dir)
os.mkdir(dir)
# set the destination tree
self.dsttree = dir
# copy the buildstamp
shutil.copy2(self.conf.buildstamp, self.dsttree)
# create the .profile
profile = os.path.join(self.dsttree, ".profile")
text = """PS1="[anaconda \u@\h \W]\\$ "
PATH=/bin:/usr/bin:/usr/sbin:/mnt/sysimage/sbin:/mnt/sysimage/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin
export PS1 PATH
"""
with open(profile, "w") as f:
f.write(text)
# XXX
def get_kernel_modules(self, kernel, modset):
moddir = os.path.join(self.const.MODDIR, kernel.version)
src_moddir = os.path.join(self.srctree, moddir)
dst_moddir = os.path.join(self.dsttree, moddir)
# copy all modules to the initrd tree
os.makedirs(os.path.dirname(dst_moddir))
shutil.copytree(src_moddir, dst_moddir)
# expand modules
modules = set()
pattern = re.compile(r"\.ko$")
for name in modset:
if name.startswith("="):
group = name[1:]
if group in ("scsi", "ata"):
p = os.path.join(src_moddir, "modules.block")
elif group == "net":
p = os.path.join(src_moddir, "modules.networking")
else:
p = os.path.join(src_moddir, "modules.{0}".format(group))
if os.path.isfile(p):
with open(p, "r") as f:
for line in f:
module = pattern.sub("", line.strip())
modules.add(module)
else:
modules.add(name)
# resolve modules dependencies
moddep = os.path.join(src_moddir, self.const.MODDEPFILE)
with open(moddep, "r") as f:
lines = map(lambda line: line.strip(), f.readlines())
modpattern = re.compile(r"^.*/(?P<name>.*)\.ko:(?P<deps>.*)$")
deppattern = re.compile(r"^.*/(?P<name>.*)\.ko$")
unresolved = True
while unresolved:
unresolved = False
for line in lines:
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:
unresolved = True
modules.add(depname)
# remove not needed modules
for root, dirs, files in os.walk(dst_moddir):
for file in files:
path = os.path.join(root, file)
name, ext = os.path.splitext(file)
if ext == ".ko":
if name not in modules:
os.unlink(path)
else:
# get the required firmware
cmd = "{0.MODINFO} -F firmware {1}"
cmd = cmd.format(self.cmd, path)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
continue
for fw in stdout.split():
fw = os.path.join(self.const.FWDIR, fw)
src = os.path.join(self.srctree, fw)
if not os.path.exists(src):
msg = "missing firmware {0}".format(fw)
self.pwarning(msg)
continue
# copy the firmware
dst = os.path.join(self.dsttree, fw)
dir = os.path.dirname(dst)
makedirs_(dir)
shutil.copy2(src, dst)
# copy additional firmware
fw = [("ipw2100", "ipw2100*"),
("ipw2200", "ipw2200*"),
("iwl3945", "iwlwifi-3945*"),
("iwl4965", "iwlwifi-4965*"),
("atmel", "atmel_*.bin"),
("zd1211rw", "zd1211"),
("qla2xxx", "ql*")]
for module, fname in fw:
if module in modules:
scopy_(src_root=self.srctree,
src_path=os.path.join(self.const.FWDIR, fname),
dst_root=self.dsttree,
dst_path=self.const.FWDIR)
# XXX
# remove empty directories
#empty_dirs = set()
#for root, dirs, files in os.walk(dst_moddir, topdown=False):
# if not dirs and not files:
# shutil.rmtree(root)
# get the modules paths
modpaths = {}
for root, dirs, files in os.walk(dst_moddir):
for file in files:
modpaths[file] = os.path.join(root, file)
# create the modules list
modlist = {}
for modtype, fname in {"scsi": "modules.block",
"eth": "modules.networking"}.items():
modlist[modtype] = {}
fname = os.path.join(dst_moddir, fname)
with open(fname, "r") as f:
for line in f:
line = line.strip()
if not line:
continue
modname, ext = os.path.splitext(line)
if (line not in modpaths or
modname in ("floppy", "libiscsi", "scsi_mod")):
continue
cmd = "{0.MODINFO} -F description {1}"
cmd = cmd.format(self.cmd, modpaths[line])
err, stdout = commands.getstatusoutput(cmd)
if err:
self.pwarning(stdout)
desc = ""
else:
desc = stdout.split("\n")[0]
desc = desc.strip()[:65]
if not desc:
desc = "{0} driver".format(modname)
info = '{0}\n\t{1}\n\t"{2}"\n'
info = info.format(modname, modtype, desc)
modlist[modtype][modname] = info
# write the source module-info
moduleinfo = os.path.join(self.workdir, self.const.MODULEINFO)
with open(moduleinfo, "w") as f:
f.write("Version 0\n")
for modtype, modules in modlist.items():
for modname in sorted(modules.keys()):
f.write(modlist[modtype][modname])
# create the final module-info
dst = os.path.join(os.path.dirname(dst_moddir), self.const.MODULEINFO)
modlist = os.path.join(self.srctree, self.const.MODLIST)
cmd = "{0} --modinfo-file {1} --ignore-missing --modinfo {2} > {3}"
cmd = cmd.format(modlist, moduleinfo, " ".join(list(modules)), dst)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
# remove the source module-info
#os.unlink(moduleinfo)
# run depmod
systemmap = os.path.join(self.srctree, self.const.BOOTDIR,
"System.map-{0}".format(kernel.version))
cmd = "{0.DEPMOD} -a -F {1} -b {2} {3}"
cmd = cmd.format(self.cmd, systemmap,
self.srctree, kernel.version)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
# compress modules
for root, dirs, files in os.walk(dst_moddir):
for file in filter(lambda f: f.endswith(".ko"), files):
path = os.path.join(root, file)
with open(path, "rb") as f:
data = f.read()
gzipped = gzip.open("{0}.gz".format(path), "wb")
gzipped.write(data)
gzipped.close()
os.unlink(path)
def get_keymaps(self):
override = "keymaps-override-{0}".format(self.conf.basearch)
override = os.path.join(self.srctree, self.const.ANACONDA_RUNTIME,
override)
getkeymaps = os.path.join(self.srctree, self.const.ANACONDA_RUNTIME,
"getkeymaps")
dst = os.path.join(self.dsttree, "etc/keymaps.gz")
dir = os.path.dirname(dst)
if not os.path.isdir(dir):
os.makedirs(dir)
if os.path.isfile(override):
self.pinfo("using keymaps override")
shutil.copy2(override, dst)
else:
cmd = "{0} {1} {2} {3}"
cmd = cmd.format(getkeymaps, self.conf.basearch, dst, self.srctree)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return False
return True
def create_locales(self):
localedir = os.path.join(self.dsttree, self.const.LOCALEDIR)
os.makedirs(localedir)
cmd = "{0.LOCALEDEF} -c -i en_US -f UTF-8 --prefix {1} en_US"
cmd = cmd.format(self.cmd, self.dsttree)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return False
return True
def compress(self, kernel):
filename = "initrd-{0}.img".format(kernel.version)
filepath = os.path.join(self.workdir, filename)
# create the cpio archive
cpioarchive = "{0}.cpio".format(filepath)
cwd = os.getcwd()
os.chdir(self.dsttree)
cmd = "find . | cpio --quiet -c -o > {0}".format(cpioarchive)
err, stdout = commands.getstatusoutput(cmd)
os.chdir(cwd)
if err:
self.perror(stdout)
return None
# create the gzip archive
with open(cpioarchive, "rb") as f:
cpiodata = f.read()
gzipped = gzip.open(filepath, "wb")
gzipped.write(cpiodata)
gzipped.close()
# remove the cpio archive
os.unlink(cpioarchive)
# remove the initrd tree
#shutil.rmtree(self.dsttree)
return filepath
class EFI(BaseImageClass):
def __init__(self, installtree, kernel, initrd, product, version,
workdir="/tmp"):
BaseImageClass.__init__(self)
self.srctree = installtree.rootdir
self.dsttree = None
self.kernel = kernel
self.initrd = initrd
self.product = product
self.version = version
self.workdir = workdir
def create(self):
msg = ":: creating the efi images for <b>{0}</b>"
self.pinfo(msg.format(self.kernel.filename))
# create efiboot image with kernel
self.pinfo("creating efiboot image with kernel")
efiboot_kernel = self.create_efiboot(with_kernel=True)
if efiboot_kernel is None:
self.perror("unable to create the efiboot image")
return None, None
# create the efidisk image
self.pinfo("creating efidisk image")
efidisk = self.create_efidisk(efiboot_kernel)
if efidisk is None:
self.perror("unable to create the efidisk image")
return None, None
# remove the efiboot image with kernel
os.unlink(efiboot_kernel)
# create efiboot image without kernel
self.pinfo("creating efiboot image without kernel")
efiboot_nokernel = self.create_efiboot(with_kernel=False)
if efiboot_nokernel is None:
self.perror("unable to create the efiboot image")
return None, None
return efiboot_nokernel, efidisk
def create_efiboot(self, with_kernel=True):
# create the efi tree directory
efitree = tempfile.mkdtemp(prefix="efitree.", dir=self.workdir)
efikernelpath = "/images/pxeboot/vmlinuz"
efiinitrdpath = "/images/pxeboot/initrd.img"
efisplashpath = "/EFI/BOOT/splash.xpm.gz"
# copy kernel and initrd files to efi tree directory
if with_kernel:
kpath = self.kernel.path
shutil.copy2(kpath, os.path.join(efitree, "vmlinuz"))
shutil.copy2(self.initrd, os.path.join(efitree, "initrd.img"))
efikernelpath = "/EFI/BOOT/vmlinuz"
efiinitrdpath = "/EFI/BOOT/initrd.img"
# copy conf files to efi tree directory
srcdir = os.path.join(self.srctree, self.const.ANACONDA_BOOTDIR)
scopy_(src_root=srcdir, src_path="*.conf",
dst_root=efitree, dst_path="")
# edit the grub.conf file
grubconf = os.path.join(efitree, "grub.conf")
replace_(grubconf, "@PRODUCT@", self.product)
replace_(grubconf, "@VERSION@", self.version)
replace_(grubconf, "@KERNELPATH@", efikernelpath)
replace_(grubconf, "@INITRDPATH@", efiinitrdpath)
replace_(grubconf, "@SPLASHPATH@", efisplashpath)
if self.conf.efiarch == "IA32":
shutil.copy2(grubconf, os.path.join(efitree, "BOOT.conf"))
dst = os.path.join(efitree, "BOOT{0}.conf".format(self.conf.efiarch))
shutil.move(grubconf, dst)
# copy grub.efi
grubefi = os.path.join(self.srctree, self.const.EFIDIR, "grub.efi")
if self.conf.efiarch == "IA32":
shutil.copy2(grubefi, os.path.join(efitree, "BOOT.efi"))
dst = os.path.join(efitree, "BOOT{0}.efi".format(self.conf.efiarch))
shutil.copy2(grubefi, dst)
# copy splash.xpm.gz
splash = os.path.join(self.srctree, self.const.SPLASH)
shutil.copy2(splash, efitree)
efiboot = os.path.join(self.workdir, "efiboot.img")
if os.path.isfile(efiboot):
os.unlink(efiboot)
# calculate the size of the efi tree directory
fsoverhead = 100 * 1024
sizeinbytes = fsoverhead
for root, dirs, files in os.walk(efitree):
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(math.ceil(sizeinbytes / 1024.0))
cmd = "{0.MKDOSFS} -n ANACONDA -C {1} {2} > /dev/null"
cmd = cmd.format(self.cmd, efiboot, size)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return None
# mount the efiboot image
efibootdir = tempfile.mkdtemp(prefix="efiboot.", dir=self.workdir)
cmd = "mount -o loop,shortname=winnt,umask=0777 -t vfat {0} {1}"
cmd = cmd.format(efiboot, efibootdir)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return None
# copy the files to the efiboot image
dstdir = os.path.join(efibootdir, "EFI/BOOT")
os.makedirs(dstdir)
scopy_(src_root=efitree, src_path="*",
dst_root=dstdir, dst_path="")
# unmount the efiboot image
cmd = "umount {0}".format(efibootdir)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.pwarning(stdout)
# remove the working directories
shutil.rmtree(efibootdir)
#shutil.rmtree(efitree)
# XXX copy the conf files and splash.xpm.gz to the output directory
if not with_kernel:
scopy_(src_root=efitree, src_path="*.conf",
dst_root=self.conf.efidir, dst_path="")
shutil.copy2(splash, self.conf.efidir)
return efiboot
def create_efidisk(self, efiboot):
efidisk = os.path.join(self.workdir, "efidisk.img")
if os.path.isfile(efidisk):
os.unlink(efidisk)
partsize = os.path.getsize(efiboot)
disksize = 17408 + partsize + 17408
disksize = disksize + (disksize % 512)
# create the efidisk file
with open(efidisk, "wb") as f:
f.truncate(disksize)
# create the loop device
cmd = "{0.LOSETUP} -v -f {1} | {0.AWK} '{{print $4}}'"
cmd = cmd.format(self.cmd, efidisk)
err, loop = commands.getstatusoutput(cmd)
if err:
self.perror(loop)
os.unlink(efidisk)
return None
# create the dm device
dmdev = "efiboot"
cmd = '{0.DMSETUP} create {1} --table "0 {2} linear {3} 0"'
cmd = cmd.format(self.cmd, dmdev, disksize / 512, loop)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(output)
self.remove_loop_dev(loop)
os.unlink(efidisk)
return None
cmd = ("{0.PARTED} --script /dev/mapper/{1} "
"mklabel gpt unit b mkpart '\"EFI System Partition\"' "
"fat32 17408 {2} set 1 boot on")
cmd = cmd.format(self.cmd, dmdev, partsize + 17408)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
self.remove_dm_dev(dmdev)
self.remove_loop_dev(loop)
os.unlink(efidisk)
return None
with open(efiboot, "rb") as f_from:
with open("/dev/mapper/{0}p1".format(dmdev), "wb") as f_to:
efidata = f_from.read(1024)
while efidata:
f_to.write(efidata)
efidata = f_from.read(1024)
self.remove_dm_dev("{0}p1".format(dmdev))
self.remove_dm_dev(dmdev)
self.remove_loop_dev(loop)
return efidisk
def remove_loop_dev(self, dev):
cmd = "{0.LOSETUP} -d {1}".format(self.cmd, dev)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.pwarning(stdout)
def remove_dm_dev(self, dev):
cmd = "{0.DMSETUP} remove /dev/mapper/{1}".format(self.cmd, dev)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.pwarning(stdout)
class Install(BaseImageClass):
def __init__(self, installtree, template_file, workdir="/tmp"):
BaseImageClass.__init__(self)
self.srctree = installtree.rootdir
self.dsttree = installtree.rootdir
self.template_file = template_file
self.workdir = workdir
def create(self, type="squashfs"):
self.pinfo(":: creating the install image")
# copy the .buildstamp
shutil.copy2(self.conf.buildstamp, self.srctree)
self.copy_stubs()
self.copy_bootloaders()
self.rename_repos()
self.move_anaconda_files()
self.create_modules_symlinks()
self.fix_man_pages()
self.remove_locales()
self.remove_unnecessary_files()
self.move_bins()
# parse the template file
self.pinfo("parsing the template")
variables = {"buildarch": self.conf.buildarch,
"basearch": self.conf.basearch,
"libdir": self.conf.libdir}
self.parse_template(self.template_file, variables)
installimg = os.path.join(self.workdir, "install.img")
if os.path.isfile(installimg):
os.unlink(installimg)
if type == "squashfs":
self.pinfo("using squash filesystem")
cmd = "{0.MKSQUASHFS} {1} {2} -all-root -no-fragments -no-progress"
cmd = cmd.format(self.cmd, self.srctree, installimg)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return None
elif type == "cramfs":
# TODO
raise NotImplementedError
elif type == "ext2":
# TODO
raise NotImplementedError
return installimg
def copy_stubs(self):
stubs = ("raidstart", "raidstop", "losetup", "list-harddrives",
"loadkeys", "mknod", "syslogd")
for stub in map(lambda s: "{0}-stub".format(s), stubs):
src = os.path.join(self.srctree, "usr/lib/anaconda", stub)
dst = os.path.join(self.srctree, "usr/bin", stub)
shutil.copy2(src, dst)
def copy_bootloaders(self):
srcdir = os.path.join(self.srctree, self.const.BOOTDIR)
dstdir = os.path.join(self.srctree, self.const.ANACONDA_BOOTDIR)
if self.conf.buildarch in ("i386", "i586", "i686", "x86_64"):
for f in glob.iglob(os.path.join(srcdir, "memtest*")):
shutil.copy2(f, dstdir)
elif self.conf.buildarch in ("ppc", "ppc64"):
f = os.path.join(srcdir, "efika.forth")
shutil.copy2(f, dstdir)
elif self.conf.buildarch in ("sparc", "sparc64"):
for f in glob.iglob(os.path.join(srcdir, "*.b")):
shutil.copy2(f, dstdir)
elif self.conf.buildarch == "ia64":
srcdir = os.path.join(self.srctree, self.const.BOOTDIR_IA64)
for f in glob.iglob(os.path.join(srcdir, "*")):
shutil.copy2(dstdir)
def rename_repos(self):
src = os.path.join(self.srctree, "etc/yum.repos.d")
dst = os.path.join(self.srctree, "etc/anaconda.repos.d")
shutil.move(src, dst)
def move_anaconda_files(self):
# move anaconda executable
src = os.path.join(self.srctree, "usr/sbin/anaconda")
dst = os.path.join(self.srctree, "usr/bin/anaconda")
shutil.move(src, dst)
# move anaconda libraries
srcdir = os.path.join(self.srctree, self.const.ANACONDA_RUNTIME)
dstdir = os.path.join(self.srctree, "usr", self.conf.libdir)
for f in glob.iglob(os.path.join(srcdir, "lib*")):
shutil.move(f, dstdir)
def create_modules_symlinks(self):
mkdir_(os.path.join(self.srctree, "modules"))
mkdir_(os.path.join(self.srctree, "firmware"))
remove_(os.path.join(self.srctree, self.const.MODDIR))
remove_(os.path.join(self.srctree, self.const.FWDIR))
os.symlink("/modules", os.path.join(self.srctree, self.const.MODDIR))
os.symlink("/firmware", os.path.join(self.srctree, self.const.FWDIR))
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.srctree, "usr/bin", file)
if not os.path.isfile(name):
os.symlink(target, name)
# fix /etc/man.config to point into /mnt/sysimage
manconf = os.path.join(self.srctree, self.const.MANCONF)
replace_(manconf, r"^MANPATH\s+(\S+)", "MANPATH\t/mnt/sysimage\g<1>")
replace_(manconf, r"^MANPATH_MAP\s+(\S+)\s+(\S+)",
"MANPATH_MAP\t\g<1>\t/mnt/sysimage\g<2>")
def remove_locales(self):
langtable = os.path.join(self.srctree, self.const.LANGTABLE)
localepath = os.path.join(self.srctree, self.const.LOCALES)
if os.path.isfile(langtable):
keep = set()
with open(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(localepath, fields[1])
if os.path.isdir(dir):
keep.add(fields[1])
locale = fields[3].split(".")[0]
dir = os.path.join(localepath, locale)
if os.path.isdir(dir):
keep.add(locale)
for locale in os.listdir(localepath):
if locale not in keep:
path = os.path.join(localepath, locale)
remove_(path)
def remove_unnecessary_files(self):
for root, dirs, files in os.walk(self.srctree):
for file in files:
path = os.path.join(root, file)
if (fnmatch.fnmatch(path, "*.a") and
not path.count("kernel-wrapper/wrapper.a")):
os.unlink(path)
if (fnmatch.fnmatch(path, "lib*.la") and
not path.count("gtk-2.0")):
os.unlink(path)
if fnmatch.fnmatch(path, "*.py"):
pyo, pyc = path + "o", path + "c"
if os.path.isfile(pyo):
os.unlink(pyo)
if os.path.isfile(pyc):
os.unlink(pyc)
os.symlink("/dev/null", pyc)
# remove libunicode-lite
remove_(os.path.join(self.srctree, "usr", self.conf.libdir,
"libunicode-lite*"))
def move_bins(self):
# move bin to usr/bin
scopy_(src_root=self.srctree, src_path="bin/*",
dst_root=self.srctree, dst_path="usr/bin")
remove_(os.path.join(self.srctree, "bin"))
# move sbin to /usr/sbin
scopy_(src_root=self.srctree, src_path="sbin/*",
dst_root=self.srctree, dst_path="usr/sbin")
remove_(os.path.join(self.srctree, "sbin"))
# fix broken links
brokenlinks = []
for dir in ("bin", "sbin"):
dir = os.path.join(self.srctree, "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)
pattern = re.compile(r"^\.\./\.\./(bin|sbin)/(.*)$")
for link in brokenlinks:
target = os.readlink(link)
newtarget = pattern.sub(r"../\g<1>/\g<2>", target)
if newtarget != target:
os.unlink(link)
os.symlink(newtarget, link)
class Boot(BaseImageClass):
def __init__(self, product, workdir="/tmp"):
BaseImageClass.__init__(self)
self.product = product
self.workdir = workdir
self.efiboot = os.path.join(self.conf.imgdir, "efiboot.img")
def create(self):
self.pinfo(":: creating the boot iso image")
bootiso = os.path.join(self.workdir, "boot.iso")
if os.path.isfile(bootiso):
os.unlink(bootiso)
if os.path.isfile(self.efiboot):
self.pinfo("creating efi capable boot iso")
efiargs = "-eltorito-alt-boot -e images/efiboot.img -no-emul-boot"
efigraft = "EFI/BOOT={0}".format(self.conf.efidir)
else:
efiargs = ""
efigraft = ""
cmd = ("{0.MKISOFS} -U -A {1} -V {1} -volset {1} -J -joliet-long"
" -r -v -T -o {2} -b isolinux/isolinux.bin -c isolinux/boot.cat"
" -no-emul-boot -boot-load-size 4 -boot-info-table"
" {3} -graft-points isolinux={4} images={5} {6}")
cmd = cmd.format(self.cmd, self.product, bootiso, efiargs,
self.conf.isodir, self.conf.imgdir, efigraft)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return None
if os.path.isfile(self.cmd.ISOHYBRID):
self.pinfo("creating hybrid boot iso")
cmd = "{0.ISOHYBRID} {1}".format(self.cmd, bootiso)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.pwarning(stdout)
return bootiso

View File

@ -1,502 +0,0 @@
#
# install.py
# class for creating install images
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): David Cantrell <dcantrell@redhat.com>
# Martin Gracik <mgracik@redhat.com>
#
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)
# XXX i cannot find this in the repos for f12
def configure_fedorakmod(self):
if os.path.isfile(self.paths.FEDORAKMODCONF):
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):
pass
# # 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

149
src/pylorax/insttree.py Normal file
View File

@ -0,0 +1,149 @@
#
# insttree.py
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import os
import re
import commands
from base import BaseLoraxClass
from sysutils import *
class Kernel(object):
pass
class InstallTree(BaseLoraxClass):
def __init__(self, yum, rootdir, updatesdir=None):
BaseLoraxClass.__init__(self)
self.yum = yum
self.rootdir = rootdir
self.updatesdir = updatesdir
self.kpattern = re.compile(r"vmlinuz-(?P<ver>[-.0-9a-z]+?"
r"(?P<pae>(PAE)?)(?P<xen>(xen)?))$")
def install_packages(self, packages):
for name in packages:
if not self.yum.install(name):
self.pwarning("no package <b>{0}</b> found".format(name))
self.yum.process_transaction()
self.run_ldconfig()
def run_ldconfig(self):
ldsoconf = os.path.join(self.rootdir, self.const.LDSOCONF)
# XXX
with open(ldsoconf, "w") as f:
f.write("/usr/kerberos/{0}\n".format(self.conf.libdir))
procdir = os.path.join(self.rootdir, "proc")
mkdir_(procdir)
# mount proc
cmd = "{0.MOUNT} -t proc proc {1}".format(self.cmd, procdir)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.perror(stdout)
return
cwd = os.getcwd()
# chroot to the install tree directory, and run ldconfig
pid = os.fork()
if pid:
# parent
os.waitpid(pid, 0)
else:
# child
os.chroot(self.rootdir)
os.chdir("/")
err, stdout = commands.getstatusoutput(self.cmd.LDCONFIG)
if err:
self.perror(stdout)
os._exit(0)
os.chdir(cwd)
# umount proc
cmd = "{0.UMOUNT} {1}".format(self.cmd, procdir)
err, stdout = commands.getstatusoutput(cmd)
if err:
self.pwarning(stdout)
# XXX
os.unlink(ldsoconf)
def copy_updates(self):
if self.updatesdir and os.path.isdir(self.updatesdir):
scopy_(src_root=self.updatesdir, src_path="*",
dst_root=self.rootdir, dst_path="")
@property
def kernels(self):
if self.conf.buildarch == "ia64":
kerneldir = self.const.BOOTDIR_IA64
else:
kerneldir = self.const.BOOTDIR
self.kerneldir = os.path.join(self.rootdir, kerneldir)
for filename in os.listdir(self.kerneldir):
m = self.kpattern.match(filename)
if m:
kernel = Kernel()
kernel.filename = filename
kernel.path = os.path.join(self.kerneldir, filename)
kernel.version = m.group("ver")
kernel.is_pae = bool(m.group("pae"))
kernel.is_xen = bool(m.group("xen"))
yield kernel
@property
def do_efi(self):
return os.path.isdir(os.path.join(self.rootdir, self.const.EFIDIR))
# XXX this should be just a temporary fix,
# should get fixed in the respective packages
def fix_problems(self):
# remove broken build and source links from the modules directory
for kernel in self.kernels:
moddir = os.path.join(self.rootdir, self.const.MODDIR,
kernel.version)
build = os.path.join(moddir, "build")
if os.path.islink(build) and not os.path.exists(build):
os.unlink(build)
source = os.path.join(moddir, "source")
if os.path.islink(source) and not os.path.exists(source):
os.unlink(source)
# fix udev broken links
for fname in ("udevcontrol", "udevsettle", "udevtrigger"):
fname = os.path.join(self.rootdir, "sbin", fname)
if os.path.islink(fname):
os.unlink(fname)
os.symlink("udevadm", fname)

View File

@ -1,224 +0,0 @@
#
# launcher.py
# functions for the command line launcher
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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

View File

@ -1,76 +0,0 @@
#
# __init__.py
# lorax control system classes
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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

View File

@ -1,49 +0,0 @@
#
# __init__.py
# function for loading action modules
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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

View File

@ -1,55 +0,0 @@
#
# base.py
# base lorax control system action 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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")

View File

@ -1,300 +0,0 @@
#
# file.py
# lcs file 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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<filename>.*?)$"
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<src_root>.*?)\s(?P<src_path>.*?)\sto\s" \
"(?P<dst_root>.*?)\s(?P<dst_path>.*?)" \
"(\s(?P<nosymlinks>nosymlinks))?$"
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<name>.*?)\starget\s(?P<target>.*?)$"
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<filename>.*?)$"
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<dir>.*?)(\smode\s(?P<mode>.*?))?$"
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<filename>.*?)\suser\s(?P<user>.*?)" \
"\sgroup\s(?P<group>.*?)(\s(?P<recursive>recursive))?$"
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<filename>.*?)\smode\s(?P<mode>[0-7]*?)" \
"(\s(?P<recursive>recursive))?$"
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<filename>.*?)\stext\s"(?P<text>.*?)"' \
'(\s(?P<append>append))?$'
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<filename>.*?)\sfind\s"(?P<find>.*?)"' \
'\sreplace\s"(?P<replace>.*?)"$'
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"]

View File

@ -1,57 +0,0 @@
#
# ssh.py
# lcs ssh 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import commands
from base import LCSAction
import pylorax.utils as utils
COMMANDS = { "gensshkey" : "GenerateSSHKey" }
class GenerateSSHKey(LCSAction):
REGEX = r"^(?P<filename>.*?)\stype\s(?P<type>.*?)$"
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"]

39
src/pylorax/ltmpl.py Normal file
View File

@ -0,0 +1,39 @@
#
# ltmpl.py
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
from mako.template import Template as MakoTemplate
from mako.lookup import TemplateLookup as MakoTemplateLookup
class Template(object):
def parse(self, template_file, variables):
# we have to set the template lookup directories to ["/"],
# otherwise the file includes will not work properly
lookup = MakoTemplateLookup(directories=["/"])
template = MakoTemplate(filename=template_file, lookup=lookup)
s = template.render(**variables)
# enumerate, strip and remove empty lines
lines = enumerate(s.splitlines(), start=1)
lines = map(lambda (n, line): (n, line.strip()), lines)
lines = filter(lambda (n, line): line, lines)
return lines

View File

@ -1,6 +1,5 @@
#
# output.py
# output control
#
# Copyright (C) 2009 Red Hat, Inc.
#
@ -21,100 +20,127 @@
#
import sys
import singleton
import re
from decorators import singleton
### color codes
C_DEFAULT = "\x1b[39m"
C_RESET = "\x1b[0m"
# color codes
C_DEFAULT = "\x1b[39m"
C_RESET = "\x1b[0m"
C_BLACK = "\x1b[0;30m"
C_WHITE = "\x1b[1;37m"
C_RED = "\x1b[0;31m"
C_GREEN = "\x1b[0;32m"
C_BLUE = "\x1b[0;34m"
C_LIGHTRED = "\x1b[1;31m"
C_LIGHTGREEN = "\x1b[1;32m"
C_LIGHTBLUE = "\x1b[1;34m"
C_BLACK = "\x1b[0;30m"
C_WHITE = "\x1b[1;37m"
C_RED = "\x1b[0;31m"
C_GREEN = "\x1b[0;32m"
C_BLUE = "\x1b[0;34m"
C_LIGHTRED = "\x1b[1;31m"
C_LIGHTGREEN = "\x1b[1;32m"
C_LIGHTBLUE = "\x1b[1;34m"
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
C_BOLD = "\x1b[1m"
C_UNDERLINE = "\x1b[4m"
class Terminal(singleton.Singleton):
# format tags
TAGS = [(re.compile(r"<b>"), C_BOLD),
(re.compile(r"<u>"), C_UNDERLINE),
(re.compile(r"<red>"), C_RED),
(re.compile(r"<green>"), C_GREEN),
(re.compile(r"<blue>"), C_BLUE),
(re.compile(r"</(b|u|red|green|blue)>"), C_RESET)]
# output levels
CRITICAL = 50
ERROR = 40
WARNING = 30
INFO = 20
DEBUG = 10
NOTSET = 0
@singleton
class LoraxOutput(object):
def __init__(self):
self.__colors = True
self.__encoding = "utf-8"
self.__output_level = INFO
self.__indent_level = 0
self._colors = True
self._encoding = "utf-8"
self._output_level = INFO
self._indent_level = 0
def basic_config(self, colors=None, encoding=None, level=None):
self._ignore_errors = set()
def basic_config(self, colors=None, encoding=None, output_level=None):
if colors is not None:
self.__colors = colors
self._colors = colors
if encoding is not None:
self.__encoding = encoding
self._encoding = encoding
if level is not None:
self.__output_level = level
if output_level is not None:
self._output_level = output_level
@property
def ignore(self):
return self._ignore_errors
@ignore.setter
def ignore(self, errors):
self._ignore_errors = errors
def indent(self):
self.__indent_level += 1
self._indent_level += 1
def unindent(self):
if self.__indent_level > 0:
self.__indent_level -= 1
if self._indent_level > 0:
self._indent_level -= 1
def write(self, s, file=sys.stdout):
if self._colors:
s = self.__format(s)
else:
s = self.__raw(s)
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 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, file=sys.stdout):
s = "%s%s" % (" " * self.__indent_level, s)
self.write(s + "\n", color=color, type=type, file=file)
def writeline(self, s, file=sys.stdout):
s = "{0}{1}\n".format(" " * self._indent_level, s)
self.write(s, file=file)
def critical(self, s, file=sys.stdout):
if self.__output_level <= CRITICAL:
self.writeline("** critical: %s" % s, file=file)
s = "** critical: {0}".format(s)
if (self._output_level <= CRITICAL and
self.__raw(s) not in self.ignore):
self.writeline(s, file=file)
def error(self, s, file=sys.stdout):
if self.__output_level <= ERROR:
self.writeline("** error: %s" % s, file=file)
s = "** error: {0}".format(s)
if (self._output_level <= ERROR and
self.__raw(s) not in self.ignore):
self.writeline(s, file=file)
def warning(self, s, file=sys.stdout):
if self.__output_level <= WARNING:
self.writeline("** warning: %s" % s, file=file)
s = "** warning: {0}".format(s)
if (self._output_level <= WARNING and
self.__raw(s) not in self.ignore):
self.writeline(s, file=file)
def info(self, s, file=sys.stdout):
if self.__output_level <= INFO:
if self._output_level <= INFO:
self.writeline(s, file=file)
def debug(self, s, file=sys.stdout):
if self.__output_level <= DEBUG:
if self._output_level <= DEBUG:
self.writeline(s, file=file)
def __raw(self, s):
for tag, ccode in TAGS:
s = tag.sub("", s)
return s
def __format(self, s):
for tag, ccode in TAGS:
s = tag.sub(ccode, s)
return s

View File

@ -1,522 +0,0 @@
#
# ramdisk.py
# class for creating init ramdisk
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
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:
self.output.debug(str(action))
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<name>.*)\.ko:(?P<deps>.*)$")
deppattern = re.compile(r"^.*/(?P<name>.*)\.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,
ignore_errors=True)
# 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.basearch, 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 create_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" % (
self.paths.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 create_s390x(self):
return self.create_s390()
# XXX this should be removed
def create_alpha(self):
raise NotImplementedError
def create_ia64(self):
raise NotImplementedError
def create_ppc(self):
if self.conf.arch == "ppc":
bits = "32"
elif self.conf.arch == "ppc64":
bits = "64"
ppc_dir = os.path.join(self.conf.outputdir, "ppc", "ppc%s" % bits)
utils.makedirs(ppc_dir)
if self.conf.arch == "ppc":
mac_dir = os.path.join(self.conf.outputdir, "ppc", "mac")
utils.makedirs(mac_dir)
initrd_filename = os.path.join(ppc_dir, "ramdisk.image.gz")
self.compress(initrd_filename)
kernel_filename = os.path.join(ppc_dir, "vmlinuz")
shutil.copy2(self.conf.kernelfile, kernel_filename)
yaboot_src = os.path.join(self.paths.ANACONDA_BOOT, "yaboot.conf.in")
yaboot_dst = os.path.join(ppc_dir, "yaboot.conf")
shutil.copy2(yaboot_src, yaboot_dst)
utils.replace(yaboot_dst, "%BITS%", bits)
utils.replace(yaboot_dst, "%PRODUCT%", self.conf.product)
utils.replace(yaboot_dst, "%VERSION%", self.conf.version)
text = """[images-%s]
kernel = ppc/ppc%s/vmlinuz
initrd = ppc/ppc%s/ramdisk.image.gz
""" % (self.conf.arch, bits, bits)
utils.edit(self.conf.treeinfo, append=True, text=text)
netboot_dir = os.path.join(self.conf.imagesdir, "netboot")
utils.makedirs(netboot_dir)
ppc_img = os.path.join(netboot_dir, "ppc%s.img" % bits)
if os.path.exists(self.paths.MKZIMAGE) and \
os.path.exists(self.paths.ZIMAGE_STUB):
shutil.copy2(self.paths.ZIMAGE_LDS, ppc_dir)
cmd = "%s %s no no %s %s %s" % \
(self.paths.MKZIMAGE, kernel_filename, initrd_filename,
self.paths.ZIMAGE_STUB, ppc_img)
err, output = commands.getstatusoutput(cmd)
if err:
self.output.warning(output)
utils.remove(os.path.join(ppc_dir, "zImage.lds"))
elif os.path.exists(self.paths.WRAPPER) and \
os.path.exists(self.paths.WRAPPER_A):
cmd = "%s -o %s -i %s -D %s %s" % \
(self.paths.WRAPPER, ppc_img, initrd_filename,
self.paths.WRAPPER_A_DIR, kernel_filename)
err, output = commands.getstatusoutput(cmd)
if err:
self.output.warning(output)
if os.path.exists(ppc_img):
text = "zimage = images/netboot/ppc%s.img" % bits
utils.edit(self.conf.treeinfo, append=True, text=text)
else:
utils.remove(netboot_dir)
return None, None
def create_ppc64(self):
return create_ppc()

View File

@ -1,6 +1,5 @@
#
# utils.py
# file utilities
# sysutils.py
#
# Copyright (C) 2009 Red Hat, Inc.
#
@ -20,6 +19,10 @@
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
__all__ = ["mkdir_", "makedirs_", "remove_", "symlink_", "touch_",
"chown_", "chmod_", "replace_", "scopy_", "dcopy_"]
import sys
import os
import shutil
@ -31,103 +34,52 @@ import grp
import commands
def expand_path(path, globs=True):
l = []
m = re.match(r"(?P<prefix>.*){(?P<expand>.*?)}(?P<suffix>.*)", 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:
# XXX are there any other chars in globs?
if globs and (path.find("*") != -1 or path.find("?") != -1):
l.extend(glob.glob(path))
else:
l.append(path)
return l
class SysUtilsError(Exception):
pass
def remove(file):
for fname in expand_path(file):
class SmartCopyError(SysUtilsError):
pass
class LinkerError(SysUtilsError):
pass
def mkdir_(dir):
if not os.path.isdir(dir):
os.mkdir(dir)
def makedirs_(dir):
if not os.path.isdir(dir):
os.makedirs(dir)
def remove_(path):
for fname in glob.iglob(path):
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):
def symlink_(link_target, link_name, force=True):
if force and (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)
def touch_(fname):
if os.path.exists(fname):
os.utime(fname, None)
else:
with open(file, "w") as f:
with open(fname, "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
def chown_(path, user=None, group=None, recursive=False):
uid = gid = -1
if user is not None:
@ -135,56 +87,88 @@ def chown(file, user=None, group=None, recursive=False):
if group is not None:
gid = grp.getgrnam(group)[2]
for fname in expand_path(file):
for fname in glob.iglob(path):
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)
chown_(nested, user, group, recursive)
def chmod(file, mode, recursive=False):
for fname in expand_path(file):
def chmod_(path, mode, recursive=False):
for fname in glob.iglob(path):
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)
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)
def replace_(fname, find, replace):
fin = fileinput.input(fname, inplace=1)
pattern = re.compile(find)
for line in fin:
line = re.sub(find, replace, line)
line = pattern.sub(replace, line)
sys.stdout.write(line)
fin.close()
class SmartCopyError(Exception):
pass
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, deps=False, ignore_errors=ignore_errors)
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, deps=True, ignore_errors=ignore_errors)
def __copy(src_path, dst_path, src_root="/", dst_root="/",
symlinks=True, deps=False, ignore_errors=False):
if not src_root.endswith("/"):
src_root += "/"
if not dst_root.endswith("/"):
dst_root += "/"
smartcopy = SmartCopy(src_root, dst_root, symlinks, deps, ignore_errors)
src = os.path.join(src_root, src_path)
pattern = re.compile(r"(\*|\?|\[.*?\])")
if pattern.search(src):
fnames = glob.glob(src)
else:
fnames = [src]
if not fnames and not ignore_errors:
err_msg = "cannot stat '{0}': No such file or directory"
raise SysUtilsError(err_msg.format(src))
for fname in fnames:
fname = fname.replace(src_root, "", 1)
smartcopy.copy(fname, dst_path)
smartcopy.process()
# XXX
class SmartCopy(object):
def __init__(self, src_root="/", dst_root="/", symlinks=True,
def __init__(self, src_root="/", dst_root="/", symlinks=True, deps=False,
ignore_errors=False):
self.src_root = src_root
self.dst_root = dst_root
self.symlinks = symlinks
self.deps = deps
self.ignore_errors = ignore_errors
self.linker = Linker(src_root)
@ -201,14 +185,15 @@ class SmartCopy(object):
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
# check if the source path exists
if not os.path.exists(src):
err_msg = "cannot stat '%s': No such file or directory" % src
err_msg = "cannot stat '{0}': No such file or directory"
err_msg = err_msg.format(src)
if not self.ignore_errors:
raise SmartCopyError(err_msg)
else:
self.errors.append(err_msg)
return # EXIT
return
if os.path.isfile(src):
self.__copy_file(src_path, dst_path, src, dst)
@ -217,32 +202,23 @@ class SmartCopy(object):
def __copy_file(self, src_path, dst_path, src, dst):
# if destination is an existing directory,
# append the source filename to the destination path
# append the source filename to the destination
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
err_msg = "cannot overwrite directory '{0}' with non-directory"
err_msg = err_msg.format(dst)
if not self.ignore_errors:
raise SmartCopyError(err_msg)
else:
self.errors.append(err_msg)
return # EXIT
return
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)
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):
@ -250,60 +226,47 @@ class SmartCopy(object):
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/"
# remove the trailing "/"
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)
self.__copy_link(src_path, dst_path, src, new_dst, dir=True)
else:
# create the destination directory, if it does not exist
if not os.path.exists(new_dst) and \
new_dst not in self.makedirs:
# create the destination directory
if not os.path.isdir(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
err_msg = "cannot overwrite file '{0}' with directory"
err_msg = err_msg.format(new_dst)
if not self.ignore_errors:
raise SmartCopyError(err_msg)
else:
self.errors.append(err_msg)
return # EXIT
return
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)
err_msg = "cannot list directory '{0}': {1}'"
err_msg = err_msg.format(src, why)
if not self.ignore_errors:
raise SmartCopyError(err_msg)
else:
self.errors.append(err_msg)
return # EXIT
return
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):
def __copy_link(self, src_path, dst_path, src, dst, dir=False):
if not self.symlinks:
# TODO
raise NotImplementedError
# read the link target
link_target = os.readlink(src)
@ -320,10 +283,9 @@ class SmartCopy(object):
if target_dst_dir.endswith("/"):
target_dst_dir = target_dst_dir[:-1]
# create the destination directory, if it doesn't exist
# create the destination directory
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:
if not os.path.isdir(target_dst) and target_dst not in self.makedirs:
self.makedirs.append(target_dst)
# copy the target along with the link
@ -332,7 +294,7 @@ class SmartCopy(object):
# create the symlink named dst, pointing to link_target
self.links.add((link_target, dst))
def get_deps(self):
def __get_deps(self):
deps = set()
for src, dst in self.copyfiles:
@ -345,78 +307,84 @@ class SmartCopy(object):
# 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:
if not os.path.isdir(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)
if self.deps:
self.__get_deps()
# copy all the files
# create required directories
map(makedirs_, self.makedirs)
# 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)
# copy all the files
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
map(lambda (target, name): symlink_(target, name), self.links)
# XXX
class Linker(object):
LIBDIRS = ( "lib64",
"usr/lib64",
"lib",
"usr/lib" )
LIBDIRS = ("lib64",
"usr/lib64",
"lib",
"usr/lib")
LDDBIN = "/usr/bin/ldd"
FILEBIN = "/usr/bin/file"
def __init__(self, root="/"):
libdirs = map(lambda path: os.path.join(root, path), self.LIBDIRS)
libdirs = ":".join(libdirs)
ld_linux = None
pattern = re.compile(r"^RTLDLIST=(?P<ld_linux>.*)$")
with open("/usr/bin/ldd", "r") as f:
with open(self.LDDBIN, "r") as f:
for line in f:
m = re.match(r"^RTLDLIST=(?P<ld_linux>.*)$", line.strip())
m = pattern.match(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")
raise LinkerError("cannot 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<lib>[a-zA-Z0-9.-_/]*)" \
r"\s\(0x[0-9a-f]*\)$")
self.lddcmd = "LD_LIBRARY_PATH={0} {1} --list"
self.lddcmd = self.lddcmd.format(libdirs, ld_linux)
def is_elf(self, file):
err, output = commands.getstatusoutput("file --brief %s" % file)
self.pattern = re.compile(r"^[-._/a-zA-Z0-9]+\s=>\s"
r"(?P<lib>[-._/a-zA-Z0-9]+)"
r"\s\(0x[0-9a-f]+\)$")
def is_elf(self, fname):
cmd = "{0} --brief {1}".format(self.FILEBIN, fname)
err, stdout = commands.getstatusoutput(cmd)
if err:
raise LinkerError("error getting the file type")
raise LinkerError(stdout)
if not output.startswith("ELF"):
if not stdout.count("ELF"):
return False
return True
def get_deps(self, file):
err, output = commands.getstatusoutput("%s %s" % (self.lddcmd, file))
def get_deps(self, fname):
cmd = "{0} {1}".format(self.lddcmd, fname)
err, stdout = commands.getstatusoutput(cmd)
if err:
raise LinkerError("error getting the file dependencies")
raise LinkerError(stdout)
deps = set()
for line in output.splitlines():
for line in stdout.splitlines():
m = self.pattern.match(line.strip())
if m:
deps.add(m.group("lib"))

110
src/pylorax/yumbase.py Normal file
View File

@ -0,0 +1,110 @@
#
# yumbase.py
#
# 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 <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import os
import ConfigParser
import yum
def get_yum_base_object(installroot, repositories, mirrorlists=[],
tempdir="/tmp"):
def sanitize_repo(repo):
if repo.startswith("/"):
return "file://{0}".format(repo)
elif repo.startswith("http://") or repo.startswith("ftp://"):
return repo
else:
return None
# sanitize the repositories
repositories = map(sanitize_repo, repositories)
mirrorlists = map(sanitize_repo, mirrorlists)
# remove invalid repositories
repositories = filter(bool, repositories)
mirrorlists = filter(bool, mirrorlists)
cachedir = os.path.join(tempdir, "yum.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-{0:d}".format(n)
data = {"name": "lorax extra repo {0:d}".format(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-{0:d}".format(n)
data = {"name": "lorax mirrorlist {0:d}".format(n),
"mirrorlist": mirror,
"enabled": 1 }
c.add_section(section)
map(lambda (key, value): c.set(section, key, value), data.items())
# write the yum configuration file
with open(yumconf, "w") as f:
c.write(f)
# create the yum base object
yb = yum.YumBase()
yb.preconf.fn = yumconf
yb.preconf.root = installroot
yb._getConfig()
yb._getRpmDB()
yb._getRepos()
yb._getSacks()
return yb

View File

@ -1,9 +0,0 @@
#%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

View File

@ -1,9 +0,0 @@
#%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

View File

@ -1,9 +0,0 @@
#%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

View File

@ -1,17 +0,0 @@
Port 22
HostKey /etc/ssh/ssh_host_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
PermitRootLogin yes
IgnoreRhosts yes
StrictModes yes
X11Forwarding yes
X11DisplayOffset 10
PrintMotd yes
XAuthLocation /sbin/xauth
KeepAlive yes
SyslogFacility AUTHPRIV
RSAAuthentication yes
PasswordAuthentication yes
PermitEmptyPasswords yes
PermitUserEnvironment yes

View File

@ -1 +0,0 @@
s390

View File

@ -1,5 +0,0 @@
<?xml version="1.0"?>
<gconf>
<entry name="accessibility" mtime="1176200664" type="bool" value="true">
</entry>
</gconf>

View File

@ -1,13 +0,0 @@
[defaults]
skeleton = /mnt/sysimage/etc/skel
mailspooldir = /mnt/sysimage/var/mail
crypt_style = md5
modules = files shadow
create_modules = files shadow
[files]
directory = /mnt/sysimage/etc
[shadow]
directory = /mnt/sysimage/etc

View File

@ -1,3 +0,0 @@
SELINUX=permissive
SELINUXTYPE=targeted

View File

@ -1,9 +0,0 @@
This directory contains image files that can be used to create media
capable of starting the @PRODUCT@ installation process.
The boot.iso file is an ISO 9660 image of a bootable CD-ROM. It is useful
in cases where the CD-ROM installation method is not desired, but the
CD-ROM's boot speed would be an advantage.
To use this image file, burn the file onto CD-R (or CD-RW) media as you
normally would.

View File

@ -1,6 +0,0 @@
The files in this directory are useful for booting a machine via PXE.
The following files are available:
vmlinuz - the kernel used for the installer
initrd.img - an initrd with support for all install methods and
drivers supported for installation of @PRODUCT@