1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
1 |
#!/bin/bash
|
2 |
||
3 |
VERBOSITY=0 |
|
4 |
TEMP_D="" |
|
5 |
HTTP_PID="" |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
6 |
XKVM_PID="" |
7 |
HTTP_PORT_TRIES=${HTTP_PORT_TRIES:-5} |
|
8 |
HTTP_PORT_MIN=${HTTP_PORT_MIN:-12000} |
|
9 |
HTTP_PORT_MAX=${HTTP_PORT_MAX:-65500} |
|
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
10 |
MY_D=$(dirname "$0") |
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
11 |
DEFAULT_ROOT_ARG="root=LABEL=cloudimg-rootfs" |
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
12 |
|
13 |
error() { echo "$@" 1>&2; } |
|
14 |
||
15 |
Usage() { |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
16 |
cat <<EOF
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
17 |
Usage: ${0##*/} [ options ] boot-image curtin install [args]
|
18 |
||
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
19 |
boot the image 'boot-image', so that it will run
|
1.1.1
by Scott Moser
Import upstream version 0.1.0~bzr75 |
20 |
curtin install [args]
|
21 |
after booting. 'curtin install [args]' can be any command'
|
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
22 |
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
23 |
options:
|
1.1.6
by Scott Moser
Import upstream version 0.1.0~bzr93 |
24 |
--add F[:T] add file 'F' to the curtin archive at T
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
25 |
-a | --append append args to kernel cmdline (--kernel)
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
26 |
-A | --arch A assume guest kernel architecture A
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
27 |
-d | --disk D add a disk 'D' format
|
28 |
(path[:size][:driver][:bsize][:devopts])
|
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
29 |
driver can be specified without size using path::driver
|
30 |
driver defaults to virtio-blk
|
|
31 |
bsize <logical>[,<physical>][,<min_io_size>]
|
|
32 |
bsize defaults to 512b sector size
|
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
33 |
opts is a comma delimitted list of property=value
|
34 |
elements. Examine qemu-kvm -device scsi-hd,? for
|
|
35 |
details.
|
|
36 |
--vnc D use -vnc D (mutually exclusive with --silent)
|
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
37 |
-h | --help show this message
|
38 |
-i | --initrd F use initramfs F
|
|
39 |
-k | --kernel F use kernel K
|
|
40 |
--mem K memory in Kb
|
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
41 |
-n | --netdev netdev can be 'user' or a bridge
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
42 |
-p | --publish F make file 'F' available in web server
|
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
43 |
--silent use -nographic
|
44 |
--vnc D use -vnc D (mutually exclusive with --silent)
|
|
45 |
directly through to qemu-system.
|
|
46 |
Note, qemu adds 5900 to port numbers. (:0 = port 5900)
|
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
47 |
--serial-log F : log to F (default 'serial.log')
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
48 |
--root-arg X pass 'X' through as the root= param when booting a
|
49 |
kernel. default: $DEFAULT_ROOT_PARAM
|
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
50 |
-v | --verbose be more verbose
|
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
51 |
--no-install-deps do not install insert '--install-deps'
|
52 |
on curtin command invocations
|
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
53 |
|
1.1.40
by Scott Moser
Import upstream version 0.1.0~bzr415 |
54 |
the following are passed through to xkvm:
|
55 |
--uefi-nvram
|
|
56 |
--bios
|
|
57 |
||
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
58 |
use of --kernel/--initrd will seed cloud-init via cmdline
|
59 |
rather than the local datasource
|
|
1.1.1
by Scott Moser
Import upstream version 0.1.0~bzr75 |
60 |
|
61 |
Example:
|
|
62 |
* boot myboot.img, and install my-root.tar.gz
|
|
63 |
${0##*/} myboot.img --publish my-root.tar.gz curtin \
|
|
64 |
install PUBURL/my-root.tar.gz
|
|
65 |
||
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
66 |
EOF
|
67 |
}
|
|
68 |
||
69 |
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; } |
|
70 |
cleanup() { |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
71 |
local msg="" pid="" |
72 |
[ ! -d "$TEMP_D" ] || msg="${msg:+$msg }remove temp dir ${TEMP_D}." |
|
73 |
[ -z "$HTTP_PID" ] || msg="${msg:+$msg }kill http pid ${HTTP_PID}." |
|
74 |
[ -z "$XKVM_PID" ] || msg="${msg:+$msg }kill xkvm pid ${XKVM_PID}." |
|
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
75 |
debug 1 "cleaning up [${SECONDS}s].${msg:+ $msg}" |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
76 |
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" |
77 |
for pid in ${XKVM_PID} ${HTTP_PID}; do |
|
78 |
kill $pid |
|
79 |
done
|
|
80 |
}
|
|
81 |
sighandle() { |
|
82 |
debug 1 "recieved $1" |
|
83 |
exit ${2:-1} |
|
84 |
}
|
|
85 |
||
86 |
register_signal_handlers() { |
|
87 |
local cur
|
|
88 |
for cur in TERM INT; do |
|
89 |
trap "sighandle $cur" "SIG$cur" |
|
90 |
done
|
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
91 |
}
|
92 |
||
93 |
debug() { |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
94 |
local level=${1}; shift; |
95 |
[ "${level}" -gt "${VERBOSITY}" ] && return |
|
96 |
error "${@}" |
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
97 |
}
|
98 |
||
99 |
get_my_ip() { |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
100 |
[ -z "$IP_ADDR" ] || { _RET="${IP_ADDR}"; return 0; } |
101 |
local Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
|
102 |
local iface ipaddr="" tmpf="" |
|
103 |
# work around LP: #1483440
|
|
104 |
cp "/proc/net/route" "${TEMP_D}/current-route" |
|
105 |
while read Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT; do |
|
106 |
[ "$Mask" = "00000000" ] && break |
|
107 |
done < "${TEMP_D}/current-route" |
|
108 |
iface="$Iface" |
|
109 |
ipaddr=$(LC_ALL=C /sbin/ip -4 addr list dev "$iface" scope global) || return |
|
110 |
ipaddr=${ipaddr#* inet } |
|
111 |
ipaddr=${ipaddr%%/*} |
|
112 |
_RET="$ipaddr" |
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
113 |
}
|
114 |
||
115 |
write_metadata() { |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
116 |
cat <<EOF
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
117 |
instance-id: 'inst-${RANDOM}'
|
118 |
EOF
|
|
119 |
}
|
|
120 |
||
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
121 |
write_pstate_config() { |
122 |
local pstate="$1" config1="$2" config2="$3" |
|
123 |
cat > "$config1" <<EOF |
|
124 |
#cloud-config
|
|
125 |
power_state:
|
|
126 |
mode: "$pstate"
|
|
127 |
EOF
|
|
128 |
sed -e "s,PSTATE,$pstate," > "$config2" <<"EOF" |
|
129 |
#upstart-job
|
|
130 |
# precise does not do cloud-config poweroff
|
|
131 |
description "power-state for precise"
|
|
132 |
start on stopped cloud-final |
|
133 |
console output |
|
134 |
task |
|
135 |
script |
|
136 |
[ "$(lsb_release -sc)" = "precise" ] || exit 0 |
|
137 |
target="PSTATE" |
|
138 |
msg="precise-powerstate: $target" |
|
139 |
case "$target" in |
|
140 |
on) exit 0;; |
|
141 |
off|poweroff) shutdown -P now "$msg";; |
|
142 |
reboot) shutdown -r now "$msg";; |
|
143 |
*) echo "$msg : unknown target"; exit 1;; |
|
144 |
esac
|
|
145 |
echo "$msg" |
|
146 |
exit 0 |
|
147 |
end script |
|
148 |
EOF |
|
149 |
}
|
|
150 |
||
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
151 |
write_userdata() { |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
152 |
local x
|
153 |
cat <<EOF
|
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
154 |
#cloud-config-archive
|
155 |
- type: text/cloud-config
|
|
156 |
content: |
|
|
157 |
password: passw0rd
|
|
158 |
chpasswd: { expire: False }
|
|
159 |
output: {all: '| tee -a /var/log/cloud-init-output.log'}
|
|
160 |
EOF
|
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
161 |
for x in "$@"; do |
162 |
printf "%s\n" "- |" && sed 's,^, ,' "$x" || return |
|
163 |
done
|
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
164 |
}
|
165 |
||
166 |
xkvm_check() { |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
167 |
command -v xkvm >/dev/null 2>&1 && return |
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
168 |
[ -x "$MY_D/xkvm" ] && PATH="$MY_D:$PATH" && return |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
169 |
cat 1>&2 <<EOF |
1.1.21
by Scott Moser
Import upstream version 0.1.0~bzr200 |
170 |
Unable to find 'xkvm' in PATH, should be in curtin's tools/ dir
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
171 |
EOF
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
172 |
return 1 |
173 |
}
|
|
174 |
||
175 |
_start_http() { |
|
176 |
local pubdir="$1" ip="$2" port="$3" |
|
177 |
local statfile="_datesum" contents="" burl="http://$ip:$port" |
|
178 |
local found="" hpid="" ret="" |
|
179 |
contents="$$:$(date +%s.%N)" |
|
180 |
echo "$contents" > "$pubdir/$statfile" |
|
181 |
( set -eb; cd "$pubdir" && |
|
182 |
exec python -m SimpleHTTPServer "$port" ) >"$pubdir/ws.log" 2>&1 & |
|
183 |
hpid=$! |
|
184 |
HTTP_PID=$hpid # set so cleanup cleans up during wget |
|
185 |
debug 3 "checking web service [pid=$hpid] on $burl" |
|
186 |
found=$(env -u http_proxy wget -q --waitretry=0.4 --retry-connrefused \ |
|
187 |
--tries=10 "$burl/$statfile" --timeout=4 -O - 2>/dev/null) && |
|
188 |
[ "$found" = "$contents" ] && { |
|
189 |
_RET=$hpid |
|
190 |
return 0 |
|
191 |
}
|
|
192 |
ret=$? |
|
193 |
kill $hpid && HTTP_PID="" |
|
194 |
return $ret |
|
195 |
}
|
|
196 |
||
197 |
start_http() { |
|
198 |
# start_http(pubdir, ip, port="", tries=5)
|
|
199 |
# starts a web service at 'port' that serves files in 'pubdir'
|
|
200 |
# waits until it is verified to be lisenting at ip
|
|
201 |
# if port is not provided, '$tries' random ports are tried.
|
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
202 |
#
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
203 |
# sets HTTP_PID and returns in _RET the port selected.
|
204 |
local pubdir="$1" ip="$2" port="$3" tries="${4:-5}" i="" |
|
205 |
[ -z "$ip" ] && ip="localhost" |
|
206 |
local pmin="$HTTP_PORT_MIN" pmax="$HTTP_PORT_MAX" ret="" tried="" |
|
207 |
local ptries="" |
|
208 |
ptries=( ) |
|
209 |
if [ -n "$port" ]; then |
|
210 |
ptries=( $port ) |
|
211 |
elif [ $(($pmax-$pmin+1)) -le $tries ]; then |
|
212 |
# if tries spans the whole range, then just try them all
|
|
213 |
local range=$(($pmax-$pmin+1)) |
|
214 |
for((i=0;i<$range;i++)); do |
|
215 |
ptries[$i]=$((pmin+$i)) |
|
216 |
done
|
|
217 |
else
|
|
218 |
for((i=0;i<$tries;i++)); do |
|
219 |
ptries[$i]="random" |
|
220 |
done
|
|
221 |
fi
|
|
222 |
for port in "${ptries[@]}"; do |
|
223 |
[ "$port" = "random" ] && port=$(($pmin+($RANDOM%($pmax+1-$pmin)))) |
|
224 |
debug 2 "trying http server $ip:$port" |
|
225 |
_start_http "$pubdir" "$ip" "$port" && |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
226 |
HTTP_PID="$_RET" && _RET="$port" && |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
227 |
debug 1 "serving $pubdir at http://$ip:$port/ in pid $HTTP_PID" && |
228 |
return 0 |
|
229 |
ret=$? |
|
230 |
tried="$tried $port" |
|
231 |
done
|
|
232 |
error "failed to start http on service on $ip tried ports: ${tried# }" |
|
233 |
return $ret |
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
234 |
}
|
235 |
||
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
236 |
find_apt_proxy() { |
237 |
# pick an apt proxy for the guest
|
|
238 |
local out="" |
|
239 |
||
240 |
# if user set uncommon 'apt_proxy', then trust it
|
|
241 |
[ -n "$apt_proxy" ] && echo "$apt_proxy" && return 0 |
|
242 |
||
243 |
# see if the host has an apt proxy configured, and use it
|
|
244 |
if command -v apt-config >/dev/null 2>&1; then |
|
245 |
out=$(apt-config shell x Acquire::HTTP::Proxy) && |
|
246 |
out=$(sh -c 'eval $1 && echo $x' -- "$out") && [ -n "$out" ] && |
|
247 |
echo "$out" && return |
|
248 |
fi
|
|
249 |
||
250 |
return 1 |
|
251 |
}
|
|
252 |
||
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
253 |
main() { |
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
254 |
local short_opts="a:A:d:h:i:k:n:p:v" |
1.1.40
by Scott Moser
Import upstream version 0.1.0~bzr415 |
255 |
local long_opts="add:,append:,arch:,bios:,disk:,dowait,help,initrd:,kernel:,mem:,netdev:,no-dowait,power:,publish:,root-arg:,silent,serial-log:,uefi-nvram:,verbose,vnc:" |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
256 |
local getopt_out="" |
257 |
getopt_out=$(getopt --name "${0##*/}" \ |
|
258 |
--options "${short_opts}" --long "${long_opts}" -- "$@") && |
|
259 |
eval set -- "${getopt_out}" || |
|
260 |
{ bad_Usage; return 1; } |
|
261 |
||
262 |
local seed="" |
|
263 |
local bootimg="" bootimg_dist="" target="" mem="1024" |
|
264 |
local udata="" ip="" http_port="${HTTP_PORT}" burl="" |
|
265 |
local tmp="" top_d |
|
266 |
local initrd="" kernel="" uappend="" iargs="" disk_args="" |
|
267 |
local pubs="" disks="" pstate="null" |
|
1.1.40
by Scott Moser
Import upstream version 0.1.0~bzr415 |
268 |
local bsize="512" |
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
269 |
local netdevs="" install_deps="--install-deps" |
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
270 |
local arch_hint="" |
271 |
local video="-curses -vga std" serial_log="serial.log" |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
272 |
local root_arg="$DEFAULT_ROOT_ARG" |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
273 |
# dowait: run xkvm with a '&' and then 'wait' on the pid.
|
274 |
# the reason to do this or not do this has to do with interactivity
|
|
275 |
# if detached with &, then user input will not go to xkvm.
|
|
276 |
# if *not* detached, then signal handling is blocked until
|
|
277 |
# the foreground subprocess returns. which means we can't handle
|
|
278 |
# a sigterm and kill xkvm.
|
|
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
279 |
# We default to dowait=false if input and output are a terminal
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
280 |
local dowait="" |
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
281 |
[ -t 0 -a -t 1 ] && dowait=false || dowait=true |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
282 |
pubs=( ) |
283 |
disks=( ) |
|
284 |
addfiles=( ) |
|
285 |
netdevs=( ) |
|
286 |
pt=( ) |
|
287 |
||
288 |
# if output is to a terminal, then set dowait default to false
|
|
289 |
[ -t 0 ] && dowait=false || dowait=true |
|
290 |
while [ $# -ne 0 ]; do |
|
291 |
cur=${1}; next=${2}; |
|
292 |
case "$cur" in |
|
293 |
--add) addfiles[${#addfiles[@]}]="$next"; shift;; |
|
294 |
-a|--append) uappend="$next"; shift;; |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
295 |
-A|--arch) arch_hint="$next"; shift;; |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
296 |
-d|--disk) disks[${#disks[@]}]="$next"; shift;; |
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
297 |
--dowait) pt[${#pt[@]}]="$cur"; dowait=true;; |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
298 |
-h|--help) Usage ; exit 0;; |
299 |
-i|--initrd) initrd="$next"; shift;; |
|
300 |
-k|--kernel) kernel="$next"; shift;; |
|
301 |
--mem) mem="$next"; shift;; |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
302 |
-n|--netdev) netdevs[${#netdevs[@]}]="$next"; shift;; |
303 |
--no-dowait) pt[${#pt[@]}]="$cur"; dowait=false;; |
|
304 |
--no-install-deps) install_deps="";; |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
305 |
--power)
|
306 |
case "$next" in |
|
307 |
off) pstate="poweroff";; |
|
308 |
on|none) pstate="null";; |
|
309 |
reboot) pstate="$next";; |
|
310 |
*) error "Invalid power state, must be: off, on, reboot";; |
|
311 |
esac
|
|
312 |
shift;;
|
|
313 |
-p|--publish) pubs[${#pub[@]}]="$next"; shift;; |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
314 |
--root-arg) root_arg="$next";; |
315 |
--serial-log) serial_log="$next"; shift;; |
|
316 |
--silent) video="-nographic";; |
|
1.1.40
by Scott Moser
Import upstream version 0.1.0~bzr415 |
317 |
--uefi-nvram|--bios) |
318 |
# handle all --opt=* pass through here.
|
|
319 |
pt[${#pt[@]}]="$cur=$next";; |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
320 |
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; |
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
321 |
--vnc)
|
322 |
video="-vnc $next" |
|
323 |
debug 1 "VNC requested - $next" |
|
324 |
shift;;
|
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
325 |
--) shift; break;; |
326 |
esac
|
|
327 |
shift;
|
|
328 |
done
|
|
329 |
||
330 |
# handle passing through '-v' if given
|
|
331 |
local t="" |
|
332 |
for((i=0;i<${VERBOSITY};i++)); do t="${t}v"; done |
|
333 |
[ -n "$t" ] && pt[${#pt[@]}]="-$t" |
|
334 |
||
335 |
[ $# -ge 0 ] || { bad_Usage "must provide boot-image"; return 1; } |
|
336 |
bootimg_dist="$1" |
|
337 |
shift
|
|
338 |
cmdargs=( "$@" ) |
|
339 |
||
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
340 |
xkvm_check || return |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
341 |
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") || |
342 |
{ error "failed to make tempdir"; return 1; } |
|
343 |
||
344 |
trap cleanup EXIT
|
|
345 |
register_signal_handlers |
|
346 |
||
347 |
if [ "${#disks[@]}" -eq 0 ]; then |
|
348 |
disks=( "${TEMP_D}/disk1.img" ) |
|
349 |
fi
|
|
350 |
||
351 |
bootimg_dist=$(readlink -f "$bootimg_dist") || |
|
352 |
{ error "bad bootimg $bootimg_dist"; return 1; } |
|
353 |
||
354 |
[ -z "$initrd" -o -f "$initrd" ] || |
|
355 |
{ error "initrd not a file: $initrd"; return 1; } |
|
356 |
[ -z "$kernel" -o -f "$kernel" ] || |
|
357 |
{ error "kernel not a file: $kernel"; return 1; } |
|
358 |
||
359 |
tmp=$(dirname "$0") && top_d=$(cd "$tmp" && cd .. && pwd) || |
|
360 |
{ error "failed to get dir for $0"; return 1; } |
|
361 |
||
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
362 |
local disk="" src="" size="" fmt="" out="" id="" driver="" if="" |
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
363 |
local split_input="" serial="" |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
364 |
disk_args=( ) |
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
365 |
id=1 |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
366 |
for disk in "${disks[@]}"; do |
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
367 |
((id++)) |
368 |
# 1=src
|
|
369 |
# 2=src:size
|
|
370 |
# 3=src:size:driver
|
|
371 |
# 4=src:size:driver:bsize
|
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
372 |
# 5=src:size:driver:bsize:devopts
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
373 |
src=$(echo $disk | awk -F: '{print $1}') |
374 |
size=$(echo $disk | awk -F: '{print $2}') |
|
375 |
driver=$(echo $disk | awk -F: '{print $3}') |
|
376 |
bsize=$(echo $disk | awk -F: '{print $4}') |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
377 |
devopts=$(echo $disk | awk -F: '{print $5}') |
378 |
||
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
379 |
if [ -z "${src}" ]; then |
380 |
error "Failed to provide disk source"
|
|
381 |
exit 1 |
|
382 |
fi
|
|
383 |
||
384 |
if [ -z "${size}" ]; then |
|
385 |
size=5G |
|
386 |
fi
|
|
387 |
||
388 |
if [ -z "${driver}" ]; then |
|
389 |
driver="virtio-blk" |
|
390 |
fi
|
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
391 |
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
392 |
if [ -z "${bsize}" ]; then |
393 |
bsize="512" |
|
394 |
fi
|
|
395 |
||
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
396 |
if [ ! -f "$src" ]; then |
397 |
qemu-img create -f raw "${src}" "$size" || |
|
398 |
{ error "failed create $src of size $size"; return 1; } |
|
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
399 |
fmt="raw" |
400 |
else
|
|
401 |
out=$(LANG=C qemu-img info "$src") && |
|
402 |
fmt=$(echo "$out" | awk '$0 ~ /^file format:/ { print $3 }') || |
|
403 |
{ error "failed to determine format of $src"; return 1; } |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
404 |
fi
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
405 |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
406 |
# prepend comma if passing devopts
|
407 |
if [ -n "${devopts}" ]; then |
|
408 |
devopts=",${devopts}" |
|
409 |
fi
|
|
410 |
||
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
411 |
# set logical/physical size blocksz is logical:phys
|
412 |
local logbs=$(round_up ${bsize%%:*}) |
|
413 |
local phybs=$(round_up ${bsize##*:}) |
|
414 |
local bs_args="logical_block_size=$logbs" |
|
415 |
bs_args="${bs_args},physical_block_size=$phybs" |
|
416 |
bs_args="${bs_args},min_io_size=$logbs" |
|
417 |
||
418 |
disk_args=( "${disk_args[@]}" "-drive" |
|
419 |
"file=${src},if=none,cache=unsafe,format=$fmt,id=drv${id},index=$id" ) |
|
420 |
||
421 |
disk_args=( "${disk_args[@]}" "-device" |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
422 |
"${driver},drive=drv${id},${bs_args}${devopts}" ) |
423 |
||
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
424 |
done
|
425 |
||
426 |
get_my_ip || { error "failed to get your ip. set IP_ADDR"; return 1; } |
|
427 |
ip=${_RET} |
|
428 |
||
429 |
local tok src pub fpath
|
|
430 |
# tok in pubs looks like file[:pubname]
|
|
431 |
# link them into the temp dir for publishing
|
|
432 |
for tok in "${pubs[@]}"; do |
|
433 |
case "$tok" in |
|
434 |
*:*) src="${tok%:*}"; pub="${tok##*:}";; |
|
435 |
*) src=${tok}; pub="";; |
|
436 |
esac
|
|
437 |
fpath=$(readlink -f "$src") || |
|
438 |
{ error "'$src': failed to get path"; return 1; } |
|
439 |
if [ -n "$pub" ]; then |
|
440 |
pub="${src##*/}" |
|
441 |
fi
|
|
442 |
ln -sf "$fpath" "${TEMP_D}/${pub}" |
|
443 |
done
|
|
444 |
||
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
445 |
start_http "${TEMP_D}" "$ip" "$http_port" "${HTTP_TRIES}" </dev/null || |
446 |
{ error "failed to start http service"; return 1; } |
|
447 |
http_port=$_RET |
|
448 |
burl="http://$ip:${http_port}/" |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
449 |
# now replace PUBURL anywhere in cmdargs
|
450 |
for((i=0;i<${#cmdargs[@]};i++)); do |
|
451 |
cmdargs[$i]=${cmdargs[$i]//PUBURL/$burl} |
|
452 |
done
|
|
453 |
||
454 |
local addargs="" f="" |
|
455 |
addargs=( ) |
|
456 |
for f in "${addfiles[@]}"; do |
|
457 |
if [ "${f#*:}" != "$f" ]; then |
|
458 |
addargs[${#addargs[@]}]="--add=$f" |
|
459 |
else
|
|
460 |
addargs[${#addargs[@]}]="--add=$f:${f##*/}" |
|
461 |
fi
|
|
462 |
done
|
|
463 |
||
464 |
# We now pack up --config= options for the user
|
|
465 |
# potentially should check to make sure they've not already done this
|
|
466 |
# as this updating could then be destructive / annoying
|
|
467 |
# specifically, it could be annoying if you had a config inside
|
|
468 |
# the image that you were meaning to reference, and we copied (or tried)
|
|
469 |
# the file from the host.
|
|
470 |
for((i=1;i<${#cmdargs[@]};i++)); do |
|
471 |
cur=${cmdargs[$i]} |
|
472 |
next=${cmdargs[$i+1]} |
|
473 |
stuffed_cfg="" |
|
474 |
fpath="" |
|
475 |
case "$cur" in |
|
476 |
--config|-c) |
|
477 |
fpath=$next; |
|
478 |
cmdargs[$i+1]="config/${fpath##*/}" |
|
479 |
;;
|
|
480 |
--config=*) |
|
481 |
fpath=${cur#--config=} |
|
482 |
cmdargs[$i]="--config=config/${fpath##*/}" |
|
483 |
;;
|
|
484 |
*) continue;; |
|
485 |
esac
|
|
486 |
addargs[${#addargs[@]}]="--add=config/${fpath##*/}:$fpath" |
|
487 |
done
|
|
488 |
||
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
489 |
if [ "${cmdargs[0]}" = "curtin" -a -n "$install_deps" ]; then |
490 |
# if this is a 'curtin' command, then also insert --install-deps
|
|
491 |
debug 1 "adding --install-deps to command" |
|
492 |
cmdargs=( curtin $install_deps "${cmdargs[@]:1}" ) |
|
493 |
fi
|
|
494 |
||
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
495 |
PYTHONPATH="${top_d}${PYTHONPATH:+${PYTHONPATH}}" \ |
496 |
"${top_d}/bin/curtin" pack "${addargs[@]}" -- \ |
|
497 |
"${cmdargs[@]}" > "${TEMP_D}/install-cmd" || |
|
498 |
{ error "failed to pack"; return 1; } |
|
499 |
||
500 |
udata="${TEMP_D}/user-data" |
|
501 |
mdata="${TEMP_D}/meta-data" |
|
502 |
||
503 |
local ccfiles="" |
|
504 |
ccfiles=( ) |
|
505 |
if [ -n "${pstate}" ]; then |
|
1.1.32
by Scott Moser
Import upstream version 0.1.0~bzr314 |
506 |
write_pstate_config "$pstate" "${TEMP_D}/pstate.1" "${TEMP_D}/pstate.2" |
507 |
ccfiles[${#ccfiles[@]}]="${TEMP_D}/pstate.1" |
|
508 |
ccfiles[${#ccfiles[@]}]="${TEMP_D}/pstate.2" |
|
509 |
fi
|
|
510 |
||
511 |
if tmp=$(find_apt_proxy); then |
|
512 |
debug 1 "using $tmp for proxy" |
|
513 |
printf '#cloud-config\napt_proxy: "%s"\n' "$tmp" > "${TEMP_D}/cc-proxy" |
|
514 |
ccfiles[${#ccfiles[@]}]="${TEMP_D}/cc-proxy" |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
515 |
fi
|
516 |
||
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
517 |
if command -v ssh-keys-list >/dev/null 2>&1; then |
518 |
ssh-keys-list cloud-config > "${TEMP_D}/cc-ssh-keys" && |
|
519 |
ccfiles[${#ccfiles[@]}]="${TEMP_D}/cc-ssh-keys" || |
|
520 |
{ error "failed to get users ssh keys."; return 1; } |
|
521 |
fi
|
|
522 |
||
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
523 |
write_metadata > "$mdata" || { error "failed to write meta-data"; return 1; } |
524 |
write_userdata "${TEMP_D}/install-cmd" "${ccfiles[@]}" > "$udata" || |
|
525 |
{ error "failed to write user-data"; return 1; } |
|
526 |
||
527 |
bootimg="${TEMP_D}/boot.img" |
|
528 |
qemu-img create -f qcow2 -b "${bootimg_dist}" "$bootimg" 2G || |
|
529 |
{ error "failed create from ${bootimg_dist}"; return 1; } |
|
530 |
||
531 |
local seedargs="" |
|
532 |
seedargs=() |
|
533 |
if [ -n "$kernel" ]; then |
|
534 |
local append="" root="" |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
535 |
# Note: root_arg is by default done by LABEL. This assumes
|
536 |
# a.) our root device is not multipath
|
|
537 |
# b.) no other disks attached will have this LABEL
|
|
538 |
# c.) the LABEL is in fact correct.
|
|
539 |
# all of these assumptions are true under vmtest.
|
|
540 |
if [ -z "$root_arg" ]; then |
|
541 |
debug 1 "WARN: root_arg is empty with kernel." |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
542 |
fi
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
543 |
append="${root_arg:+${root_arg} }ds=nocloud-net;seedfrom=$burl" |
544 |
||
545 |
local console_name="" |
|
546 |
case "${arch_hint}" in |
|
547 |
s390x) console_name="";; |
|
548 |
ppc64*) console_name="hvc0";; |
|
549 |
*) console_name="ttyS0";; |
|
550 |
esac
|
|
551 |
if [ -n "$console_name" ]; then |
|
552 |
append="${append} console=${console_name}" |
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
553 |
fi
|
554 |
append="${append} $uappend" |
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
555 |
seedargs=( "${seedargs[@]}" -kernel "$kernel" ) |
556 |
[ -n "$initrd" ] && seedargs=( "${seedargs[@]}" -initrd "$initrd" ) |
|
557 |
seedargs=( "${seedargs[@]}" -append "$append" ) |
|
558 |
else
|
|
559 |
seed="${TEMP_D}/seed.img" |
|
560 |
cloud-localds "$seed" "$udata" "$mdata" || |
|
561 |
{ error "failed cloud-localds"; return 1; } |
|
562 |
seedargs=( "-drive" "file=${seed},if=virtio,media=cdrom" ) |
|
563 |
fi
|
|
564 |
||
565 |
local netargs
|
|
566 |
netargs=( ) |
|
567 |
for dev in "${netdevs[@]}"; do |
|
1.1.34
by Scott Moser
Import upstream version 0.1.0~bzr359 |
568 |
netargs=( "${netargs[@]}" "--netdev=${dev}" ) |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
569 |
done
|
570 |
||
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
571 |
local cmd serial_args="" chardev_arg="" |
572 |
[ "${serial_log}" = "none" ] && serial_log="" |
|
573 |
if [ -n "${serial_log}" ]; then |
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
574 |
if [ "${arch_hint}" = "s390x" ]; then |
575 |
if [ "${serial_log}" = "stdio" ]; then |
|
576 |
chardev_arg="stdio" |
|
577 |
else
|
|
578 |
chardev_arg="file,path=${serial_log}" |
|
579 |
fi
|
|
580 |
serial_args="-nodefaults -chardev ${chardev_arg},id=charconsole0 -device sclpconsole,chardev=charconsole0,id=console0" |
|
581 |
else
|
|
582 |
serial_args="-serial file:${serial_log}" |
|
583 |
#debug mode serial_args="-serial ${serial_log} -monitor stdio"
|
|
584 |
fi
|
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
585 |
fi
|
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
586 |
# -monitor stdio
|
587 |
cmd=( |
|
1.1.34
by Scott Moser
Import upstream version 0.1.0~bzr359 |
588 |
xkvm "${pt[@]}" "${netargs[@]}" -- |
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
589 |
-m ${mem} ${serial_args} ${video} |
590 |
-drive "file=$bootimg,if=none,cache=unsafe,format=qcow2,id=boot,index=0" |
|
591 |
-device "virtio-blk,drive=boot"
|
|
1.1.34
by Scott Moser
Import upstream version 0.1.0~bzr359 |
592 |
"${disk_args[@]}" |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
593 |
"${seedargs[@]}" |
1.1.34
by Scott Moser
Import upstream version 0.1.0~bzr359 |
594 |
)
|
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
595 |
|
1.1.33
by Scott Moser
Import upstream version 0.1.0~bzr351 |
596 |
debug 1 "running with dowait=$dowait: ${cmd[*]}" |
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
597 |
local sstart=$SECONDS |
598 |
if $dowait; then |
|
599 |
"${cmd[@]}" & |
|
600 |
XKVM_PID=$! |
|
601 |
debug 1 "xkvm pid: $XKVM_PID. launch pid: $$" |
|
602 |
wait "${XKVM_PID}" |
|
603 |
ret=$? |
|
604 |
XKVM_PID="" |
|
605 |
else
|
|
606 |
"${cmd[@]}" |
|
607 |
ret=$? |
|
608 |
fi
|
|
609 |
debug 1 "xkvm returned $ret took $(($SECONDS-$sstart))" |
|
610 |
||
611 |
return $ret |
|
612 |
}
|
|
613 |
||
1.1.39
by Scott Moser
Import upstream version 0.1.0~bzr399 |
614 |
random_wwn() { |
615 |
# wwn must be a int64, less than (1 << 63) - 1
|
|
616 |
# we achieve this by combining 4 (1 << 15) ints
|
|
617 |
printf "0x%04x%04x%04x%04x" $RANDOM $RANDOM $RANDOM $RANDOM |
|
618 |
}
|
|
1.1.36
by Scott Moser
Import upstream version 0.1.0~bzr385 |
619 |
|
620 |
round_up() { |
|
621 |
local size="${1}" |
|
622 |
local multiple="${2:-512}" |
|
623 |
local max_size=$((32 * 1024)) # 32k max |
|
624 |
||
625 |
size=$(( (($size + $multiple - 1) / $multiple) * $multiple)) |
|
626 |
if [ $size -gt $max_size ]; then |
|
627 |
echo $max_size |
|
628 |
return
|
|
629 |
elif [ $size -lt $multiple ]; then |
|
630 |
echo $multiple |
|
631 |
return
|
|
632 |
fi
|
|
633 |
echo $size |
|
634 |
}
|
|
635 |
||
636 |
||
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
637 |
test_start_http() { |
638 |
# run this like:
|
|
639 |
# HTTP_PORT_MIN=59000 HTTP_PORT_MAX=63001 ./tools/launch \
|
|
640 |
# /tmp/smfoo localhost
|
|
641 |
VERBOSITY=3 |
|
642 |
trap cleanup EXIT
|
|
643 |
register_signal_handlers |
|
644 |
echo "mypid: $$" |
|
645 |
start_http "$@" || { ret=$?; echo "returned $ret"; return $ret; } |
|
646 |
ret=$? |
|
647 |
port=$_RET |
|
648 |
echo "pid $HTTP_PID is serving on $port" |
|
649 |
sleep ${SLEEPTIME:-3} & |
|
650 |
XKVM_PID=$! |
|
651 |
wait $XKVM_PID |
|
652 |
ret=$? |
|
653 |
XKVM_PID="" |
|
654 |
return $ret |
|
1
by Scott Moser
Import upstream version 0.1.0~bzr54 |
655 |
}
|
656 |
||
657 |
main "$@" |
|
658 |
||
1.1.30
by Scott Moser
Import upstream version 0.1.0~bzr275 |
659 |
# vi: ts=4 expandtab
|