2
by Ben Howard
Adding Azure image generation scripts |
1 |
#!/bin/bash
|
2 |
||
3 |
VERBOSITY=0 |
|
4 |
TEMP_D="" |
|
5 |
DEF_DISK_FORMAT="raw" |
|
6 |
DEF_FILESYSTEM="iso9660" |
|
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 |
EOF
|
|
38 |
}
|
|
39 |
||
40 |
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; } |
|
41 |
cleanup() { |
|
42 |
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" |
|
43 |
}
|
|
44 |
||
45 |
debug() { |
|
46 |
local level=${1}; shift; |
|
47 |
[ "${level}" -gt "${VERBOSITY}" ] && return |
|
48 |
error "${@}" |
|
49 |
}
|
|
50 |
||
51 |
short_opts="hi:d:f:m:o:v" |
|
52 |
long_opts="disk-format:,dsmode:,filesystem:,help,interfaces:,output:,verbose" |
|
53 |
getopt_out=$(getopt --name "${0##*/}" \ |
|
54 |
--options "${short_opts}" --long "${long_opts}" -- "$@") && |
|
55 |
eval set -- "${getopt_out}" || |
|
56 |
bad_Usage |
|
57 |
||
58 |
## <<insert default variables here>>
|
|
59 |
output="" |
|
60 |
userdata="" |
|
61 |
metadata="" |
|
62 |
filesystem=$DEF_FILESYSTEM |
|
63 |
diskformat=$DEF_DISK_FORMAT |
|
64 |
interfaces=_unset |
|
65 |
dsmode="" |
|
66 |
||
67 |
||
68 |
while [ $# -ne 0 ]; do |
|
69 |
cur=${1}; next=${2}; |
|
70 |
case "$cur" in |
|
71 |
-h|--help) Usage ; exit 0;; |
|
72 |
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; |
|
73 |
-d|--disk-format) diskformat=$next; shift;; |
|
74 |
-f|--filesystem) filesystem=$next; shift;; |
|
75 |
-m|--dsmode) dsmode=$next; shift;; |
|
76 |
-i|--interfaces) interfaces=$next; shift;; |
|
77 |
--) shift; break;; |
|
78 |
esac
|
|
79 |
shift;
|
|
80 |
done
|
|
81 |
||
82 |
## check arguments here
|
|
83 |
## how many args do you expect?
|
|
84 |
[ $# -ge 1 ] || bad_Usage "must provide output, userdata" |
|
85 |
[ $# -le 3 ] || bad_Usage "confused by additional args" |
|
86 |
||
87 |
output=$1 |
|
88 |
userdata=$2 |
|
89 |
metadata=$3 |
|
90 |
||
91 |
[ -n "$metadata" -a "${interfaces}" != "_unset" ] && |
|
92 |
fail "metadata and --interfaces are incompatible"
|
|
93 |
[ -n "$metadata" -a -n "$dsmode" ] && |
|
94 |
fail "metadata and dsmode are incompatible"
|
|
95 |
[ "$interfaces" = "_unset" -o -r "$interfaces" ] || |
|
96 |
fail "$interfaces: not a readable file" |
|
97 |
||
98 |
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") || |
|
99 |
fail "failed to make tempdir"
|
|
100 |
trap cleanup EXIT
|
|
101 |
||
102 |
if [ -n "$metadata" ]; then |
|
103 |
cp "$metadata" "$TEMP_D/meta-data" || fail "$metadata: failed to copy" |
|
104 |
else
|
|
105 |
{
|
|
106 |
echo "instance-id: iid-local01" |
|
107 |
[ -n "$dsmode" ] && echo "dsmode: $dsmode" |
|
108 |
[ -n "$interfaces" ] && echo "interfaces: |" && |
|
109 |
sed 's,^, ,' "$interfaces" |
|
110 |
} > "$TEMP_D/meta-data" |
|
111 |
fi
|
|
112 |
||
113 |
if [ "$userdata" = "-" ]; then |
|
114 |
cat > "$TEMP_D/user-data" || fail "failed to read from stdin" |
|
115 |
else
|
|
116 |
cp "$userdata" "$TEMP_D/user-data" || fail "$userdata: failed to copy" |
|
117 |
fi
|
|
118 |
||
119 |
## alternatively, create a vfat filesystem with same files
|
|
120 |
img="$TEMP_D/seed.img" |
|
121 |
truncate --size 100K "$img" || fail "failed truncate image" |
|
122 |
||
123 |
case "$filesystem" in |
|
124 |
iso9660|iso) |
|
125 |
genisoimage -output "$img" -volid cidata \ |
|
126 |
-joliet -rock "$TEMP_D/user-data" "$TEMP_D/meta-data" \ |
|
127 |
> "$TEMP_D/err" 2>&1 || |
|
128 |
{ cat "$TEMP_D/err" 1>&2; fail "failed to genisoimage"; } |
|
129 |
;;
|
|
130 |
vfat)
|
|
131 |
mkfs.vfat -n cidata "$img" || fail "failed mkfs.vfat" |
|
132 |
mcopy -oi "$img" "$TEMP_D/user-data" "$TEMP_D/meta-data" :: || |
|
133 |
fail "failed to copy user-data, meta-data to img"
|
|
134 |
;;
|
|
135 |
*) fail "unknown filesystem $filesystem";; |
|
136 |
esac
|
|
137 |
||
138 |
[ "$output" = "-" ] && output="$TEMP_D/final" |
|
139 |
qemu-img convert -f raw -O "$diskformat" "$img" "$output" || |
|
140 |
fail "failed to convert to disk format $diskformat" |
|
141 |
||
142 |
[ "$output" != "$TEMP_D/final" ] || { cat "$output" && output="-"; } || |
|
143 |
fail "failed to write to -"
|
|
144 |
||
145 |
error "wrote ${output} with filesystem=$filesystem and diskformat=$diskformat" |
|
146 |
# vi: ts=4 noexpandtab
|
|
147 |