[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC 3/6] linux-stubdomain: Build a disk image.
This patch build a disk image intend to be mounted as rootfs by the stub-domain. It is build using the 'debugfs' tool and make a ext2 fs. Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> --- stubdom-linux/.gitignore | 2 + stubdom-linux/Makefile | 16 +++- stubdom-linux/extra/initscript | 40 +++++++++ stubdom-linux/extra/qemu-ifup | 7 ++ stubdom-linux/mk-ramdisk-common | 178 ++++++++++++++++++++++++++++++++++++++++ stubdom-linux/mk-ramdisk-ioemu | 124 ++++++++++++++++++++++++++++ 6 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 stubdom-linux/extra/initscript create mode 100644 stubdom-linux/extra/qemu-ifup create mode 100755 stubdom-linux/mk-ramdisk-common create mode 100755 stubdom-linux/mk-ramdisk-ioemu diff --git a/stubdom-linux/.gitignore b/stubdom-linux/.gitignore index 170e0c7..2cb91da 100644 --- a/stubdom-linux/.gitignore +++ b/stubdom-linux/.gitignore @@ -1,3 +1,5 @@ /linux-*.tar.xz /linux-*/ /vmlinuz-stubdom +/initramfs +/stubdom-disk.img diff --git a/stubdom-linux/Makefile b/stubdom-linux/Makefile index 0844046..93f8f48 100644 --- a/stubdom-linux/Makefile +++ b/stubdom-linux/Makefile @@ -9,7 +9,13 @@ LINUX_V=linux-3.4.13 QEMU_TREE=git://xenbits.xen.org/people/aperard/qemu-dm.git QEMU_BRANCH=origin/stubdom-preview1 -all: vmlinuz-stubdom +# Stubdom disk content +STUBDOM_DISK_FILE= \ + qemu-build/i386-softmmu/qemu-system-i386 \ + extra/initscript \ + extra/qemu-ifup + +all: stubdom-disk.img vmlinuz-stubdom qemu-remote: export GIT=$(GIT); \ @@ -67,3 +73,11 @@ $(LINUX_V)/arch/x86/boot/bzImage: $(LINUX_V)/.config vmlinuz-stubdom: $(LINUX_V)/arch/x86/boot/bzImage cp -f $^ $@ + +stubdom-disk.img: mk-ramdisk-common mk-ramdisk-ioemu $(STUBDOM_DISK_FILE) + env -u MAKELEVEL -u MAKEFLAGS -u MFLAGS ./mk-ramdisk-ioemu + chmod a-w $@ + +install: stubdom-disk.img vmlinuz-stubdom + cp -f vmlinuz-stubdom $(DESTDIR)/usr/lib/xen/boot/ + cp -f stubdom-disk.img $(DESTDIR)/usr/lib/xen/boot/ diff --git a/stubdom-linux/extra/initscript b/stubdom-linux/extra/initscript new file mode 100644 index 0000000..122892f --- /dev/null +++ b/stubdom-linux/extra/initscript @@ -0,0 +1,40 @@ +#!/bin/busybox sh + +_initscript_panic() { + sleep 10 +} + +trap _initscript_panic 0 + +set -e +set -x +mount -t sysfs /sys /sys +mount -t proc /proc /proc +mount -t xenfs -o nodev /proc/xen /proc/xen + +# TODO: Check if there is network for the vm before doing this +if test -e /sys/class/net/eth0; then + ip link set eth0 address fe:ff:ff:ff:ff:fe + ip addr flush eth0 + ip link set eth0 up + brctl addbr br0 + brctl addif br0 eth0 + ip link set br0 up +else + echo "No network interface named eth0." + ls -l /sys/class/net/ +fi + +# TODO Could probably to xenstore-read `xenstore-read vm`/image/dmargs +# because /local/domain/$domid is probably the root for relative path +domid=$(xenstore-read target) +dom_path="/local/domain/$domid" +vm_path=$(xenstore-read "$dom_path/vm") +dm_args=$(xenstore-read "$vm_path/image/dmargs") + +( sleep 30; free ) & +( sleep 60; free ) & +#( sleep 120; ip addr ) & +( sleep 120; free ) & +free +/bin/qemu $dm_args diff --git a/stubdom-linux/extra/qemu-ifup b/stubdom-linux/extra/qemu-ifup new file mode 100644 index 0000000..d71672b --- /dev/null +++ b/stubdom-linux/extra/qemu-ifup @@ -0,0 +1,7 @@ +#! /bin/busybox sh + +ip link set "$1" down +ip link set "$1" address fe:ff:ff:ff:ff:fd +ip addr flush "$1" +brctl addif br0 "$1" +ip link set "$1" up diff --git a/stubdom-linux/mk-ramdisk-common b/stubdom-linux/mk-ramdisk-common new file mode 100755 index 0000000..9a4a810 --- /dev/null +++ b/stubdom-linux/mk-ramdisk-common @@ -0,0 +1,178 @@ +#!/bin/bash +# +# This a simple implementaton of mkinitrd + + +# Set the umask. For iscsi, the initrd can contain platintext +# password (chap secret), so only allow read by owner. +umask 022 + +TMPDIR="/tmp" +PROBE="yes" +MNTIMAGE="`pwd`/initramfs/" +IMAGE="./initramfs.cpio" +verbose="" +: ${debug:=false} +case $debug in + true|false) ;; + *) + echo '$debug need to be true or false.' + exit 1 + ;; +esac +$debug && verbose='-v' + +DSO_DEPS="" +LDSO="" +get_dso_deps() { + bin="$1" ; shift + DSO_DEPS="" + + declare -a FILES + declare -a NAMES + + # this is a hack, but the only better way requires binutils or elfutils + # be installed. i.e., we need readelf to find the interpretter. + if [ -z "$LDSO" ]; then + for ldso in /lib*/ld*.so* ; do + [ -L $ldso ] && continue + [ -x $ldso ] || continue + $ldso --verify $bin >/dev/null 2>&1 || continue + LDSO="$ldso" + done + fi + + # I still hate shell. + declare -i n=0 + while read NAME I0 FILE ADDR I1 ; do + # ignore libfakeroot lib + [ "$NAME" == "libfakeroot-sysv.so" ] && continue + [ "$NAME" == "libfakeroot.so" ] && continue + [ "$NAME" == "libfakeroot-0.so" ] && continue + [ "$FILE" == "not" ] && FILE="$FILE $ADDR" + NAMES[$n]="$NAME" + FILES[$n]="$FILE" + n=$((n+1)) + done << EOF + $(LD_TRACE_PRELINKING=1 LD_WARN= LD_TRACE_LOADED_OBJECTS=1 \ + $LDSO $bin 2>/dev/null) +EOF + + [ ${#FILES[*]} -eq 0 ] && return + + # we don't want the name of the binary in the list + if [ "${FILES[0]}" == "$bin" ]; then + FILES[0]="" + NAMES[0]="" + [ ${#FILES[*]} -eq 1 ] && return + fi + + declare -i n=0 + while [ $n -lt ${#FILES[*]} ]; do + FILE="${FILES[$n]}" + if [ "$FILE" == "not found" ]; then + cat 1>&2 <<EOF +There are missing files on your system. The dynamic object $bin +requires ${NAMES[$n]} n order to properly function. mkinitrd cannot continue. +EOF + exit 1 + fi + case "$FILE" in + /lib*) + TLIBDIR=`echo "$FILE" | sed 's,\(/lib[^/]*\)/.*$,\1,'` + BASE=`basename "$FILE"` + # Prefer nosegneg libs over direct segment accesses on i686. + if [ -f "$TLIBDIR/i686/nosegneg/$BASE" ]; then + FILE="$TLIBDIR/i686/nosegneg/$BASE" + # Otherwise, prefer base libraries rather than their optimized + # variants. + elif [ -f "$TLIBDIR/$BASE" ]; then + FILE="$TLIBDIR/$BASE" + fi + FILES[$n]="$FILE" + ;; + esac + dynamic="yes" + n=$((n+1)) + done + + DSO_DEPS="${FILES[@]}" +} + +readlink_() { + l=$(readlink "$1") + if ! test -e "$l"; then + echo "$(dirname "$1")/$l" + else + echo "$l" + fi +} + +indent_chars="_" +inst() { + if [ "$#" != "2" -a "$#" != "3" ];then + echo "usage: inst <file> <root> [<destination file>]" + return 1 + fi + local file="$1" ; shift + local root="${1%%/}/"; shift + local dest="${1##/}"; shift || true + [ -z "$dest" ] && dest="${file##/}" + + local old_indent_chars=${indent_chars} + indent_chars="${indent_chars} " + indent=${indent_chars:2} + + mkdir -p "$root/$(dirname $dest)" + + local RET=0 + local target="" + [ -L "$file" ] && target=$(readlink_ "$file") + if [ -n "$target" -a "$dest" != "$target" ]; then + if [ -e "$root$dest" ]; then + $debug && echo "${indent}$dest already exists" + RET=0 + else + $debug && echo "l${indent:1}$file -> $dest" + ln -sf "$(readlink "$file")" "$root$dest" + + inst "$target" "$root" "/lib/$(basename $target)" + l=`echo "$x" | sed -n 's,\(/lib[^/]*\)/.*$,\1,p'` + if [ -n "$l" ]; then + inst "$x" "$root" "$l"/`basename "$x"` + else + inst "$x" "$root" + fi + RET=$? + indent_chars=${old_indent_chars} + return $RET + fi + fi + + if [ -e "$root$dest" ]; then + # echo "${indent}$root$dest already exists" + RET=0 + else + if [ -n "$target" -a -L "$target" ]; then + inst "$target" "$root" + RET=$? + else + $debug && echo "${indent}$file -> $dest" + cp -aL "$file" "$root$dest" + + get_dso_deps "$file" + local DEPS="$DSO_DEPS" + for x in $DEPS ; do + $debug && echo "_${indent:1}$x (deb of $(basename $file)" + #TLIBDIR=`echo "${x#$XEN_LIB}" | sed -r 's,.*(/lib[^/]*)/.*$,\1,'` + #[ "$TLIBDIR" == "$(basename "$x")" ] && + TLIBDIR="/lib" + BASE=`basename "$x"` + inst "$x" "$root" "$TLIBDIR/$BASE" + done + RET=$? + fi + fi + indent_chars=${old_indent_chars} + return $RET +} diff --git a/stubdom-linux/mk-ramdisk-ioemu b/stubdom-linux/mk-ramdisk-ioemu new file mode 100755 index 0000000..9b222d1 --- /dev/null +++ b/stubdom-linux/mk-ramdisk-ioemu @@ -0,0 +1,124 @@ +#!/bin/bash + +XEN_ROOT="`pwd`/.." + +script_qemu_ifup="extra/qemu-ifup" +script_init="extra/initscript" + +debug=false +verbose= + +set -e +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$XEN_ROOT/tools/xenstore" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$XEN_ROOT/tools/libxc" + +source ./mk-ramdisk-common + +cp(){ + command cp $verbose "$@" +} + +rm -fr "$MNTIMAGE" "$IMAGE" + +mkdir -p "$MNTIMAGE"/{bin,etc,proc/xen,sys,lib,usr,dev,tmp} +ln -s ../lib "$MNTIMAGE"/usr/lib +ln -s lib "$MNTIMAGE"/lib64 + +echo "Building initrd in $MNTIMAGE" +#inst /bin/busybox "$MNTIMAGE" /bin/busybox +cp -L /bin/busybox "$MNTIMAGE/bin/busybox" +# Will use make install from qemu +make DESTDIR="$MNTIMAGE" -C qemu-build install +# this gather libs install on the system +inst "$MNTIMAGE/bin/qemu-system-i386" "$MNTIMAGE" /bin/qemu + +# this cp keep the link to ld-2.11.x.so +if test "`uname -m`" = x86_64; then + cp --no-dereference "/lib/ld-linux-x86-64.so.2" "$MNTIMAGE/lib/ld-linux-x86-64.so.2" +else + cp --no-dereference "/lib/ld-linux.so.2" "$MNTIMAGE/lib/ld-linux.so.2" +fi + +inst "$XEN_ROOT/tools/xenstore/xenstore-read" "$MNTIMAGE" "/bin/xenstore-read" + +cp "$script_qemu_ifup" "$MNTIMAGE/etc/" +chmod +x "$MNTIMAGE/etc/qemu-ifup" +cp "$script_init" "$MNTIMAGE/init" +chmod 755 "$MNTIMAGE/init" + +mkdir -p $MNTIMAGE/etc/udev +touch $MNTIMAGE/etc/udev/udev.conf + +findall() { + find "$@" +} + +ln -s busybox "$MNTIMAGE/bin/sleep" +ln -s busybox "$MNTIMAGE/bin/mount" + +try_make_disk=true +if $try_make_disk; then + stubdom_disk=stubdom-disk.img + rm -f $stubdom_disk + dd if=/dev/null of=$stubdom_disk bs=1M seek=40 + mkfs.ext2 -q -F -m0 $stubdom_disk + + cd "$MNTIMAGE" + stubdom_disk="../$stubdom_disk" + new_link(){ + image=$1 + link=$2 + target=`readlink $link` + dir=`dirname $link` + dir=${dir#./} + name_link=$(basename $link) + dir_inode=$(debugfs -R "stat /$dir" $image 2>/dev/null | + sed -nr 's/^Inode: ([[:digit:]]+)[[:space:]].*/\1/p') + test "$dir_inode" || echo 'no dir inode found' + test "$dir_inode" + while true; do + free_inode=$(debugfs -R "find_free_inode $dir_inode 0777" -w $image 2>/dev/null | + sed -nr 's/^Free inode found: ([[:digit:]]+)$/\1/p') + undel_output="$(debugfs -R "undel <$free_inode> /$dir/$name_link" -w $image 2>&1)" + if grep -q "make_link: No free space in the directory" <<<"$undel_output"; then + debugfs -R "expand_dir /$dir" -w $image 2>/dev/null + else + break + fi + done + debugfs -f <( + echo "cd /$dir" + echo "set_inode_field $name_link mode 0120777" + echo "set_inode_field $name_link size ${#target}" + # TODO still need to write the link into blocks + if test ${#target} -lt $((12*4)); then + # write into direct block + blockn=0 + while test "$target"; do + t="${target:0:4}" + target="${target:4}" + #convert a four charactere string into hexa + val=$(printf '0x%02x%02x%02x%02x\n' \'${t:3:1} \'${t:2:1} \'${t:1:1} \'${t:0:1}) + echo "set_inode_field $name_link block[$blockn] $val" + blockn=$((blockn+1)) + done + else + # write into a block + echo >&2 ".... write into block not implemented" + fi + ) -w $image >/dev/null 2>/dev/null + } + # TODO Should check for "copy_file: Could not allocate block in ext2 filesystem" + debugfs -f <(find . \ + \( -type d \! -name . -printf 'cd /\nmkdir %h/%f\n' \) \ + -o \( -type f -printf 'cd /%h\nwrite %h/%f %f\n' \) \ + | sed -re 's%^((mkdir|cd) )./%\1/%' ) -w $stubdom_disk >/dev/null + find . -type l | while read line; do + new_link $stubdom_disk "$line" + done + fsck.ext2 -fy $stubdom_disk || true + cd - >/dev/null +else + (cd "$MNTIMAGE"; findall . | cpio -H newc --quiet -o) >| "$IMAGE" || exit 1 + gzip -f "$IMAGE" +fi -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |