Last active
December 29, 2016 18:44
-
-
Save cpswan/6221258 to your computer and use it in GitHub Desktop.
cloud-localds from Ubuntu 13.04 - place in /usr/bin on older dists (e.g. 12.04)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
VERBOSITY=0 | |
TEMP_D="" | |
DEF_DISK_FORMAT="raw" | |
DEF_FILESYSTEM="iso9660" | |
error() { echo "$@" 1>&2; } | |
errorp() { printf "$@" 1>&2; } | |
fail() { [ $# -eq 0 ] || error "$@"; exit 1; } | |
failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; } | |
Usage() { | |
cat <<EOF | |
Usage: ${0##*/} [ options ] output user-data [meta-data] | |
Create a disk for cloud-init to utilize nocloud | |
options: | |
-h | --help show usage | |
-d | --disk-format D disk format to output. default: raw | |
-f | --filesystem F filesystem format (vfat or iso), default: iso9660 | |
-i | --interfaces F write network interfaces file into metadata | |
-m | --dsmode M add 'dsmode' ('local' or 'net') to the metadata | |
default in cloud-init is 'net', meaning network is | |
required. | |
Example: | |
* cat my-user-data | |
#cloud-config | |
password: passw0rd | |
chpasswd: { expire: False } | |
ssh_pwauth: True | |
* echo "instance-id: \$(uuidgen || echo i-abcdefg)" > 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 | |
## <<insert default variables here>> | |
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\"" | |
# write json formatted user-data (json is a subset of yaml) | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment