{pkgs}: with pkgs; rec { inherit (kernelPackages_2_6_29) kernel; klibcShrunk = pkgs.klibcShrunk.override { klibc = klibc_15; }; kvm = pkgs.kvm76; modulesClosure = makeModulesClosure { inherit kernel; rootModules = ["cifs" "virtio_net" "virtio_pci" "virtio_blk" "virtio_balloon" "nls_utf8"]; }; # !!! should use the mount_cifs package in all-packages.nix here. mountCifs = (makeStaticBinaries stdenv).mkDerivation { name = "mount.cifs"; src = mount_cifs.src; buildInputs = [nukeReferences]; buildCommand = '' ensureDir $out/bin gcc -Wall $src -o $out/bin/mount.cifs strip $out/bin/mount.cifs nuke-refs $out/bin/mount.cifs ''; allowedReferences = []; # prevent accidents like glibc being included in the initrd }; createDeviceNodes = dev: '' mknod ${dev}/null c 1 3 mknod ${dev}/zero c 1 5 mknod ${dev}/tty c 5 0 mknod ${dev}/vda b 253 0 ''; stage1Init = writeScript "vm-run-stage1" '' #! ${klibcShrunk}/bin/sh.shared -e echo START export PATH=${klibcShrunk}/bin:${mountCifs}/bin mkdir /etc echo -n > /etc/fstab mount -t proc none /proc for o in $(cat /proc/cmdline); do case $o in mountDisk=1) mountDisk=1 ;; command=*) set -- $(IFS==; echo $o) command=$2 ;; tmpDir=*) set -- $(IFS==; echo $o) export tmpDir=$2 ;; out=*) set -- $(IFS==; echo $o) export out=$2 ;; esac done for i in $(cat ${modulesClosure}/insmod-list); do args= case $i in */cifs.ko) args="CIFSMaxBufSize=4194304" ;; esac echo "loading module $i with args $args" insmod $i $args done mount -t tmpfs none /dev ${createDeviceNodes "/dev"} ipconfig 10.0.2.15:::::eth0:none mkdir /fs if test -z "$mountDisk"; then mount -t tmpfs none /fs else mount -t ext2 /dev/vda /fs fi mkdir -p /fs/hostfs mkdir -p /fs/dev mount -o bind /dev /fs/dev n=. echo "mounting host filesystem..." while true; do if mount.cifs //10.0.2.4/qemu /fs/hostfs -o guest,username=nobody; then break else n=".$n" test ''${#n} -le 10 || exit 1 sleep 1 echo "retrying..." fi done mkdir -p /fs/nix/store mount -o bind /fs/hostfs/nix/store /fs/nix/store mkdir -p /fs/tmp mount -t tmpfs -o "mode=755" none /fs/tmp mkdir -p /fs/proc mount -t proc none /fs/proc mkdir -p /fs/etc ln -sf /proc/mounts /fs/etc/mtab echo "Now running: $command" test -n "$command" set +e chroot /fs $command /tmp $out /hostfs/$tmpDir echo $? > /fs/hostfs/$tmpDir/in-vm-exit mount -o remount,ro dummy /fs echo DONE reboot ''; initrd = makeInitrd { contents = [ { object = stage1Init; symlink = "/init"; } ]; }; stage2Init = writeScript "vm-run-stage2" '' #! ${bash}/bin/sh source $3/saved-env export NIX_STORE=/nix/store export NIX_BUILD_TOP="$1" export TMPDIR="$1" export PATH=/empty out="$2" export ORIG_TMPDIR="$3" cd "$NIX_BUILD_TOP" if ! test -e /bin/sh; then ${coreutils}/bin/mkdir -p /bin ${coreutils}/bin/ln -s ${bash}/bin/sh /bin/sh fi # For debugging: if this is the second time this image is run, # then don't start the build again, but instead drop the user into # an interactive shell. if test -n "$origBuilder" -a ! -e /.debug; then ${coreutils}/bin/touch /.debug exec $origBuilder $origArgs else export PATH=/bin:/usr/bin:${coreutils}/bin echo "Starting interactive shell..." echo "(To run the original builder: \$origBuilder \$origArgs)" exec ${bash}/bin/sh fi ''; qemuCommandLinux = '' qemu-system-x86_64 -no-kvm-irqchip \ -nographic -no-reboot \ -net nic,model=virtio -net user -smb / \ -drive file=$diskImage,if=virtio,boot=on \ -kernel ${kernel}/vmlinuz \ -initrd ${initrd}/initrd \ -append "console=ttyS0 panic=1 command=${stage2Init} tmpDir=$TMPDIR out=$out mountDisk=$mountDisk" \ $QEMU_OPTS ''; vmRunCommand = qemuCommand: writeText "vm-run" '' export > saved-env PATH=${coreutils}/bin:${kvm}/bin:${samba}/sbin diskImage=''${diskImage:-/dev/null} eval "$preVM" # Write the command to start the VM to a file so that the user can # debug inside the VM if the build fails (when Nix is called with # the -K option to preserve the temporary build directory). cat > ./run-vm < $out/nix-support/full-name ''; createRootFS = '' mkdir /mnt ${e2fsprogs}/sbin/mke2fs -F /dev/vda ${klibcShrunk}/bin/mount -t ext2 /dev/vda /mnt if test -e /mnt/.debug; then exec ${bash}/bin/sh fi touch /mnt/.debug mkdir /mnt/proc /mnt/dev /mnt/sys /mnt/bin ${createDeviceNodes "/mnt/dev"} ''; modifyDerivation = f: attrs: let attrsCleaned = removeAttrs attrs ["meta" "passthru" "outPath" "drvPath"]; newDrv = derivation (attrsCleaned // (f attrs)); in newDrv // { meta = if attrs ? meta then attrs.meta else {}; passthru = if attrs ? passthru then attrs.passthru else {}; }; /* Run a derivation in a Linux virtual machine (using Qemu/KVM). By default, there is no disk image; the root filesystem is a tmpfs, and /nix/store is shared with the host (via the CIFS protocol to a Samba instance automatically started by Qemu). Thus, any pure Nix derivation should run unmodified, e.g. the call runInLinuxVM patchelf will build the derivation `patchelf' inside a VM. The attribute `preVM' can optionally contain a shell command to be evaluated *before* the VM is started (i.e., on the host). The attribute `memSize' specifies the memory size of the VM in megabytes, defaulting to 256. The attribute `diskImage' can optionally specify a file system image to be attached to /dev/sda. (Note that currently we expect the image to contain a filesystem, not a full disk image with a partition table etc.) If the build fails and Nix is run with the `-K' option, a script `run-vm' will be left behind in the temporary build directory that allows you to boot into the VM and debug it interactively. */ runInLinuxVM = modifyDerivation (attrs: { builder = "${bash}/bin/sh"; args = ["-e" (vmRunCommand qemuCommandLinux)]; origArgs = attrs.args; origBuilder = attrs.builder; QEMU_OPTS = "-m ${toString (if attrs ? memSize then attrs.memSize else 256)}"; }); qemuCommandGeneric = '' qemu-system-x86_64 \ -nographic -no-reboot \ -smb $(pwd) -hda $diskImage \ $QEMU_OPTS ''; /* Run a command in a x86 virtual machine image containing an arbitrary OS. The VM should be configured to do the following: - Write log output to the serial port. - Mount //10.0.2.4/qemu via SMB. - Execute the command "cmd" on the SMB share. It can access the original derivation attributes in "saved-env" on the share. - Produce output under "out" on the SMB share. - Write an exit code to "in-vm-exit" on the SMB share ("0" meaning success). - Reboot to shutdown the machine (because Qemu doesn't seem capable of a APM/ACPI VM shutdown). */ runInGenericVM = modifyDerivation (attrs: { system = "i686-linux"; builder = "${bash}/bin/sh"; args = ["-e" (vmRunCommand qemuCommandGeneric)]; QEMU_OPTS = "-m ${toString (if attrs ? memSize then attrs.memSize else 256)}"; preVM = '' diskImage=$(pwd)/disk-image.qcow2 origImage=${attrs.diskImage} if test -d "$origImage"; then origImage="$origImage/disk-image.qcow2"; fi qemu-img create -b "$origImage" -f qcow2 $diskImage echo "$buildCommand" > cmd eval "$postPreVM" ''; postVM = '' cp -prvd out $out ''; }); /* Like runInLinuxVM, but run the build not using the stdenv from the Nix store, but using the tools provided by /bin, /usr/bin etc. from the specified filesystem image, which typically is a filesystem containing a non-NixOS Linux distribution. */ runInLinuxImage = attrs: runInLinuxVM (attrs // { mountDisk = true; /* Mount `image' as the root FS, but use a temporary copy-on-write image since we don't want to (and can't) write to `image'. */ preVM = '' diskImage=$(pwd)/disk-image.qcow2 origImage=${attrs.diskImage} if test -d "$origImage"; then origImage="$origImage/disk-image.qcow2"; fi qemu-img create -b "$origImage" -f qcow2 $diskImage ''; /* Inside the VM, run the stdenv setup script normally, but at the very end set $PATH and $SHELL to the `native' paths for the distribution inside the VM. */ postHook = '' PATH=/usr/bin:/bin:/usr/sbin:/sbin SHELL=/bin/sh eval "$origPostHook" ''; origPostHook = if attrs ? postHook then attrs.postHook else ""; /* Don't run Nix-specific build steps like patchelf. */ fixupPhase = "true"; }); /* Create a filesystem image of the specified size and fill it with a set of RPM packages. */ fillDiskWithRPMs = {size ? 4096, rpms, name, fullName, preInstall ? "", postInstall ? "", runScripts ? true}: runInLinuxVM (stdenv.mkDerivation { inherit name preInstall postInstall rpms; preVM = createEmptyImage {inherit size fullName;}; buildCommand = '' ${createRootFS} chroot=$(type -tP chroot) echo "unpacking RPMs..." for i in $rpms; do echo "$i..." ${rpm}/bin/rpm2cpio "$i" | (cd /mnt && ${cpio}/bin/cpio -i --make-directories) done eval "$preInstall" echo "initialising RPM DB..." PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ ldconfig -v || true PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ rpm --initdb # Make the Nix store available in /mnt, because that's where the RPMs live. mkdir -p /mnt/nix/store ${klibcShrunk}/bin/mount -o bind /nix/store /mnt/nix/store echo "installing RPMs..." PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ rpm -iv ${if runScripts then "" else "--noscripts"} $rpms echo "running post-install script..." eval "$postInstall" rm /mnt/.debug ${klibcShrunk}/bin/umount /mnt/nix/store ${klibcShrunk}/bin/umount /mnt ''; passthru = {inherit fullName;}; }); /* Generate a script that can be used to run an interactive session in the given image. */ makeImageTestScript = image: writeScript "image-test" '' #! ${bash}/bin/sh if test -z "$1"; then echo "Syntax: $0 " exit 1 fi diskImage="$1" if ! test -e "$diskImage"; then qemu-img create -b ${image}/disk-image.qcow2 -f qcow2 "$diskImage" fi export TMPDIR=$(mktemp -d) export out=/dummy export origBuilder= export origArgs= export > $TMPDIR/saved-env mountDisk=1 ${qemuCommandLinux} ''; /* Build RPM packages from the tarball `src' in the Linux distribution installed in the filesystem `diskImage'. The tarball must contain an RPM specfile. */ buildRPM = attrs: runInLinuxImage (stdenv.mkDerivation ({ phases = "prepareImagePhase sysInfoPhase buildPhase installPhase"; outDir = "rpms/${attrs.diskImage.name}"; prepareImagePhase = '' if test -n "$extraRPMs"; then for rpmdir in $extraRPMs ; do rpm -iv $(ls $rpmdir/rpms/*/*.rpm | grep -v 'src\.rpm' | sort | head -1) done fi ''; sysInfoPhase = '' echo "System/kernel: $(uname -a)" if test -e /etc/fedora-release; then echo "Fedora release: $(cat /etc/fedora-release)"; fi if test -e /etc/SuSE-release; then echo "SUSE release: $(cat /etc/SuSE-release)"; fi header "installed RPM packages" rpm -qa --qf "%{Name}-%{Version}-%{Release} (%{Arch}; %{Distribution}; %{Vendor})\n" stopNest ''; buildPhase = '' eval "$preBuild" # Hacky: RPM looks for .spec inside the tarball, so # strip off the hash. stripHash "$src" srcName="$strippedName" cp "$src" "$srcName" # `ln' doesn't work always work: RPM requires that the file is owned by root export HOME=/tmp/home mkdir $HOME rpmout=/tmp/rpmout mkdir $rpmout $rpmout/SPECS $rpmout/BUILD $rpmout/RPMS $rpmout/SRPMS echo "%_topdir $rpmout" >> $HOME/.rpmmacros rpmbuild -vv -ta "$srcName" eval "$postBuild" ''; installPhase = '' eval "$preInstall" ensureDir $out/$outDir find $rpmout -name "*.rpm" -exec cp {} $out/$outDir \; for i in $out/$outDir/*.rpm; do header "Generated RPM/SRPM: $i" rpm -qip $i stopNest done eval "$postInstall" ''; # */ } // attrs)); /* Create a filesystem image of the specified size and fill it with a set of Debian packages. `debs' must be a list of list of .deb files, namely, the Debian packages grouped together into strongly connected components. See deb/deb-closure.nix. */ fillDiskWithDebs = {size ? 4096, debs, name, fullName, postInstall ? null}: runInLinuxVM (stdenv.mkDerivation { inherit name postInstall; debs = (lib.intersperse "|" debs); preVM = createEmptyImage {inherit size fullName;}; buildCommand = '' ${createRootFS} PATH=$PATH:${dpkg}/bin:${dpkg}/sbin:${glibc}/sbin:${lzma}/bin # Unpack the .debs. We do this to prevent pre-install scripts # (which have lots of circular dependencies) from barfing. echo "unpacking Debs..." for deb in $debs; do if test "$deb" != "|"; then echo "$deb..." dpkg-deb --extract "$deb" /mnt fi done # Make the Nix store available in /mnt, because that's where the .debs live. mkdir -p /mnt/inst/nix/store ${klibcShrunk}/bin/mount -o bind /nix/store /mnt/inst/nix/store ${klibcShrunk}/bin/mount -o bind /proc /mnt/proc ${klibcShrunk}/bin/mount -o bind /dev /mnt/dev # Misc. files/directories assumed by various packages. echo "initialising Dpkg DB..." touch /mnt/etc/shells touch /mnt/var/lib/dpkg/status touch /mnt/var/lib/dpkg/available touch /mnt/var/lib/dpkg/diversions # Now install the .debs. This is basically just to register # them with dpkg and to make their pre/post-install scripts # run. echo "installing Debs..." export DEBIAN_FRONTEND=noninteractive oldIFS="$IFS" IFS="|" for component in $debs; do IFS="$oldIFS" echo echo ">>> INSTALLING COMPONENT: $component" debs= for i in $component; do debs="$debs /inst/$i"; done chroot=$(type -tP chroot) PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ /usr/bin/dpkg --install --force-all $debs < /dev/null done echo "running post-install script..." eval "$postInstall" ln -sf dash /mnt/bin/sh rm /mnt/.debug ${klibcShrunk}/bin/umount /mnt/inst/nix/store ${klibcShrunk}/bin/umount /mnt/proc ${klibcShrunk}/bin/umount /mnt/dev ${klibcShrunk}/bin/umount /mnt ''; passthru = {inherit fullName;}; }); /* Generate a Nix expression containing fetchurl calls for the closure of a set of top-level RPM packages from the `primary.xml.gz' file of a Fedora or openSUSE distribution. */ rpmClosureGenerator = {name, packagesList, urlPrefix, packages, archs ? []}: runCommand "${name}.nix" {buildInputs = [perl perlPackages.XMLSimple]; inherit archs;} '' gunzip < ${packagesList} > ./packages.xml perl -w ${rpm/rpm-closure.pl} \ ./packages.xml ${urlPrefix} ${toString packages} > $out ''; /* Helper function that combines rpmClosureGenerator and fillDiskWithRPMs to generate a disk image from a set of package names. */ makeImageFromRPMDist = { name, fullName, size ? 4096, urlPrefix, packagesList, packages , preInstall ? "", postInstall ? "", archs ? ["noarch" "i386"], runScripts ? true}: fillDiskWithRPMs { inherit name fullName size preInstall postInstall runScripts; rpms = import (rpmClosureGenerator { inherit name packagesList urlPrefix packages archs; }) {inherit fetchurl;}; }; /* Like `rpmClosureGenerator', but now for Debian/Ubuntu releases (i.e. generate a closure from a Packages.bz2 file). */ debClosureGenerator = {name, packagesList, urlPrefix, packages}: runCommand "${name}.nix" {} '' bunzip2 < ${packagesList} > ./Packages # Work around this bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=452279 substituteInPlace ./Packages --replace x86_64-linux-gnu x86-64-linux-gnu ${perl}/bin/perl -I${dpkg} -w ${deb/deb-closure.pl} \ ./Packages ${urlPrefix} ${toString packages} > $out ''; /* Helper function that combines debClosureGenerator and fillDiskWithDebs to generate a disk image from a set of package names. */ makeImageFromDebDist = {name, fullName, size ? 4096, urlPrefix, packagesList, packages, postInstall ? ""}: let expr = debClosureGenerator { inherit name packagesList urlPrefix packages; }; in (fillDiskWithDebs { inherit name fullName size postInstall; debs = import expr {inherit fetchurl;}; }) // {inherit expr;}; /* A bunch of functions that build disk images of various Linux distributions, given a set of top-level package names to be installed in the image. */ diskImageFuns = { fedora2i386 = args: makeImageFromRPMDist ({ name = "fedora-core-2-i386"; fullName = "Fedora Core 2 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/core/2/i386/os/repodata/primary.xml.gz; sha256 = "1nq1k2k0nzkii737cka301f0vbd2ix2wsfvi6bblpi748q6h2w4k"; }; urlPrefix = mirror://fedora/linux/core/2/i386/os; runScripts = false; } // args); fedora3i386 = args: makeImageFromRPMDist ({ name = "fedora-core-3-i386"; fullName = "Fedora Core 3 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/core/3/i386/os/repodata/primary.xml.gz; sha256 = "13znspn4g1bkjkk47393k9chswgzl6nx1n0q6h2wrw52c7d9nw9i"; }; urlPrefix = mirror://fedora/linux/core/3/i386/os; archs = ["noarch" "i386" "i586"]; runScripts = false; } // args); fedora5i386 = args: makeImageFromRPMDist ({ name = "fedora-core-5-i386"; fullName = "Fedora Core 5 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/core/5/i386/os/repodata/primary.xml.gz; sha256 = "0lfk4mzrpiyls8h7k9ckc3vgywbmg05zsr4ag6qakgnv9gljijig"; }; urlPrefix = mirror://fedora/linux/core/5/i386/os; } // args); fedora7i386 = args: makeImageFromRPMDist ({ name = "fedora-7-i386"; fullName = "Fedora 7 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/7/Fedora/i386/os/repodata/primary.xml.gz; sha256 = "0zq7ifirj45wry7b2qkm12qhzzazal3hn610h5kwbrfr2xavs882"; }; urlPrefix = mirror://fedora/linux/releases/7/Fedora/i386/os; } // args); fedora8i386 = args: makeImageFromRPMDist ({ name = "fedora-8-i386"; fullName = "Fedora 8 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/8/Fedora/i386/os/repodata/primary.xml.gz; sha256 = "0vr9345rrk0vhs4pc9cjp8npdkqz0xqyirv84vhyfn533m9ws36f"; }; urlPrefix = mirror://fedora/linux/releases/8/Fedora/i386/os; } // args); fedora9i386 = args: makeImageFromRPMDist ({ name = "fedora-9-i386"; fullName = "Fedora 9 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/9/Fedora/i386/os/repodata/primary.xml.gz; sha256 = "18780xgyag5acx79warcpvzlfkm0mni8xawl6jjvgxg9n3lp6zg0"; }; urlPrefix = mirror://fedora/linux/releases/9/Fedora/i386/os; } // args); fedora9x86_64 = args: makeImageFromRPMDist ({ name = "fedora-9-x86_64"; fullName = "Fedora 9 (x86_64)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/9/Fedora/x86_64/os/repodata/primary.xml.gz; sha256 = "0qcjigzbw29ahhkfjaw5pbpyl7mj9l349hikwv25jcnid1cbpmx7"; }; urlPrefix = mirror://fedora/linux/releases/9/Fedora/x86_64/os; archs = ["noarch" "x86_64"]; } // args); fedora10i386 = args: makeImageFromRPMDist ({ name = "fedora-10-i386"; fullName = "Fedora 10 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/10/Fedora/i386/os/repodata/primary.xml.gz; sha256 = "15ha8pxzvlch707mpy06c7pkr2ra2vpd5b8x30qhydvx8fgcqcx9"; }; urlPrefix = mirror://fedora/linux/releases/10/Fedora/i386/os; } // args); fedora10x86_64 = args: makeImageFromRPMDist ({ name = "fedora-10-x86_64"; fullName = "Fedora 10 (x86_64)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/10/Fedora/x86_64/os/repodata/primary.xml.gz; sha256 = "1pmaav6mdaw13fq99wfggbsmhcix306cimijjxh35qi7yc3wbsz4"; }; urlPrefix = mirror://fedora/linux/releases/10/Fedora/x86_64/os; archs = ["noarch" "x86_64"]; } // args); fedora11i386 = args: makeImageFromRPMDist ({ name = "fedora-11-i386"; fullName = "Fedora 11 (i386)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/11/Fedora/i386/os/repodata/36af1d88214b770fd3d814a5126083b8e808510c76acfdc3a234d6f7e43c2425-primary.xml.gz; sha256 = "09947kjggmillb1zvb3n1i8his5qhdh1598lv39hyxsb4641vbrn"; }; urlPrefix = mirror://fedora/linux/releases/11/Fedora/i386/os; archs = ["noarch" "i386" "i586"]; } // args); fedora11x86_64 = args: makeImageFromRPMDist ({ name = "fedora-11-x86_64"; fullName = "Fedora 11 (x86_64)"; packagesList = fetchurl { url = mirror://fedora/linux/releases/11/Fedora/x86_64/os/repodata/c792495863f5314329c463d51860fc74c6367f72c3cb1c132f6c3290102d68da-primary.xml.gz; sha256 = "1nk85l890ckc5w9irjy3f9zkdiklzih1imb3qhll6cgmcdc4k4n7"; }; urlPrefix = mirror://fedora/linux/releases/11/Fedora/x86_64/os; archs = ["noarch" "x86_64"]; } // args); opensuse103i386 = args: makeImageFromRPMDist ({ name = "opensuse-10.3-i586"; fullName = "openSUSE 10.3 (i586)"; packagesList = fetchurl { url = mirror://opensuse/distribution/10.3/repo/oss/suse/repodata/primary.xml.gz; sha256 = "0zb5kxsb755nqq9i8jdclmanacyf551ncx6a011v9jqphsvyfvd7"; }; urlPrefix = mirror://opensuse/distribution/10.3/repo/oss/suse/; archs = ["noarch" "i586"]; } // args); opensuse110i386 = args: makeImageFromRPMDist ({ name = "opensuse-11.0-i586"; fullName = "openSUSE 11.0 (i586)"; packagesList = fetchurl { url = mirror://opensuse/distribution/11.0/repo/oss/suse/repodata/primary.xml.gz; sha256 = "13rv855aj8p3h1zpsji5xa1wpkhgq94gcxzvg05l2b68b15q3mwn"; }; urlPrefix = mirror://opensuse/distribution/11.0/repo/oss/suse/; archs = ["noarch" "i586"]; } // args); opensuse110x86_64 = args: makeImageFromRPMDist ({ name = "opensuse-11.0-x86_64"; fullName = "openSUSE 11.0 (x86_64)"; packagesList = fetchurl { url = mirror://opensuse/distribution/11.0/repo/oss/suse/repodata/primary.xml.gz; sha256 = "13rv855aj8p3h1zpsji5xa1wpkhgq94gcxzvg05l2b68b15q3mwn"; }; urlPrefix = mirror://opensuse/distribution/11.0/repo/oss/suse/; archs = ["noarch" "x86_64"]; } // args); opensuse111i386 = args: makeImageFromRPMDist ({ name = "opensuse-11.1-i586"; fullName = "openSUSE 11.1 (i586)"; packagesList = fetchurl { url = mirror://opensuse/distribution/11.1/repo/oss/suse/repodata/primary.xml.gz; sha256 = "1mfmp9afikj0hci1s8cpwjdr0ycbpfym9gdhci590r9fa75w221j"; }; urlPrefix = mirror://opensuse/distribution/11.1/repo/oss/suse/; archs = ["noarch" "i586"]; } // args); opensuse111x86_64 = args: makeImageFromRPMDist ({ name = "opensuse-11.1-x86_64"; fullName = "openSUSE 11.1 (x86_64)"; packagesList = fetchurl { url = mirror://opensuse/distribution/11.1/repo/oss/suse/repodata/primary.xml.gz; sha256 = "1mfmp9afikj0hci1s8cpwjdr0ycbpfym9gdhci590r9fa75w221j"; }; urlPrefix = mirror://opensuse/distribution/11.1/repo/oss/suse/; archs = ["noarch" "x86_64"]; } // args); # Interestingly, the SHA-256 hashes provided by Ubuntu in # http://nl.archive.ubuntu.com/ubuntu/dists/{gutsy,hardy}/Release are # wrong, but the SHA-1 and MD5 hashes are correct. Intrepid is fine. ubuntu710i386 = args: makeImageFromDebDist ({ name = "ubuntu-7.10-gutsy-i386"; fullName = "Ubuntu 7.10 Gutsy (i386)"; packagesList = fetchurl { url = mirror://ubuntu/dists/gutsy/main/binary-i386/Packages.bz2; sha1 = "8b52ee3d417700e2b2ee951517fa25a8792cabfd"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu804i386 = args: makeImageFromDebDist ({ name = "ubuntu-8.04-hardy-i386"; fullName = "Ubuntu 8.04 Hardy (i386)"; packagesList = fetchurl { url = mirror://ubuntu/dists/hardy/main/binary-i386/Packages.bz2; sha1 = "db74581ee75cb3bee2a8ae62364e97956c723259"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu804x86_64 = args: makeImageFromDebDist ({ name = "ubuntu-8.04-hardy-amd64"; fullName = "Ubuntu 8.04 Hardy (amd64)"; packagesList = fetchurl { url = mirror://ubuntu/dists/hardy/main/binary-amd64/Packages.bz2; sha1 = "d1f1d2b3cc62533d6e4337f2696a5d27235d1f28"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu810i386 = args: makeImageFromDebDist ({ name = "ubuntu-8.10-intrepid-i386"; fullName = "Ubuntu 8.10 Intrepid (i386)"; packagesList = fetchurl { url = mirror://ubuntu/dists/intrepid/main/binary-i386/Packages.bz2; sha256 = "70483d40a9e9b74598f2faede7df5d5103ee60055af7374f8db5c7e6017c4cf6"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu810x86_64 = args: makeImageFromDebDist ({ name = "ubuntu-8.10-intrepid-amd64"; fullName = "Ubuntu 8.10 Intrepid (amd64)"; packagesList = fetchurl { url = mirror://ubuntu/dists/intrepid/main/binary-amd64/Packages.bz2; sha256 = "01b2f3842cbdd5834446ddf91691bcf60f59a726dcefa23fb5b93fdc8ea7e27f"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu904i386 = args: makeImageFromDebDist ({ name = "ubuntu-9.04-jaunty-i386"; fullName = "Ubuntu 9.04 Jaunty (i386)"; packagesList = fetchurl { url = mirror://ubuntu/dists/jaunty/main/binary-i386/Packages.bz2; sha256 = "72c95e4901ad56ce8791723e2ae40bce2399f306f9956cac80e964011e1948d0"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu904x86_64 = args: makeImageFromDebDist ({ name = "ubuntu-9.04-jaunty-amd64"; fullName = "Ubuntu 9.04 Jaunty (amd64)"; packagesList = fetchurl { url = mirror://ubuntu/dists/jaunty/main/binary-amd64/Packages.bz2; sha256 = "af760ce04e43f066b8938b1abdeff979a642f940515659ede44f7877ca358ca8"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu910i386 = args: makeImageFromDebDist ({ name = "ubuntu-9.10-karmic-i386"; fullName = "Ubuntu 9.10 Karmic (i386)"; packagesList = fetchurl { url = mirror://ubuntu/dists/karmic/main/binary-i386/Packages.bz2; sha256 = "6e3e813857496f2af6cd7e6ada06b3398fa067a7992c5fd7e8bd8fa92e3548b7"; }; urlPrefix = mirror://ubuntu; } // args); ubuntu910x86_64 = args: makeImageFromDebDist ({ name = "ubuntu-9.10-karmic-amd64"; fullName = "Ubuntu 9.10 Karmic (amd64)"; packagesList = fetchurl { url = mirror://ubuntu/dists/karmic/main/binary-amd64/Packages.bz2; sha256 = "3a604fcb0c135eeb8b95da3e90a8fd4cfeff519b858cd3c9e62ea808cb9fec40"; }; urlPrefix = mirror://ubuntu; } // args); debian40i386 = args: makeImageFromDebDist ({ name = "debian-4.0r8-etch-i386"; fullName = "Debian 4.0r8 Etch (i386)"; packagesList = fetchurl { url = mirror://debian/dists/etch/main/binary-i386/Packages.bz2; sha256 = "80ea57a7f106086c74470229998b07885d185dc62fe4a3200d2fffc5b2371f3d"; }; urlPrefix = mirror://debian; } // args); debian40x86_64 = args: makeImageFromDebDist ({ name = "debian-4.0r8-etch-amd64"; fullName = "Debian 4.0r8 Etch (amd64)"; packagesList = fetchurl { url = mirror://debian/dists/etch/main/binary-amd64/Packages.bz2; sha256 = "d00114ef5e0c287273eebff7e7c4ca1aa0388a56c7d980a0a031e7782741e5ba"; }; urlPrefix = mirror://debian; } // args); debian50i386 = args: makeImageFromDebDist ({ name = "debian-5.0.3-lenny-i386"; fullName = "Debian 5.0.3 Lenny (i386)"; packagesList = fetchurl { url = mirror://debian/dists/lenny/main/binary-i386/Packages.bz2; sha256 = "87886ed314c53a57c6689022c0043c25c3c96c643e3034fc51acae0572b5ff1f"; }; urlPrefix = mirror://debian; } // args); debian50x86_64 = args: makeImageFromDebDist ({ name = "debian-5.0.3-lenny-amd64"; fullName = "Debian 5.0.3 Lenny (amd64)"; packagesList = fetchurl { url = mirror://debian/dists/lenny/main/binary-amd64/Packages.bz2; sha256 = "c51dc5b87d7cd12bd3537bb905428a49869a0f4e0e7cb3546dd8a00fb32db380"; }; urlPrefix = mirror://debian; } // args); }; /* Common packages for Fedora images. */ commonFedoraPackages = [ "autoconf" "automake" "basesystem" "bzip2" "curl" "diffutils" "fedora-release" "findutils" "gawk" "gcc-c++" "gzip" "make" "patch" "perl" "pkgconfig" "rpm" "rpm-build" "tar" "unzip" ]; /* Common packages for openSUSE images. */ commonOpenSUSEPackages = [ "aaa_base" "autoconf" "automake" "bzip2" "curl" "diffutils" "findutils" "gawk" "gcc-c++" "gzip" "make" "patch" "perl" "pkg-config" "rpm" "tar" "unzip" "util-linux" "gnu-getopt" ]; /* Common packages for Debian/Ubuntu images. */ commonDebianPackages = [ "base-passwd" "dpkg" "libc6-dev" "perl" "sysvinit" "bash" "dash" "gzip" "bzip2" "tar" "grep" "findutils" "g++" "make" "curl" "patch" "diff" "locales" # Needed by checkinstall: "util-linux" "file" "dpkg-dev" "pkg-config" # Needed because it provides /etc/login.defs, whose absence causes # the "passwd" post-installs script to fail. "login" # For shutting up some messages during some post-install scripts: "mktemp" ]; # Ubuntu 9.10 no longer has sysvinit. karmicPackages = lib.filter (x: x != "sysvinit") commonDebianPackages; /* A bunch of disk images. */ diskImages = { redhat9i386 = fillDiskWithRPMs { name = "redhat-9-i386"; fullName = "Red Hat Linux 9 (i386)"; size = 1024; rpms = import ./rpm/redhat-9-i386.nix {inherit fetchurl;}; }; suse90i386 = fillDiskWithRPMs { name = "suse-9.0-i386"; fullName = "SUSE Linux 9.0 (i386)"; size = 1024; rpms = import ./rpm/suse-9-i386.nix {inherit fetchurl;}; # Urgh. The /etc/group entries are installed by aaa_base (or # something) but due to dependency ordering, that package isn't # installed yet by the time some other packages refer to these # entries. preInstall = '' echo 'bin:x:1:daemon' >> /mnt/etc/group echo 'tty:x:5:' >> /mnt/etc/group echo 'disk:x:6:' >> /mnt/etc/group echo 'lp:x:7:' >> /mnt/etc/group echo 'uucp:x:14:' >> /mnt/etc/group echo 'audio:x:17:' >> /mnt/etc/group echo 'video:x:33:' >> /mnt/etc/group ''; }; fedora2i386 = diskImageExtraFuns.fedora2i386 []; fedora3i386 = diskImageExtraFuns.fedora3i386 []; fedora5i386 = diskImageExtraFuns.fedora5i386 []; fedora7i386 = diskImageExtraFuns.fedora7i386 []; fedora8i386 = diskImageExtraFuns.fedora8i386 []; fedora9i386 = diskImageExtraFuns.fedora9i386 []; fedora9x86_64 = diskImageExtraFuns.fedora9x86_64 []; fedora10i386 = diskImageExtraFuns.fedora10i386 []; fedora10x86_64 = diskImageExtraFuns.fedora10x86_64 []; fedora11i386 = diskImageExtraFuns.fedora11i386 []; fedora11x86_64 = diskImageExtraFuns.fedora11x86_64 []; opensuse103i386 = diskImageExtraFuns.opensuse103i386 []; opensuse110i386 = diskImageExtraFuns.opensuse110i386 []; opensuse110x86_64 = diskImageExtraFuns.opensuse110x86_64 []; opensuse111i386 = diskImageExtraFuns.opensuse111i386 []; opensuse111x86_64 = diskImageExtraFuns.opensuse111x86_64 []; ubuntu710i386 = diskImageExtraFuns.ubuntu710i386 []; ubuntu804i386 = diskImageExtraFuns.ubuntu804i386 []; ubuntu804x86_64 = diskImageExtraFuns.ubuntu804x86_64 []; ubuntu810i386 = diskImageExtraFuns.ubuntu810i386 []; ubuntu810x86_64 = diskImageExtraFuns.ubuntu810x86_64 []; ubuntu904i386 = diskImageExtraFuns.ubuntu904i386 []; ubuntu904x86_64 = diskImageExtraFuns.ubuntu904x86_64 []; ubuntu910i386 = diskImageExtraFuns.ubuntu910i386 []; ubuntu910x86_64 = diskImageExtraFuns.ubuntu910x86_64 []; debian40i386 = diskImageExtraFuns.debian40i386 []; debian40x86_64 = diskImageExtraFuns.debian40x86_64 []; debian50i386 = diskImageExtraFuns.debian50i386 []; debian50x86_64 = diskImageExtraFuns.debian50x86_64 []; }; diskImageExtraFuns = { fedora2i386 = extraVirtualPackages : diskImageFuns.fedora2i386 { packages = commonFedoraPackages ++ extraVirtualPackages; }; fedora3i386 = extraVirtualPackages : diskImageFuns.fedora3i386 { packages = commonFedoraPackages ++ extraVirtualPackages; }; fedora5i386 = extraVirtualPackages : diskImageFuns.fedora5i386 { packages = commonFedoraPackages ++ ["util-linux"] ++ extraVirtualPackages; }; fedora7i386 = extraVirtualPackages : diskImageFuns.fedora7i386 { packages = commonFedoraPackages ++ extraVirtualPackages; }; fedora8i386 = extraVirtualPackages : diskImageFuns.fedora8i386 { packages = commonFedoraPackages ++ extraVirtualPackages; }; fedora9i386 = extraVirtualPackages : diskImageFuns.fedora9i386 { packages = commonFedoraPackages ++ [ "cronie" "util-linux-ng" ] ++ extraVirtualPackages; }; fedora9x86_64 = extraVirtualPackages : diskImageFuns.fedora9x86_64 { packages = commonFedoraPackages ++ [ "cronie" "util-linux-ng" ] ++ extraVirtualPackages; }; fedora10i386 = extraVirtualPackages : diskImageFuns.fedora10i386 { packages = commonFedoraPackages ++ [ "cronie" "util-linux-ng" ] ++ extraVirtualPackages; }; fedora10x86_64 = extraVirtualPackages : diskImageFuns.fedora10x86_64 { packages = commonFedoraPackages ++ [ "cronie" "util-linux-ng" ] ++ extraVirtualPackages; }; fedora11i386 = extraVirtualPackages : diskImageFuns.fedora11i386 { packages = commonFedoraPackages ++ [ "cronie" "util-linux-ng" ] ++ extraVirtualPackages; }; fedora11x86_64 = extraVirtualPackages : diskImageFuns.fedora11x86_64 { packages = commonFedoraPackages ++ [ "cronie" "util-linux-ng" ] ++ extraVirtualPackages; }; opensuse103i386 = extraVirtualPackages : diskImageFuns.opensuse103i386 { packages = commonOpenSUSEPackages ++ ["devs"] ++ extraVirtualPackages; }; opensuse110i386 = extraVirtualPackages : diskImageFuns.opensuse110i386 { packages = commonOpenSUSEPackages ++ extraVirtualPackages; }; opensuse110x86_64 = extraVirtualPackages : diskImageFuns.opensuse110x86_64 { packages = commonOpenSUSEPackages ++ extraVirtualPackages; }; opensuse111i386 = extraVirtualPackages : diskImageFuns.opensuse111i386 { packages = commonOpenSUSEPackages ++ extraVirtualPackages; }; opensuse111x86_64 = extraVirtualPackages : diskImageFuns.opensuse111x86_64 { packages = commonOpenSUSEPackages ++ extraVirtualPackages; }; ubuntu710i386 = extraVirtualPackages : diskImageFuns.ubuntu710i386 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu804i386 = extraVirtualPackages : diskImageFuns.ubuntu804i386 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu804x86_64 = extraVirtualPackages : diskImageFuns.ubuntu804x86_64 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu810i386 = extraVirtualPackages : diskImageFuns.ubuntu810i386 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu810x86_64 = extraVirtualPackages : diskImageFuns.ubuntu810x86_64 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu904i386 = extraVirtualPackages : diskImageFuns.ubuntu904i386 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu904x86_64 = extraVirtualPackages : diskImageFuns.ubuntu904x86_64 { packages = commonDebianPackages ++ extraVirtualPackages; }; ubuntu910i386 = extraVirtualPackages : diskImageFuns.ubuntu910i386 { packages = karmicPackages ++ extraVirtualPackages; }; ubuntu910x86_64 = extraVirtualPackages : diskImageFuns.ubuntu910x86_64 { packages = karmicPackages ++ extraVirtualPackages; }; debian40i386 = extraVirtualPackages : diskImageFuns.debian40i386 { packages = commonDebianPackages ++ extraVirtualPackages; }; debian40x86_64 = extraVirtualPackages : diskImageFuns.debian40x86_64 { packages = commonDebianPackages ++ extraVirtualPackages; }; debian50i386 = extraVirtualPackages : diskImageFuns.debian50i386 { packages = commonDebianPackages ++ extraVirtualPackages; }; debian50x86_64 = extraVirtualPackages : diskImageFuns.debian50x86_64 { packages = commonDebianPackages ++ extraVirtualPackages; }; }; }