From 096642065e8e7398a957bebabbbc85b691bec3b4 Mon Sep 17 00:00:00 2001 From: varac Date: Tue, 9 Oct 2012 15:50:55 +0200 Subject: initial commit, create-guest-with-cloudinit + helper scripts --- create-guest-with-cloudinit | 92 +++++++++++++++++++++++++ libvirt-make-seed-disk | 152 ++++++++++++++++++++++++++++++++++++++++++ libvirt-write-disk-attach-xml | 23 +++++++ 3 files changed, 267 insertions(+) create mode 100755 create-guest-with-cloudinit create mode 100755 libvirt-make-seed-disk create mode 100755 libvirt-write-disk-attach-xml diff --git a/create-guest-with-cloudinit b/create-guest-with-cloudinit new file mode 100755 index 0000000..56eec5f --- /dev/null +++ b/create-guest-with-cloudinit @@ -0,0 +1,92 @@ +#!/bin/sh + +VG='vg01' +ETC='/etc/cloudinit' +VARDIR='/var/lib/libvirt/cloudinit' + +fail() { [ $# -eq 0 ] || echo "$@"; exit 1; } +bad_usage() { usage 1>&2; [ $# -eq 0 ] || fail "$@"; exit 1; } + +usage() { + cat < /dev/null 2>&1 +if [ $? -eq 0 ]; then fail "Domain $vmname is defined in libvirt. Please undefine first."; fi + + +lvcreate -L ${size}g -n $vmname $VG +virt-clone -o leap-baseimage-wheezy -n $vmname -f /dev/$VG/$vmname --force + +# resize second (root) partition +echo ",+," | sfdisk -N2 /dev/$VG/$vmname > /dev/null + +libvirt-make-seed-disk $VARDIR/$vmname-user-data.img $userdata +libvirt-write-disk-attach-xml $VARDIR/$vmname-user-data.img > $VARDIR/$vmname-disk-attach.xml + +echo +echo "Attached userdata-disk is at $VARDIR/$vmname-user-data.img" +echo +echo "Finished creating guest $vmname. Enjoy." +echo +echo Press to start the new guest. +read bogus + +echo +echo 'Starting new guest, attaching to console. Exit with Ctrl+]' +echo + +virsh start $vmname +sleep 2 +virsh attach-device $vmname $VARDIR/$vmname-disk-attach.xml +virsh console $vmname + +#do we really need to detach the cloud-init disk ? +#virsh detach-device $vmname $VARDIR/$vmname-disk-attach.xml + + diff --git a/libvirt-make-seed-disk b/libvirt-make-seed-disk new file mode 100755 index 0000000..01e386f --- /dev/null +++ b/libvirt-make-seed-disk @@ -0,0 +1,152 @@ +#!/bin/bash +VERBOSITY=0 +TEMP_D="" +DEF_DISK_FORMAT="raw" +#DEF_FILESYSTEM="iso9660" +DEF_FILESYSTEM="vfat" + +error() { echo "$@" 1>&2; } +errorp() { printf "$@" 1>&2; } +fail() { [ $# -eq 0 ] || error "$@"; exit 1; } +failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; } + +Usage() { + cat < my-meta-data + * ${0##*/} my-seed.img my-user-data my-meta-data + * kvm -net nic -net user,hostfwd=tcp::2222-:22 \\ + -drive file=disk1.img,if=virtio -drive file=my-seed.img,if=virtio + * ssh -p 2222 ubuntu@localhost +EOF +} + +bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; } +cleanup() { + [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" +} + +debug() { + local level=${1}; shift; + [ "${level}" -gt "${VERBOSITY}" ] && return + error "${@}" +} + +short_opts="hi:d:f:m:o:v" +long_opts="disk-format:,dsmode:,filesystem:,help,interfaces:,output:,verbose" +getopt_out=$(getopt --name "${0##*/}" \ + --options "${short_opts}" --long "${long_opts}" -- "$@") && + eval set -- "${getopt_out}" || + bad_Usage + +## <> +output="" +userdata="" +metadata="" +filesystem=$DEF_FILESYSTEM +diskformat=$DEF_DISK_FORMAT +interfaces=_unset +dsmode="" + + +while [ $# -ne 0 ]; do + cur=${1}; next=${2}; + case "$cur" in + -h|--help) Usage ; exit 0;; + -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; + -d|--disk-format) diskformat=$next; shift;; + -f|--filesystem) filesystem=$next; shift;; + -m|--dsmode) dsmode=$next; shift;; + -i|--interfaces) interfaces=$next; shift;; + --) shift; break;; + esac + shift; +done + +## check arguments here +## how many args do you expect? +[ $# -ge 2 ] || bad_Usage "must provide output, userdata" +[ $# -le 3 ] || bad_Usage "confused by additional args" + +output=$1 +userdata=$2 +metadata=$3 + +[ -n "$metadata" -a "${interfaces}" != "_unset" ] && + fail "metadata and --interfaces are incompatible" +[ -n "$metadata" -a -n "$dsmode" ] && + fail "metadata and dsmode are incompatible" +[ "$interfaces" = "_unset" -o -r "$interfaces" ] || + fail "$interfaces: not a readable file" + +TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") || + fail "failed to make tempdir" +trap cleanup EXIT + +if [ -n "$metadata" ]; then + cp "$metadata" "$TEMP_D/meta-data" || fail "$metadata: failed to copy" +else + iface_data="" + dsmode_data="" + [ "$interfaces" != "_unset" ] && + iface_data=$(sed ':a;N;$!ba;s/\n/\\n/g' "$interfaces") && + iface_data="\"interfaces\": '$iface_data'" + [ -n "$dsmode" ] && dsmode_data="\"dsmode\": \"$dsmode\"" + printf "{\n%s\n%s\n%s\n}" "\"instance-id\": \"iid-local01\"" \ + "${iface_data}" "${dsmode_data}" > "${TEMP_D}/meta-data" +fi + +if [ "$userdata" = "-" ]; then + cat > "$TEMP_D/user-data" || fail "failed to read from stdin" +else + cp "$userdata" "$TEMP_D/user-data" || fail "$userdata: failed to copy" +fi + +## alternatively, create a vfat filesystem with same files +img="$TEMP_D/seed.img" +truncate --size 100K "$img" || fail "failed truncate image" + +case "$filesystem" in + iso9660|iso) + genisoimage -output "$img" -volid cidata \ + -joliet -rock "$TEMP_D/user-data" "$TEMP_D/meta-data" \ + > "$TEMP_D/err" 2>&1 || + { cat "$TEMP_D/err" 1>&2; fail "failed to genisoimage"; } + ;; + vfat) + mkfs.vfat -n cidata "$img" || fail "failed mkfs.vfat" + mcopy -oi "$img" "$TEMP_D/user-data" "$TEMP_D/meta-data" :: || + fail "failed to copy user-data, meta-data to img" + ;; + *) fail "unknown filesystem $filesystem";; +esac + +[ "$output" = "-" ] && output="$TEMP_D/final" +qemu-img convert -f raw -O "$diskformat" "$img" "$output" || + fail "failed to convert to disk format $diskformat" + +[ "$output" != "$TEMP_D/final" ] || { cat "$output" && output="-"; } || + fail "failed to write to -" + +error "wrote ${output} with filesystem=$filesystem and diskformat=$diskformat" +# vi: ts=4 noexpandtab + diff --git a/libvirt-write-disk-attach-xml b/libvirt-write-disk-attach-xml new file mode 100755 index 0000000..e813452 --- /dev/null +++ b/libvirt-write-disk-attach-xml @@ -0,0 +1,23 @@ +#!/bin/sh -f + +disks="$1" && [ -n "$disks" ] || + { echo "must give disk image"; exit 1; } +name=${2:-my-example-dom} +devs=bcdefghij +n=0 +for disk in "$@"; do + disk=$(readlink -f "$disk") || { echo "failed to get path to $disk" 1>&2; exit 1; } + t=${devs#?} + dev=vd${devs%${t}} + devs=${devs#?} + n=$(($n+1)) + cat < + + + + + +EOF +done + -- cgit v1.2.3