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