destroy-vm.sh: script to destroy a VM
[leap_cloudadmin.git] / libvirt-make-seed-disk
1 #!/bin/bash
2 VERBOSITY=0
3 TEMP_D=""
4 DEF_DISK_FORMAT="raw"
5 #DEF_FILESYSTEM="iso9660"
6 DEF_FILESYSTEM="vfat"
7
8 error() { echo "$@" 1>&2; }
9 errorp() { printf "$@" 1>&2; }
10 fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
11 failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; }
12
13 Usage() {
14        cat <<EOF
15 Usage: ${0##*/} [ options ] output user-data [meta-data]
16
17   Create a disk for cloud-init to utilize nocloud
18
19   options:
20     -h | --help            show usage
21     -d | --disk-format D   disk format to output. default: raw
22     -f | --filesystem  F   filesystem format (vfat or iso), default: iso9660
23
24     -i | --interfaces  F   write network interfaces file into metadata
25     -m | --dsmode      M   add 'dsmode' ('local' or 'net') to the metadata
26                            default in cloud-init is 'net', meaning network is
27                            required.
28
29   Example:
30    * cat my-user-data
31      #cloud-config
32      password: passw0rd
33      chpasswd: { expire: False }
34      ssh_pwauth: True
35    * echo "instance-id: \$(uuidgen || echo i-abcdefg)" > my-meta-data
36    * ${0##*/} my-seed.img my-user-data my-meta-data
37    * kvm -net nic -net user,hostfwd=tcp::2222-:22 \\
38         -drive file=disk1.img,if=virtio -drive file=my-seed.img,if=virtio
39    * ssh -p 2222 ubuntu@localhost
40 EOF
41 }
42
43 bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
44 cleanup() {
45        [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
46 }
47
48 debug() {
49        local level=${1}; shift;
50        [ "${level}" -gt "${VERBOSITY}" ] && return
51        error "${@}"
52 }
53
54 short_opts="hi:d:f:m:o:v"
55 long_opts="disk-format:,dsmode:,filesystem:,help,interfaces:,output:,verbose"
56 getopt_out=$(getopt --name "${0##*/}" \
57        --options "${short_opts}" --long "${long_opts}" -- "$@") &&
58        eval set -- "${getopt_out}" ||
59        bad_Usage
60
61 ## <<insert default variables here>>
62 output=""
63 userdata=""
64 metadata=""
65 filesystem=$DEF_FILESYSTEM
66 diskformat=$DEF_DISK_FORMAT
67 interfaces=_unset
68 dsmode=""
69
70
71 while [ $# -ne 0 ]; do
72        cur=${1}; next=${2};
73        case "$cur" in
74                -h|--help) Usage ; exit 0;;
75                -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
76                -d|--disk-format) diskformat=$next; shift;;
77                -f|--filesystem) filesystem=$next; shift;;
78                -m|--dsmode) dsmode=$next; shift;;
79                -i|--interfaces) interfaces=$next; shift;;
80                --) shift; break;;
81        esac
82        shift;
83 done
84
85 ## check arguments here
86 ## how many args do you expect?
87 [ $# -ge 2 ] || bad_Usage "must provide output, userdata"
88 [ $# -le 3 ] || bad_Usage "confused by additional args"
89
90 output=$1
91 userdata=$2
92 metadata=$3
93
94 [ -n "$metadata" -a "${interfaces}" != "_unset" ] &&
95        fail "metadata and --interfaces are incompatible"
96 [ -n "$metadata" -a -n "$dsmode" ] &&
97        fail "metadata and dsmode are incompatible"
98 [ "$interfaces" = "_unset" -o -r "$interfaces" ] ||
99        fail "$interfaces: not a readable file"
100
101 TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
102        fail "failed to make tempdir"
103 trap cleanup EXIT
104
105 if [ -n "$metadata" ]; then
106        cp "$metadata" "$TEMP_D/meta-data" || fail "$metadata: failed to copy"
107 else
108        iface_data=""
109        dsmode_data=""
110        [ "$interfaces" != "_unset" ] &&
111                iface_data=$(sed ':a;N;$!ba;s/\n/\\n/g' "$interfaces") &&
112                iface_data="\"interfaces\": '$iface_data'"
113        [ -n "$dsmode" ] && dsmode_data="\"dsmode\": \"$dsmode\""
114        printf "{\n%s\n%s\n%s\n}" "\"instance-id\": \"iid-local01\"" \
115                "${iface_data}" "${dsmode_data}" > "${TEMP_D}/meta-data"
116 fi
117
118 if [ "$userdata" = "-" ]; then
119        cat > "$TEMP_D/user-data" || fail "failed to read from stdin"
120 else
121        cp "$userdata" "$TEMP_D/user-data" || fail "$userdata: failed to copy"
122 fi
123
124 ## alternatively, create a vfat filesystem with same files
125 img="$TEMP_D/seed.img"
126 truncate --size 100K "$img" || fail "failed truncate image"
127
128 case "$filesystem" in
129        iso9660|iso)
130                genisoimage  -output "$img" -volid cidata \
131                        -joliet -rock "$TEMP_D/user-data" "$TEMP_D/meta-data" \
132                        > "$TEMP_D/err" 2>&1 ||
133                        { cat "$TEMP_D/err" 1>&2; fail "failed to genisoimage"; }
134                ;;
135        vfat)
136                mkfs.vfat -n cidata "$img" || fail "failed mkfs.vfat"
137                mcopy -oi "$img" "$TEMP_D/user-data" "$TEMP_D/meta-data" :: ||
138                        fail "failed to copy user-data, meta-data to img"
139                ;;
140        *) fail "unknown filesystem $filesystem";;
141 esac
142
143 [ "$output" = "-" ] && output="$TEMP_D/final"
144 qemu-img convert -f raw -O "$diskformat" "$img" "$output" ||
145        fail "failed to convert to disk format $diskformat"
146
147 [ "$output" != "$TEMP_D/final" ] || { cat "$output" && output="-"; } ||
148        fail "failed to write to -"
149
150 error "wrote ${output} with filesystem=$filesystem and diskformat=$diskformat"
151 # vi: ts=4 noexpandtab
152