New version
This commit is contained in:
parent
492037c54b
commit
a4c638f132
3
AUTHORS
3
AUTHORS
@ -1,3 +1,2 @@
|
||||
David Cantrell <dcantrell@redhat.com>
|
||||
Martin Gracik <mgracik@redhat.com>
|
||||
|
||||
David Cantrell <dcantrell@redhat.com>
|
||||
|
7
Makefile
7
Makefile
@ -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
4
etc/config.i386
Normal file
@ -0,0 +1,4 @@
|
||||
[lorax]
|
||||
|
||||
packages:
|
||||
kernel-PAE grub memtest86+
|
@ -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
|
@ -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
|
@ -1 +0,0 @@
|
||||
config.i386
|
@ -1 +0,0 @@
|
||||
config.i386
|
@ -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
|
@ -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
|
@ -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
|
@ -1 +0,0 @@
|
||||
config.s390
|
@ -1 +0,0 @@
|
||||
config.i386
|
@ -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
|
@ -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
|
@ -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
|
@ -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
214
etc/templates/initrd.ltmpl
Normal 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
|
48
setup.py
48
setup.py
@ -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
120
src/bin/lorax
Executable file → Normal 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
143
src/pylorax/base.py
Normal 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)
|
@ -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
83
src/pylorax/constants.py
Normal 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]
|
@ -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
|
@ -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
865
src/pylorax/images.py
Normal 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
|
@ -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
149
src/pylorax/insttree.py
Normal 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)
|
@ -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
|
@ -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
|
@ -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
|
@ -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")
|
@ -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"]
|
@ -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
39
src/pylorax/ltmpl.py
Normal 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
|
@ -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
|
||||
|
@ -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()
|
@ -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
110
src/pylorax/yumbase.py
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1 +0,0 @@
|
||||
s390
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<gconf>
|
||||
<entry name="accessibility" mtime="1176200664" type="bool" value="true">
|
||||
</entry>
|
||||
</gconf>
|
@ -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
|
||||
|
@ -1,3 +0,0 @@
|
||||
SELINUX=permissive
|
||||
SELINUXTYPE=targeted
|
||||
|
@ -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.
|
@ -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@
|
Loading…
Reference in New Issue
Block a user