This file is indexed.

/usr/bin/cloud-localds is in cloud-image-utils 0.27-0ubuntu9.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/bin/bash

VERBOSITY=0
TEMP_D=""
DEF_DISK_FORMAT="raw"
DEF_FILESYSTEM="iso9660"
CR="
"

error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; 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
     -H | --hostname    H   set hostname in metadata to H
     -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.
     -v | --verbose         increase verbosity

   Note, --dsmode, --hostname, and --interfaces are incompatible
   with metadata.

   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="hH:i:d:f:m:o:v"
long_opts="disk-format:,dsmode:,filesystem:,help,hostname:,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=""
hostname=""


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;;
		-H|--hostname) hostname=$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

if [ -n "$metadata" ]; then
	[ "$interfaces" = "_unset" -a -z "$dsmode" -a -z "$hostname" ] ||
		fail "metadata is incompatible with:" \
			"--interfaces, --hostname, --dsmode"
fi

[ "$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
	instance_id="iid-local01"
	iface_data=""
	[ "$interfaces" != "_unset" ] &&
		iface_data=$(sed ':a;N;$!ba;s/\n/\\n/g' "$interfaces")

	# write json formatted user-data (json is a subset of yaml)
	mdata=""
	for kv in "instance-id:$instance_id" "local-hostname:$hostname" \
		"interfaces:${iface_data}" "dsmode:$dsmode"; do
		key=${kv%%:*}
		val=${kv#*:}
		[ -n "$val" ] || continue
		mdata="${mdata:+${mdata},${CR}}\"$key\": \"$val\""
	done
	printf "{\n%s\n}\n" "$mdata" > "${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"
if [ "$diskformat" != "raw" ]; then
	qemu-img convert -f raw -O "$diskformat" "$img" "$output" ||
		fail "failed to convert to disk format $diskformat"
else
	cp "$img" "$output" ||
		fail "failed to copy image to $output"
fi

[ "$output" != "$TEMP_D/final" ] || { cat "$output" && output="-"; } ||
	fail "failed to write to -"

debug 1 "wrote ${output} with filesystem=$filesystem and diskformat=$diskformat"
# vi: ts=4 noexpandtab