Merge lp:~jtv/orchestra/odev-without-apt-get-update into lp:orchestra
- odev-without-apt-get-update
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~jtv/orchestra/odev-without-apt-get-update |
Merge into: | lp:orchestra |
Diff against target: |
1715 lines (+1591/-0) (has conflicts) 24 files modified
HOWTO (+41/-0) HOWTO.juju (+68/-0) README.txt (+5/-0) TODO (+14/-0) api-list.py (+36/-0) bin/authorize-ssh (+39/-0) bin/start-odev (+26/-0) bin/system-setup (+50/-0) bin/virsh-listener (+27/-0) cobbler-server/README.txt (+8/-0) cobbler-server/build-image (+170/-0) cobbler-server/late_command.sh (+170/-0) cobbler-server/preseed.cfg (+61/-0) cobbler-server/update-latecmd (+21/-0) libvirt-domain.tmpl (+56/-0) libvirt-network.tmpl (+23/-0) misc.txt (+67/-0) ref/cobbler.xml (+61/-0) ref/net.xml (+12/-0) ref/node01.xml (+54/-0) settings.cfg (+24/-0) setup.py (+217/-0) zimmer-build/build (+271/-0) zimmer-build/ud-build.txt (+70/-0) Conflict adding file bin. Moved existing file to bin.moved. |
To merge this branch: | bzr merge lp:~jtv/orchestra/odev-without-apt-get-update |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
orchestra | Pending | ||
Review via email: mp+96514@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-03-08.
Commit message
Speed up system-setup: no more apt-get update, and bundle all checks for missing packages.
Description of the change
Installing the required packages was agonizingly slow and error-prone for Julian (who is no longer very close to the data centre). This should speed it up.
The trick I use to check of missing packages works on Lucid and Precise, which are the only systems I tried it on.
Unmerged revisions
- 115. By Jeroen T. Vermeulen
-
Leave 'apt-get update' out of the script, and check for uninstalled packages in one go (to save time).
- 114. By Scott Moser
-
add cobbler-web to zimmer explicitly
cobbler-web is no longer a dependency of orchestra-
provisioning- server.
But, we still want it. - 113. By Scott Moser
-
make genisoimage quiet in zimmer-build
- 112. By Scott Moser
-
put public-key metadata into correct file
- 111. By Scott Moser
-
actually add the --import-key flag to zimmer-build
- 110. By Scott Moser
-
HOWTO: use --import-keys=auto to zimmer-build/build
- 109. By Scott Moser
-
support importing user's keys into zimmer-build
the flag '--import-
keys=auto' will generally try to do the
right thing and get the user passwordless access to the built
zimmer system. - 108. By Scott Moser
-
HOWTO, system-setup, virsh-listener: streamline a bit
Changes here:
* system-setup now is in charge of asking user if they want
to log out and back in. It determines if the user is already
in the group, and will not do the 'read' if unneccessary
* system-setup now does not apt-get update or apt-get install
unless necessary.
* virsh-listener: move the message out of HOWTO to virsh-listener
in HOWTO, detach that process so HOWTO actually exits. - 107. By Scott Moser
-
zimmer-build/build: use NoCloud data source rather than OVF
This requires a newer (precise alpha-2) image, but is massively
simpler and doesn't require cloud-init checkout. - 106. By Scott Moser
-
install qemu-kvm as it is necessary
Preview Diff
1 | === added file 'HOWTO' |
2 | --- HOWTO 1970-01-01 00:00:00 +0000 |
3 | +++ HOWTO 2012-03-08 06:52:22 +0000 |
4 | @@ -0,0 +1,41 @@ |
5 | +#! /bin/bash -e |
6 | +# |
7 | +# This file documents how to get odev running on your system. But it's also |
8 | +# a script; you may find that you can just run it and get a working setup. |
9 | + |
10 | +## System-level setup. This needs to be done only once. |
11 | +./bin/system-setup |
12 | + |
13 | +## Build a zimmer image in this branch. |
14 | +pushd zimmer-build |
15 | +./build zimmer-disk0.img --import-keys=auto |
16 | +popd |
17 | + |
18 | +## Get zimmer and cobbler running. |
19 | +./bin/start-odev |
20 | + |
21 | +cobblerlogin=ubuntu@192.168.123.2 |
22 | +cat <<EOF |
23 | +While we're waiting for the server to come up, let's set up ssh login to |
24 | +the cobbler server at $cobblerlogin. |
25 | + |
26 | +Please enter your Launchpad login name to import your ssh keys from Launchpad, |
27 | +or an asterisk ("*") to import your local public ssh keys. Enter nothing to |
28 | +skip this step. |
29 | + |
30 | +(If the server prompts you for a password, the default is "passw0rd") |
31 | +EOF |
32 | +read keyowner |
33 | +./bin/authorize-ssh $cobblerlogin $keyowner |
34 | + |
35 | +## populate the nodes into the cobbler server |
36 | +./setup.py cobbler-setup |
37 | + |
38 | +## Listen for libvirt requests from the Cobbler server. |
39 | +VIRSH_LISTENER_DEBUG=1 ./bin/virsh-listener & |
40 | + |
41 | + |
42 | +## at this point you may want to modify zimmer to provide a proxy |
43 | +## other than itself to things installing from it (LP: #914202). |
44 | +## ssh to zimmer, and then edit : |
45 | +## /var/lib/cobbler/snippets/orchestra_proxy |
46 | |
47 | === added file 'HOWTO.juju' |
48 | --- HOWTO.juju 1970-01-01 00:00:00 +0000 |
49 | +++ HOWTO.juju 2012-03-08 06:52:22 +0000 |
50 | @@ -0,0 +1,68 @@ |
51 | +# http://askubuntu.com/questions/65359/how-do-i-configure-juju-for-local-usage |
52 | + |
53 | +pkgs="libzookeeper-java zookeeper juju bzr" |
54 | + |
55 | +JUJU_D=$HOME/juju |
56 | +JUJU_ORIGIN="lp:juju" |
57 | +JUJU_SERIES="precise" |
58 | + |
59 | +REPO="$HOME/charms" |
60 | +CHARMS_D="$CHARMS_D/$JUJU_SERIES" |
61 | + |
62 | +ZIMMER_IP=192.168.123.2 |
63 | + |
64 | +id_rsa="$HOME/.ssh/id_rsa" |
65 | +[ -f "$id_rsa" ] || ssh-keygen -t rsa -N '' -f "$id_rsa" |
66 | +read x y z < "$id_rsa" |
67 | +grep -q "$y" ~/.ssh/authorized_keys || |
68 | + cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys |
69 | + |
70 | +sudo apt-get --assume-yes install $pkgs </dev/null |
71 | + |
72 | +mkdir -p "${JUJU_D%/*}" |
73 | +#( cd ${JUJU_D%/*} && bzr branch lp:juju ) |
74 | +( cd ${JUJU_D%/*} && bzr branch $JUJU_ORIGIN juju ) |
75 | + |
76 | +mkdir -p "$CHARMS_D" |
77 | +( cd "$CHARMS_D" && bzr branch lp:charm/mysql && bzr branch lp:charm/wordpress ) |
78 | + |
79 | +ENAME="odev" |
80 | + |
81 | +mkdir ~/.juju/ |
82 | +cat > ~/.juju/environments.yaml <<EOF |
83 | +environments: |
84 | + $ENAME: |
85 | + type: orchestra |
86 | + juju-origin: $JUJU_ORIGIN |
87 | + orchestra-server: $ZIMMER_IP |
88 | + orchestra-user: cobbler |
89 | + orchestra-pass: xcobbler |
90 | + acquired-mgmt-class: orchestra-juju-acquired |
91 | + available-mgmt-class: orchestra-juju-available |
92 | + admin-secret: SEEKRIT |
93 | + storage-url: http://$ZIMMER_IP/webdav |
94 | + authorized-keys: $(cat ~/.ssh/id_rsa.pub) |
95 | + data-dir: $HOME/juju-data/$ENAME |
96 | + default-series: $JUJU_SERIES |
97 | +EOF |
98 | + |
99 | +export PATH="$JUJU_D/bin:$HOME/bin:/usr/sbin:/usr/bin:/sbin:/bin" PYTHONPATH=$JUJU_D |
100 | + |
101 | +# now start your juju bootstrap node. this will take some time, as we're |
102 | +# doing a full install into the VM. |
103 | +juju bootstrap --environment $ENAME |
104 | + |
105 | +# now create the mysql and wordpress units |
106 | +# this takes quite a while as full VM install of each |
107 | +juju deploy --environment $ENAME --repository $REPO local:mysql |
108 | +juju deploy --environment $ENAME --repository $REPO local:wordpress |
109 | + |
110 | +# now link the two |
111 | +juju add-relation --environment $ENAME wordpress mysql |
112 | + |
113 | +# juju status: |
114 | +# FIXME: resolution will try to use dns and will not work for nodes |
115 | +# workaround: can add 192.168.123.1 to /etc/resolv.conf 'server' line |
116 | +# FIXME: juju status hangs "connecting to environment" during bootstrap |
117 | +# node installation. The post should call home and indicate done. so |
118 | +# juju could/should know that its still installing. |
119 | |
120 | === added file 'README.txt' |
121 | --- README.txt 1970-01-01 00:00:00 +0000 |
122 | +++ README.txt 2012-03-08 06:52:22 +0000 |
123 | @@ -0,0 +1,5 @@ |
124 | +This allows you to create a VM cobbler provisioning environment in |
125 | +a single system. That allows development working with cobbler or the |
126 | +API without need for lots of hardware. |
127 | + |
128 | + |
129 | |
130 | === added file 'TODO' |
131 | --- TODO 1970-01-01 00:00:00 +0000 |
132 | +++ TODO 2012-03-08 06:52:22 +0000 |
133 | @@ -0,0 +1,14 @@ |
134 | +- prefix names with 'odev' (or some prefix) |
135 | +- settings.cfg: add 'cobbler' section for auth |
136 | +- improve the Domain objects |
137 | +- document |
138 | + - vinagre $(virsh vncdisplay node01) |
139 | + - ssh -L 5901:localhost:5901 -L 8000:192.168.123.2:80 |
140 | + - start ssh connection to remote system with a bunch of ports |
141 | + forwarded for vnc connections and http to the zimmer box |
142 | + ssh -C home-jimbo \ |
143 | + $(t=98; for((i=0;i<5;i++)); do p=$(printf "%02d" "$i"); echo -L $t$p:localhost:59$p; done ; echo -L${t}80:192.168.123.2:80) |
144 | +- tell orchestra to point to a different proxy server |
145 | +- document or fix annoying ssh key entries (juju prompt for add and change) |
146 | +- get serial consoles to log file for domains |
147 | +- support i386 (for i386 installs of ubuntu) |
148 | |
149 | === added file 'api-list.py' |
150 | --- api-list.py 1970-01-01 00:00:00 +0000 |
151 | +++ api-list.py 2012-03-08 06:52:22 +0000 |
152 | @@ -0,0 +1,36 @@ |
153 | +#!/usr/bin/python |
154 | + |
155 | +import xmlrpclib |
156 | +import sys |
157 | + |
158 | +host = "192.168.123.2" |
159 | +user = "cobbler" |
160 | +password = "cobbler" |
161 | +if len(sys.argv) >= 2: |
162 | + host = sys.argv[1] |
163 | +if len(sys.argv) >= 3: |
164 | + user = sys.argv[2] |
165 | +if len(sys.argv) >= 4: |
166 | + password = sys.argv[3] |
167 | + |
168 | +if not host.startswith('http://'): |
169 | + host = "http://%s/cobbler_api" % host |
170 | + |
171 | +server = xmlrpclib.Server(host) |
172 | +token = server.login(user, password) |
173 | + |
174 | +distros = server.get_distros() |
175 | +print "::::::::::: distros :::::::::::" |
176 | +for d in server.get_distros(): |
177 | + print("%s: breed=%s, os_version=%s, mgmt_classes=%s" % |
178 | + (d['name'], d['breed'], d['os_version'], d['mgmt_classes'])) |
179 | + |
180 | +profiles = server.get_profiles() |
181 | +print "\n::::::::::: profiles :::::::::::" |
182 | +for d in server.get_profiles(): |
183 | + print("%s: distro=%s parent=%s kickstart=%s" % |
184 | + (d['name'], d['distro'], d['parent'], d['kickstart'])) |
185 | + |
186 | +print "\n::::::::::: servers :::::::::::" |
187 | +for s in server.get_systems(): |
188 | + print s['interfaces'] |
189 | |
190 | === added directory 'bin' |
191 | === renamed directory 'bin' => 'bin.moved' |
192 | === added file 'bin/authorize-ssh' |
193 | --- bin/authorize-ssh 1970-01-01 00:00:00 +0000 |
194 | +++ bin/authorize-ssh 2012-03-08 06:52:22 +0000 |
195 | @@ -0,0 +1,39 @@ |
196 | +#! /bin/bash -e |
197 | +# |
198 | +# Wait for the virtual cobbler instance's ssh server to start up, and set up |
199 | +# passwordless login if desired. |
200 | +# |
201 | +# Usage: |
202 | +# authorize-ssh <cobbler-ssh-login> <key-owner> |
203 | +# |
204 | +# Where: |
205 | +# * cobbler-ssh-login is an ssh user/hostname, e.g. ubuntu@192.168.123.2 |
206 | +# * key-owner is a Launchpad login name, or * to use local keys, or nothing. |
207 | +# |
208 | +# If a Launchpad login name is given, import the associated ssh keys into the |
209 | +# cobbler instance. If key-owner is an asterisk, import the local public ssh |
210 | +# keys from ~/.ssh/id_*.pub |
211 | + |
212 | +cobblerlogin=$1 |
213 | +keyowner=$2 |
214 | + |
215 | +if test -z "$keyowner" |
216 | +then |
217 | + echo "Not setting up ssh keys." |
218 | + echo "I'll still test a login to Cobbler though." |
219 | + inputfiles=/dev/null |
220 | + remotecmd="uptime" |
221 | +elif test "$keyowner" = "*" |
222 | +then |
223 | + inputfiles=`ls ~/.ssh/id_*.pub` |
224 | + echo "Copying public key(s): $inputfiles" |
225 | + remotecmd="tee .ssh/authorized_keys" |
226 | +else |
227 | + inputfiles=/dev/null |
228 | + remotecmd="ssh-import-id $keyowner" |
229 | +fi |
230 | + |
231 | +while ! cat $inputfiles | ssh $cobblerlogin -o StrictHostKeyChecking=no $remotecmd |
232 | +do |
233 | + sleep 5 |
234 | +done |
235 | |
236 | === added file 'bin/start-odev' |
237 | --- bin/start-odev 1970-01-01 00:00:00 +0000 |
238 | +++ bin/start-odev 2012-03-08 06:52:22 +0000 |
239 | @@ -0,0 +1,26 @@ |
240 | +#! /bin/bash -e |
241 | +# |
242 | +# Get zimmer and cobbler running, assuming that zimmer has already been set up. |
243 | + |
244 | +## create libvirt xml files for nodes, zimmer, network |
245 | +./setup.py libvirt-setup |
246 | + |
247 | +## start odev-net network |
248 | +virsh -c qemu:///system net-start odev-net |
249 | + |
250 | +## create zimmer disk image qcow backing against pristine version |
251 | +qemu-img create -f qcow2 -b zimmer-build/zimmer-disk0.img zimmer-disk0.img |
252 | + |
253 | +## start zimmer instance / orchestra server |
254 | +virsh -c qemu:///system start zimmer |
255 | + |
256 | +cat <<EOF |
257 | +Starting orchestra server. |
258 | +You can now ssh ubuntu@192.168.123.2 (password: passw0rd). |
259 | +If you do that, you may run 'ssh-import-id' to import your ssh key. |
260 | + |
261 | +Access the cobbler UI on http://192.168.123.2/cobbler_web |
262 | +and log in with 'cobbler:xcobbler'. |
263 | +EOF |
264 | + |
265 | + |
266 | |
267 | === added file 'bin/system-setup' |
268 | --- bin/system-setup 1970-01-01 00:00:00 +0000 |
269 | +++ bin/system-setup 2012-03-08 06:52:22 +0000 |
270 | @@ -0,0 +1,50 @@ |
271 | +#! /bin/bash -e |
272 | +# |
273 | +# System-wide setup for odev. This requires sudo. |
274 | + |
275 | +## install some dependencies |
276 | +pkgs="" |
277 | +pkgs="$pkgs genisoimage coreutils" # for cloud-init's 'make-iso' |
278 | +pkgs="$pkgs python-libvirt libvirt-bin" # for libvirt interaction |
279 | +pkgs="$pkgs socat" # for libvirt-> cobbler |
280 | +pkgs="$pkgs python-cheetah" # for setup.py |
281 | +pkgs="$pkgs qemu-utils qemu-kvm" # needed generally |
282 | + |
283 | + |
284 | +need_packages_installed() { |
285 | + # Do any of the packages in $pkgs need installing? |
286 | + # (Show all installed versions for $pkgs, one per line, and grep for |
287 | + # blank lines in the output.) |
288 | + dpkg-query -f '${Version}\n' --show $pkgs | grep -q '^$' |
289 | +} |
290 | + |
291 | + |
292 | +if need_packages_installed |
293 | +then |
294 | + sudo apt-get install -y $pkgs </dev/null |
295 | +fi |
296 | + |
297 | +new_groups="" |
298 | +for group in libvirtd kvm |
299 | +do |
300 | + groups $USER | grep -q $group && continue |
301 | + sudo adduser $USER $group |
302 | + new_groups="${new_groups:+${new_groups} }${group}" |
303 | +done |
304 | + |
305 | +if [ -n "$new_groups" ] |
306 | +then |
307 | + cat <<EOF |
308 | +Done. |
309 | + |
310 | +The script just added you to the system group[s] $new_groups |
311 | + |
312 | +If you were not previously in these groups, you will need to log out and |
313 | +log back in again to make the changes take effect. |
314 | +EOF |
315 | + |
316 | + # The user may need to log out at this point. |
317 | + echo "Abort with ctrl-C if you need to log out first." |
318 | + echo "Otherwise, press <enter>." |
319 | + read |
320 | +fi |
321 | |
322 | === added file 'bin/virsh-listener' |
323 | --- bin/virsh-listener 1970-01-01 00:00:00 +0000 |
324 | +++ bin/virsh-listener 2012-03-08 06:52:22 +0000 |
325 | @@ -0,0 +1,27 @@ |
326 | +#!/bin/bash -e |
327 | + |
328 | +## * libvirt from the cobbler system: |
329 | +## after 'cobbler-setup' above is done, the cobbler system will know about |
330 | +## all the nodes and it will believe it can control them via the 'virsh' |
331 | +## power module. It is configured |
332 | +## to talk to qemu+tcp://192.168.123.1:65001/system . In order to allow |
333 | +## that to be valid we have to make libvirt listen on that port/interface. |
334 | +## This can be done moderately securely with 'socat'. Below, we tell socat |
335 | +## to forward tcp connections on 192.168.123.1:65001 to the libvirt unix |
336 | +## socket . It restricts connections to zimmer's IP address. |
337 | + |
338 | +sock="/var/run/libvirt/libvirt-sock" |
339 | + |
340 | +[ "${VIRSH_LISTENER_DEBUG:-0}" != "0" ] && cat <<EOF |
341 | +Starting virsh listener. |
342 | + |
343 | +You can verify this is working by powering a sytem on from the web-ui or |
344 | +the following on the cobbler server: |
345 | + |
346 | +zimmmer$ virsh -c qemu+tcp://192.168.123.1:65001/system |
347 | +EOF |
348 | + |
349 | +echo "Listening for libvirt requests on $sock." |
350 | +exec socat -d -d \ |
351 | + TCP4-LISTEN:65001,bind=192.168.123.1,range=192.168.123.2/32,fork \ |
352 | + UNIX-CONNECT:$sock |
353 | |
354 | === added directory 'cobbler-server' |
355 | === added file 'cobbler-server/README.txt' |
356 | --- cobbler-server/README.txt 1970-01-01 00:00:00 +0000 |
357 | +++ cobbler-server/README.txt 2012-03-08 06:52:22 +0000 |
358 | @@ -0,0 +1,8 @@ |
359 | +Build a cobbler image: |
360 | + $ time ./build-image -vv --preseed preseed.cfg oneiric amd64 8G |
361 | + |
362 | +to use a proxy, edit preseed.cfg, add something like: |
363 | +# Specifying the Mirror. |
364 | +d-i mirror/http/proxy string http://10.155.1.249:8000/ |
365 | + |
366 | +With correct IP and port. This will work well with squid-deb-proxy |
367 | |
368 | === added file 'cobbler-server/build-image' |
369 | --- cobbler-server/build-image 1970-01-01 00:00:00 +0000 |
370 | +++ cobbler-server/build-image 2012-03-08 06:52:22 +0000 |
371 | @@ -0,0 +1,170 @@ |
372 | +#!/bin/bash |
373 | + |
374 | +VERBOSITY=0 |
375 | +TEMP_D="" |
376 | +DEF_PRESEED="http://bit.ly/uquick" |
377 | +DEF_SIZE=4 |
378 | +DEF_MIRROR="http://archive.ubuntu.com/ubuntu" |
379 | +DEF_ARCH=$(uname -m) |
380 | +MY_DIR=${0%/*} |
381 | +PATH=$MYDIR:$PATH |
382 | + |
383 | +[ "$DEF_ARCH" = "x86_64" ] && DEF_ARCH=amd64 |
384 | + |
385 | +error() { echo "$@" 1>&2; } |
386 | +errorp() { printf "$@" 1>&2; } |
387 | +fail() { [ $# -eq 0 ] || error "$@"; exit 1; } |
388 | +failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; } |
389 | + |
390 | +Usage() { |
391 | + cat <<EOF |
392 | +Usage: ${0##*/} [ options ] release [ arch [ size ] ] |
393 | + |
394 | + Do an install of Ubuntu for release. |
395 | + arch : the arch to use (amd64 i386). Default: ${DEF_ARCH} |
396 | + size : size of the image (in GigaBytes). Default: ${DEF_SIZE} |
397 | + |
398 | + options: |
399 | + -o | --output IMAGE_FILE write the image to IMAGE_FILE |
400 | + default: <release>-<arch>.img |
401 | + -s | --preseed PRESEED use the preseed at preseed |
402 | + default: ${DEF_PRESEED} |
403 | + -m | --mirror MIRROR mirror to download iso from MIRROR |
404 | + default: ${DEF_MIRROR} |
405 | + --iso ISO use ISO file rather than downloading |
406 | +EOF |
407 | +} |
408 | + |
409 | +bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; } |
410 | +cleanup() { |
411 | + [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" |
412 | +} |
413 | + |
414 | +dl() { |
415 | + local url="$1" out="${2}" opts="" |
416 | + [ "$url" = "$out" ] && return |
417 | + [ $VERBOSITY -lt 1 ] && opts="-q" |
418 | + case "$url" in |
419 | + http://*|ftp://*) wget $opts "$url" -O "${out}";; |
420 | + *) cp -a "${url}" "${out}";; |
421 | + esac |
422 | +} |
423 | + |
424 | +debug() { |
425 | + local level=${1}; shift; |
426 | + [ "${level}" -ge "${VERBOSITY}" ] && return |
427 | + error "${@}" |
428 | +} |
429 | +update_latecommand() { |
430 | + local infile=$1 program=$2 replace=$3 base64="" |
431 | + base64=$(base64 --wrap 0 "${program}") |
432 | + # the '&' have to be escaped through sed |
433 | + str='f=$1; shift ; echo $0 | base64 --decode > "$f" \&\& chmod u+x "$f" \&\& "$f" "$@"' |
434 | + sed -e "s,$replace,in-target sh -c '$str' ${base64} /root/late-command," "${infile}" |
435 | +} |
436 | + |
437 | +short_opts="hm:o:p:v" |
438 | +long_opts="help,iso:,mirror:,output:,preseed:,verbose" |
439 | +getopt_out=$(getopt --name "${0##*/}" \ |
440 | + --options "${short_opts}" --long "${long_opts}" -- "$@") && |
441 | + eval set -- "${getopt_out}" || |
442 | + bad_Usage |
443 | + |
444 | +release="${DEF_RELEASE}" |
445 | +preseed="${DEF_PRESEED}" |
446 | +output="" |
447 | +mirror="${DEF_MIRROR}" |
448 | +arch="${DEF_ARCH}" |
449 | +iso="" |
450 | + |
451 | +while [ $# -ne 0 ]; do |
452 | + cur=${1}; next=${2}; |
453 | + case "$cur" in |
454 | + -h|--help) Usage ; exit 0;; |
455 | + -i|--iso) iso=${2}; shift;; |
456 | + -m|--mirror) mirror=${2}; shift;; |
457 | + -o|--output) output=${2}; shift;; |
458 | + -p|--preseed) preseed=${2}; shift;; |
459 | + -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; |
460 | + --) shift; break;; |
461 | + esac |
462 | + shift; |
463 | +done |
464 | + |
465 | +[ $# -ne 0 ] || bad_Usage "must provide arguments" |
466 | +[ $# -lt 1 -o $# -gt 3 ] && bad_Usage "must provide 1,2, or 3 args" |
467 | +release=$1 |
468 | +arch=${2:-${DEF_ARCH}} |
469 | +size=${3:-${DEF_SIZE}} |
470 | +size=${size%G} |
471 | + |
472 | +[ -n "$output" ] || output="${release}-${arch}.img" |
473 | + |
474 | +TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") || |
475 | + fail "failed to make tempdir" |
476 | +trap cleanup EXIT |
477 | + |
478 | +pre="${release}-${arch}" |
479 | +if [ -z "$iso" ]; then |
480 | + iso="${release}-${arch}-mini.iso" |
481 | + if [ -f "$iso" ]; then |
482 | + debug 1 "using existing iso ${iso}" |
483 | + else |
484 | + url="${mirror}/dists/$release/main/installer-$arch/current/images/netboot/mini.iso" |
485 | + debug 1 "downloading ${url}" |
486 | + dl "${url}" "${iso}" || fail "failed to download $iso from $url" |
487 | + fi |
488 | +fi |
489 | + |
490 | +dl "$preseed" $pre-preseed.cfg || |
491 | + fail "failed to download preseed: ${preseed}" |
492 | + |
493 | +update_latecommand $pre-preseed.cfg \ |
494 | + late_command.sh __LATE_COMMAND__ > "${TEMP_D}/preseed.cfg" || fail "failed to update_latecommand" |
495 | + |
496 | +debug 1 "extracting kernel and ramdisk" |
497 | +for f in /linux /initrd.gz ; do |
498 | + targ="${pre}-${f##*/}.dist" |
499 | + if [ ! "$targ" -nt "$iso" ]; then |
500 | + isoinfo -RJ -x "$f" -i "$iso" > "$targ" || |
501 | + fail "failed to extract $f from $iso" |
502 | + else |
503 | + debug 1 "skipping $targ, newer than $iso" |
504 | + fi |
505 | +done |
506 | + |
507 | +kernel="${pre}-linux.dist" |
508 | +initrd="${pre}-initrd.gz" |
509 | + |
510 | +if [ "$pre-preseed.cfg" -nt "$initrd" ]; then |
511 | + debug 1 "repacking initramfs" |
512 | + zcat "$initrd.dist" > "${TEMP_D}/initrd" && |
513 | + ( cd "${TEMP_D}" && echo "./preseed.cfg" | |
514 | + cpio -o --format=newc --append -F initrd && |
515 | + gzip -9 initrd -c ) > "${initrd}" || |
516 | + fail "failed to repack initrd" |
517 | +else |
518 | + debug 1 "not repacking $initrd, it is newer than $pre-preseed.cfg" |
519 | +fi |
520 | + |
521 | +debug 1 "creating a ${size}G disk in ${output}" |
522 | +rm -f "$output" |
523 | +qemu-img create -f qcow2 "${output}" "${size}G" || |
524 | + fail "failed to create image" |
525 | + |
526 | +time ${KVM:-kvm} -kernel "$kernel" -initrd "$initrd" \ |
527 | + -append "priority=critical locale=en_US" \ |
528 | + -drive "file=${output},if=virtio,cache=unsafe" \ |
529 | + -cdrom "${iso}" \ |
530 | + -m 1024 -boot d -no-reboot \ |
531 | + -net nic,model=virtio -net user || |
532 | + fail "kvm failed" |
533 | + |
534 | +debug 1 "restarting for first boot" |
535 | +time ${KVM:-kvm} \ |
536 | + -drive "file=${output},if=virtio,cache=unsafe" \ |
537 | + -m 512 -boot c -no-reboot \ |
538 | + -net nic,model=virtio -net user || |
539 | + fail "failed to reboot" |
540 | + |
541 | +# vi: ts=4 noexpandtab |
542 | |
543 | === added file 'cobbler-server/late_command.sh' |
544 | --- cobbler-server/late_command.sh 1970-01-01 00:00:00 +0000 |
545 | +++ cobbler-server/late_command.sh 2012-03-08 06:52:22 +0000 |
546 | @@ -0,0 +1,170 @@ |
547 | +#!/bin/bash |
548 | + |
549 | +{ |
550 | +fb_d="/root/first-boot.d" |
551 | +mkdir -p "$fb_d" |
552 | +sed -i '/^exit 0/d' /etc/rc.local |
553 | +cat >> /etc/rc.local <<EOF |
554 | +## first boot finish stuff |
555 | +if [ ! -f "$fb_d.done" ]; then |
556 | + run-parts "$fb_d" 2>&1 | tee "${fb_d}.log" |
557 | + touch "$fb_d.done" |
558 | +fi |
559 | +EOF |
560 | + |
561 | +cat >"$fb_d/10-addl-pkgs" <<"EOF" |
562 | +#!/bin/sh |
563 | +pkgs="ubuntu-orchestra-provisioning-server cman" |
564 | +[ -t 1 ] || { |
565 | + unset DEBIAN_HAS_FRONTEND DEBIAN_FRONTEND DEBCONF_REDIR DEBCONF_OLD_FD_BASE; |
566 | + export DEBIAN_FRONTEND=noninteractive; |
567 | +} |
568 | +if [ "$(lsb_release --codename --short)" = "natty" ]; then |
569 | + for p in ppa:orchestra/ppa ppa:dotdee/ppa; do apt-add-repository $p; done |
570 | +fi |
571 | +apt-get update |
572 | +apt-get install --assume-yes ${pkgs} |
573 | +EOF |
574 | + |
575 | +cat > "$fb_d/99-halt" <<EOF |
576 | +#!/bin/sh |
577 | +touch "$fb_d.done" |
578 | +/sbin/poweroff |
579 | +EOF |
580 | + |
581 | +cat >"$fb_d/50-setup-cobbler" <<"EOF" |
582 | +#!/bin/sh |
583 | + |
584 | +cp -a /etc/cobbler/settings /etc/cobbler/settings.dist |
585 | +sed -i 's,^next_server: .*,next_server: cobbler,' /etc/cobbler/settings |
586 | +sed -i 's,^server: .*,server: cobbler,' /etc/cobbler/settings |
587 | + |
588 | +# https://fedorahosted.org/cobbler/wiki/CobblerWebInterface |
589 | +# htdigest /etc/cobbler/users.digest "Cobbler" cobbler |
590 | +cat > /etc/cobbler/users.digest <<ENDUSERDIGEST |
591 | +cobbler:Cobbler:a2d6bae81669d707b72c0bd9806e01f3 |
592 | +ENDUSERDIGEST |
593 | + |
594 | +seed="/var/lib/cobbler/kickstarts/ensemble.preseed" |
595 | +cat > "$seed" <<"ENDPRESEED" |
596 | +# Ubuntu Server Quick Install for Orchestra deployed systems |
597 | +# by Dustin Kirkland <kirkland@ubuntu.com> |
598 | +# * Documentation: http://bit.ly/uquick-doc |
599 | + |
600 | +d-i debian-installer/locale string en_US.UTF-8 |
601 | +d-i debian-installer/splash boolean false |
602 | +d-i console-setup/ask_detect boolean false |
603 | +d-i console-setup/layoutcode string us |
604 | +d-i console-setup/variantcode string |
605 | +d-i netcfg/get_nameservers string |
606 | +d-i netcfg/get_ipaddress string |
607 | +d-i netcfg/get_netmask string 255.255.255.0 |
608 | +d-i netcfg/get_gateway string |
609 | +d-i netcfg/confirm_static boolean true |
610 | +d-i clock-setup/utc boolean true |
611 | +d-i partman-auto/method string regular |
612 | +d-i partman-lvm/device_remove_lvm boolean true |
613 | +d-i partman-lvm/confirm boolean true |
614 | +d-i partman/confirm_write_new_label boolean true |
615 | +d-i partman/choose_partition select Finish partitioning and write changes to disk |
616 | +d-i partman/confirm boolean true |
617 | +d-i partman/confirm_nooverwrite boolean true |
618 | +d-i partman/default_filesystem string ext4 |
619 | +d-i clock-setup/utc boolean true |
620 | +d-i clock-setup/ntp boolean true |
621 | +d-i clock-setup/ntp-server string ntp.ubuntu.com |
622 | +d-i base-installer/kernel/image string linux-server |
623 | +d-i passwd/root-login boolean false |
624 | +d-i passwd/make-user boolean true |
625 | +d-i passwd/user-fullname string ubuntu |
626 | +d-i passwd/username string ubuntu |
627 | +d-i passwd/user-password-crypted password $6$.1eHH0iY$ArGzKX2YeQ3G6U.mlOO3A.NaL22Ewgz8Fi4qqz.Ns7EMKjEJRIW2Pm/TikDptZpuu7I92frytmk5YeL.9fRY4. |
628 | +d-i passwd/user-uid string |
629 | +d-i user-setup/allow-password-weak boolean false |
630 | +d-i user-setup/encrypt-home boolean false |
631 | +d-i passwd/user-default-groups string adm cdrom dialout lpadmin plugdev sambashare |
632 | +d-i apt-setup/services-select multiselect security |
633 | +d-i apt-setup/security_host string security.ubuntu.com |
634 | +d-i apt-setup/security_path string /ubuntu |
635 | +d-i debian-installer/allow_unauthenticated string false |
636 | +d-i pkgsel/upgrade select safe-upgrade |
637 | +d-i pkgsel/language-packs multiselect |
638 | +d-i pkgsel/update-policy select none |
639 | +d-i pkgsel/updatedb boolean true |
640 | +d-i grub-installer/skip boolean false |
641 | +d-i lilo-installer/skip boolean false |
642 | +d-i grub-installer/only_debian boolean true |
643 | +d-i grub-installer/with_other_os boolean true |
644 | +d-i finish-install/keep-consoles boolean false |
645 | +d-i finish-install/reboot_in_progress note |
646 | +d-i cdrom-detect/eject boolean true |
647 | +d-i debian-installer/exit/halt boolean false |
648 | +d-i debian-installer/exit/poweroff boolean false |
649 | +d-i pkgsel/include string ubuntu-orchestra-client $getVar('EXTRA_PACKAGES','') |
650 | +byobu byobu/launch-by-default boolean true |
651 | +d-i preseed/late_command string true && \ |
652 | + $SNIPPET('ensemble_late_command') && \ |
653 | + $SNIPPET('disable_pxe') && \ |
654 | + true # add your late_commands here |
655 | +ENDPRESEED |
656 | + |
657 | +mkdir -p /var/lib/cobbler/snippets/ |
658 | +cat > /var/lib/cobbler/snippets/disable_pxe <<"ENDSNIP" |
659 | +wget "http://$http_server:$http_port/cblr/svc/op/nopxe/system/$system_name" -O /dev/null |
660 | +ENDSNIP |
661 | + |
662 | +cat > /var/lib/cobbler/snippets/ensemble_late_command <<"ENDSNIP" |
663 | +$getVar('ENSEMBLE_LATE_COMMAND', 'true') |
664 | +ENDSNIP |
665 | + |
666 | + |
667 | +mkdir -p /var/lib/cobbler/isos |
668 | +cd /var/lib/cobbler/isos |
669 | +set -- ${DISTS:-natty:i386 natty:amd64 oneiric:i386 oneiric:amd64} |
670 | +mirror="${MIRROR:-http://archive.ubuntu.com/ubuntu}" |
671 | +for t in "$@"; do |
672 | + rel=${t%:*}; arch=${t#*:} |
673 | + iso=$rel-$arch-mini.iso |
674 | + [ -f "$iso" ] && continue |
675 | + u=$mirror/dists/$rel/main/installer-$arch/current/images/netboot/mini.iso |
676 | + wget -O "$iso" "$u" |
677 | +done |
678 | + |
679 | +for t in "$@"; do |
680 | + rel=${t%:*}; arch=${t#*:} |
681 | + xa=$arch; [ "$arch" = "amd64" ] && xa=x86_64 |
682 | + mount -o loop $rel-$arch-mini.iso /mnt |
683 | + cobbler import --name=$rel-$arch --path=/mnt --breed=ubuntu --os-version=$rel --arch=$xa |
684 | + umount /mnt |
685 | + name=$rel-$xa |
686 | + ## cobbler wants to name distro and the default profile as <version>-<xa> (x86_64, not amd64) |
687 | + ## so, we just let it be. if we renamed, we'd have to do both profile and distribution |
688 | + ## [ "$xa" != "$arch" ] && |
689 | + ## cobbler profile rename --name $name --newname $rel-$arch && |
690 | + ## cobbler distro rename --name $name --newname $rel-$arch && |
691 | + ## name=$rel-$arch && |
692 | + ## cobbler profile edit --name $name --distro $name |
693 | + #fi |
694 | + cobbler profile edit --name $name --kopts="priority=critical locale=en_US" |
695 | + cobbler profile add --parent $name --name $name-ensemble --kickstart=$seed |
696 | +done |
697 | + |
698 | +# set up the webdav host |
699 | +a2enmod dav |
700 | +a2enmod dav_fs |
701 | +service apache2 restart |
702 | +cat > /etc/apache2/conf.d/dav.conf <<ENDWEBDAV |
703 | +Alias /webdav /var/lib/webdav |
704 | + |
705 | +<Directory /var/lib/webdav> |
706 | +Order allow,deny |
707 | +allow from all |
708 | +Dav On |
709 | +</Directory> |
710 | +ENDWEBDAV |
711 | +#EOF |
712 | + |
713 | +EOF |
714 | + |
715 | +chmod u+x "$fb_d"/* |
716 | +} 2>&1 | tee /root/late.log |
717 | |
718 | === added file 'cobbler-server/preseed.cfg' |
719 | --- cobbler-server/preseed.cfg 1970-01-01 00:00:00 +0000 |
720 | +++ cobbler-server/preseed.cfg 2012-03-08 06:52:22 +0000 |
721 | @@ -0,0 +1,61 @@ |
722 | +d-i debian-installer/locale string en_US.UTF-8 |
723 | +d-i debian-installer/splash boolean false |
724 | +d-i console-setup/ask_detect boolean false |
725 | +d-i console-setup/layoutcode string us |
726 | +d-i console-setup/variantcode string |
727 | +d-i netcfg/get_nameservers string |
728 | +d-i netcfg/get_ipaddress string |
729 | +d-i netcfg/get_netmask string 255.255.255.0 |
730 | +d-i netcfg/get_gateway string |
731 | +d-i netcfg/confirm_static boolean true |
732 | +d-i netcfg/get_hostname string cobbler |
733 | +d-i netcfg/get_hostname seen true |
734 | +#d-i netcfg/get_domain string unassigned-domain |
735 | +#d-i netcfg/get_domain seen true |
736 | +d-i clock-setup/utc boolean true |
737 | +d-i partman-auto/method string regular |
738 | +d-i partman-lvm/device_remove_lvm boolean true |
739 | +d-i partman-lvm/confirm boolean true |
740 | +d-i partman/confirm_write_new_label boolean true |
741 | +d-i partman/choose_partition select Finish partitioning and write changes to disk |
742 | +d-i partman/confirm boolean true |
743 | +d-i partman/confirm_nooverwrite boolean true |
744 | +d-i partman/default_filesystem string ext3 |
745 | +d-i clock-setup/utc boolean true |
746 | +d-i clock-setup/ntp boolean true |
747 | +d-i clock-setup/ntp-server string ntp.ubuntu.com |
748 | +d-i base-installer/kernel/image string linux-server |
749 | +d-i passwd/root-login boolean false |
750 | +d-i passwd/make-user boolean true |
751 | +d-i passwd/user-fullname string ubuntu |
752 | +d-i passwd/username string ubuntu |
753 | +d-i passwd/user-password-crypted password $6$.1eHH0iY$ArGzKX2YeQ3G6U.mlOO3A.NaL22Ewgz8Fi4qqz.Ns7EMKjEJRIW2Pm/TikDptZpuu7I92frytmk5YeL.9fRY4. |
754 | +d-i passwd/user-uid string |
755 | +d-i user-setup/allow-password-weak boolean false |
756 | +d-i user-setup/encrypt-home boolean false |
757 | +d-i passwd/user-default-groups string adm cdrom dialout lpadmin plugdev sambashare |
758 | +d-i apt-setup/services-select multiselect security |
759 | +d-i apt-setup/security_host string security.ubuntu.com |
760 | +d-i apt-setup/security_path string /ubuntu |
761 | +d-i debian-installer/allow_unauthenticated string false |
762 | +d-i pkgsel/upgrade select safe-upgrade |
763 | +d-i pkgsel/language-packs multiselect |
764 | +d-i pkgsel/update-policy select none |
765 | +d-i pkgsel/updatedb boolean true |
766 | +# additional packages to install |
767 | +d-i pkgsel/include string vim openssh-server python-software-properties libvirt-bin screen |
768 | +d-i grub-installer/skip boolean false |
769 | +d-i lilo-installer/skip boolean false |
770 | +d-i grub-installer/only_debian boolean true |
771 | +d-i grub-installer/with_other_os boolean true |
772 | +d-i finish-install/keep-consoles boolean false |
773 | +d-i finish-install/reboot_in_progress note |
774 | +d-i cdrom-detect/eject boolean true |
775 | +d-i debian-installer/exit/halt boolean false |
776 | +d-i debian-installer/exit/poweroff boolean false |
777 | +## Specifying the Mirror. |
778 | +#d-i mirror/http/proxy string http://192.168.1.102:8000/ |
779 | +## Finish specifying Mirror. |
780 | + |
781 | +byobu byobu/launch-by-default boolean true |
782 | +d-i preseed/late_command string __LATE_COMMAND__ |
783 | |
784 | === added file 'cobbler-server/update-latecmd' |
785 | --- cobbler-server/update-latecmd 1970-01-01 00:00:00 +0000 |
786 | +++ cobbler-server/update-latecmd 2012-03-08 06:52:22 +0000 |
787 | @@ -0,0 +1,21 @@ |
788 | +#!/bin/sh |
789 | + |
790 | +# replace 'replace' in file 'infile' with a sh snippit that will execute the |
791 | +# file/shell-script 'program' as a late-command. |
792 | +infile="${1}" |
793 | +program="$2" |
794 | +replace="${3:-__LATE_COMMAND__}" |
795 | +gzip=1 |
796 | + |
797 | +if [ "${gzip}" != "0" ]; then |
798 | + base64=$(gzip -c "${program}" | base64 --wrap 0) |
799 | + pipe_gunzip="| gunzip" |
800 | +else |
801 | + base64=$(base64 --wrap 0 "${program}" ) |
802 | + pipe_gunzip="" |
803 | +fi |
804 | +# the '&' have to be escaped through sed |
805 | +str='f=$1; shift ; echo $0 | base64 --decode '"$pipe_gunzip"' > "$f" \&\& chmod u+x "$f" \&\& "$f" "$@"' |
806 | + |
807 | +val="in-target sh -c '$str' ${base64} /root/late-command" |
808 | +sed -e "s,$replace,$val," "${infile}" |
809 | |
810 | === added file 'libvirt-domain.tmpl' |
811 | --- libvirt-domain.tmpl 1970-01-01 00:00:00 +0000 |
812 | +++ libvirt-domain.tmpl 2012-03-08 06:52:22 +0000 |
813 | @@ -0,0 +1,56 @@ |
814 | +<domain type='kvm'> |
815 | + <name>$name</name> |
816 | + <memory>$mem</memory> |
817 | + <currentMemory>$mem</currentMemory> |
818 | + <vcpu>1</vcpu> |
819 | + <os> |
820 | + <type arch='x86_64' machine='pc-0.12'>hvm</type> |
821 | + <boot dev='network' /> |
822 | + <boot dev='hd' /> |
823 | + </os> |
824 | + <features> |
825 | + <acpi/> |
826 | + <apic/> |
827 | + <pae/> |
828 | + </features> |
829 | + <clock offset='utc'/> |
830 | + <on_poweroff>destroy</on_poweroff> |
831 | + <on_reboot>restart</on_reboot> |
832 | + <on_crash>restart</on_crash> |
833 | + <devices> |
834 | + <emulator>/usr/bin/kvm</emulator> |
835 | + <disk type='file' device='disk'> |
836 | + <driver name='qemu' type='qcow2'/> |
837 | + <source file='$disk0'/> |
838 | + <target dev='vda' bus='virtio'/> |
839 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> |
840 | + </disk> |
841 | + <controller type='ide' index='0'> |
842 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> |
843 | + </controller> |
844 | + <interface type='network'> |
845 | + <!-- <boot order='1'/> --> |
846 | + <source network='$network'/> |
847 | + <target dev='vnet1'/> |
848 | + <model type='virtio'/> |
849 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> |
850 | + <mac address='$mac'/> |
851 | + </interface> |
852 | + <serial type='pty'> |
853 | + <source path='/dev/pts/5'/> |
854 | + <target port='0'/> |
855 | + </serial> |
856 | + <console type='pty'> |
857 | + <target type='serial' port='0'/> |
858 | + </console> |
859 | + <input type='mouse' bus='ps2'/> |
860 | + <graphics type='vnc' autoport='yes' keymap='en-us'/> |
861 | + <video> |
862 | + <model type='cirrus' vram='9216' heads='1'/> |
863 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> |
864 | + </video> |
865 | + <memballoon model='virtio'> |
866 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> |
867 | + </memballoon> |
868 | + </devices> |
869 | +</domain> |
870 | |
871 | === added file 'libvirt-network.tmpl' |
872 | --- libvirt-network.tmpl 1970-01-01 00:00:00 +0000 |
873 | +++ libvirt-network.tmpl 2012-03-08 06:52:22 +0000 |
874 | @@ -0,0 +1,23 @@ |
875 | +<network> |
876 | + <name>$name</name> |
877 | + <forward mode='nat'/> |
878 | + <bridge name='$bridge' stp='off' delay='0' /> |
879 | + <dns> |
880 | + <host ip='$ip_pre.1'> |
881 | + <hostname>host-system</hostname> |
882 | + </host> |
883 | + <host ip='$ip_pre.2'> |
884 | + <hostname>zimmer-server</hostname> |
885 | + </host> |
886 | + </dns> |
887 | + <ip address='$ip_pre.1' netmask='$netmask'> |
888 | + <dhcp> |
889 | + <range start='$ip_pre.$dhcp.range.start' end='$ip_pre.$dhcp.range.end' /> |
890 | + <bootp server="$all_systems.zimmer.ipaddr" file="pxelinux.0" /> |
891 | + #for $sys in $all_systems.itervalues() |
892 | + <host mac="$sys.mac" name="$sys.name" ip="$sys.ipaddr" /> |
893 | + #end for |
894 | + </dhcp> |
895 | + </ip> |
896 | +</network> |
897 | + |
898 | |
899 | === added file 'misc.txt' |
900 | --- misc.txt 1970-01-01 00:00:00 +0000 |
901 | +++ misc.txt 2012-03-08 06:52:22 +0000 |
902 | @@ -0,0 +1,67 @@ |
903 | +### apt-get install kvm-pxe ### |
904 | + |
905 | +## guest packages: |
906 | + ## squid-deb-proxy-client |
907 | + |
908 | +http://blog.dustinkirkland.com/2011/03/ubuntu-server-quick-install-no.html |
909 | + |
910 | +qemu-img create -f qcow2 disk.img 8G |
911 | +kvm -m 1024 -drive file=disk.img,if=virtio,cache=unsafe -cdrom ../iso/natty-release/ubuntu-11.04-server-amd64.iso -boot d -no-reboot |
912 | +priority=critical locale=en_US url=http://bit.ly/uquick |
913 | + |
914 | +mv disk.img disk.img.dist |
915 | +qemu-img create -f qcow2 -b disk.img.dist disk.img |
916 | + |
917 | +kvm -m 1024 -drive file=disk.img,if=virtio,cache=unsafe -cdrom ../iso/natty-release/ubuntu-11.04-server-amd64.iso -boot d |
918 | + |
919 | + |
920 | + |
921 | +sudo apt-get install python-software-properties |
922 | +for p in ppa:orchestra/ppa ppa:dotdee/ppa; do sudo apt-add-repository $p; done |
923 | +sudo apt-get update |
924 | +sudo apt-get install ubuntu-orchestra-provisioning-server |
925 | +sudo apt-get dist-upgrade |
926 | +sudo apt-get clean |
927 | +sudo apt-get update |
928 | +sudo poweroff |
929 | + |
930 | + |
931 | +mv disk.img disk.installed.img |
932 | +qemu-img create -f qcow2 -b disk.installed.img trash.img |
933 | +qemu-img create -f qcow2 -b disk.installed.img source.img |
934 | +qemu-img create -f qcow2 target.img 8G |
935 | + |
936 | +kvm -m 1024 \ |
937 | + -drive file=trash.img,if=virtio,cache=unsafe,index=0 \ |
938 | + -drive file=source.img,if=virtio,cache=unsafe,index=1 \ |
939 | + -drive file=target.img,if=virtio,cache=unsafe,index=2 \ |
940 | + -net nic,model=virtio -net user,hostfwd=tcp:127.0.0.1:2222-:22 \ |
941 | + |
942 | +ssh ubuntu@localhost -p 2222 |
943 | + |
944 | +sudo sfdisk -uS -d /dev/vdb > out |
945 | +sed -i 's,/dev/vdb,/dev/vdc,' out |
946 | +sudo sfdisk -uS /dev/vdc --force < out |
947 | +sudo dd if=/dev/vdb of=/dev/vdc bs=512 count=2048 |
948 | +sudo mkdir /mnt/src /mnt/target |
949 | +sudo mount -o ro /dev/vdb1 /mnt/src |
950 | +out=$(sudo blkid /dev/vdb1 | awk -F: '{print $2}') |
951 | +eval ${out} |
952 | +sudo mkfs.${TYPE} -U ${UUID} ${LABEL:+-L ${LABEL}} /dev/vdc1 |
953 | +out=$(sudo blkid /dev/vdb5 | awk -F: '{print $2}') |
954 | +eval ${out} |
955 | +sudo mkswap ${UUID:+-U ${UUID} } ${LABEL:+-L ${LABEL}} /dev/vdb5 |
956 | +sudo mount /dev/vdc1 /mnt/target |
957 | +sudo umount |
958 | +sudo rsync -aXHAS /mnt/src/ /mnt/target |
959 | +echo "cobbler" | sudo tee /mnt/target/etc/hostname |
960 | +sudo poweroff |
961 | + |
962 | +virsh -c qemu:///system net-dumpxml default # get the default, modify a bit |
963 | +virsh net-create libvirt-network-cobbler.xml |
964 | +virsh net-define libvirt-network-cobbler.xml |
965 | +virsh net-start cobbler |
966 | + |
967 | +virsh destroy cobbler-server; virsh undefine cobbler-server; virsh define libvirt-cobbler.xml |
968 | +nn="cobbler"; virsh net-destroy $nn; virsh net-undefine $nn; virsh net-define libvirt-network-cobbler.xml; virsh net-start $nn |
969 | + |
970 | |
971 | === added directory 'ref' |
972 | === added file 'ref/cobbler.xml' |
973 | --- ref/cobbler.xml 1970-01-01 00:00:00 +0000 |
974 | +++ ref/cobbler.xml 2012-03-08 06:52:22 +0000 |
975 | @@ -0,0 +1,61 @@ |
976 | +<domain type='kvm'> |
977 | + <name>cobbler-server</name> |
978 | + <uuid>ea9c555b-f860-6fff-d4d3-cae66cc76715</uuid> |
979 | + <memory>524288</memory> |
980 | + <currentMemory>524288</currentMemory> |
981 | + <vcpu>1</vcpu> |
982 | + <os> |
983 | + <type arch='x86_64' machine='pc-0.12'>hvm</type> |
984 | + <boot dev='hd'/> |
985 | + </os> |
986 | + <features> |
987 | + <acpi/> |
988 | + <apic/> |
989 | + <pae/> |
990 | + </features> |
991 | + <clock offset='utc'/> |
992 | + <on_poweroff>destroy</on_poweroff> |
993 | + <on_reboot>restart</on_reboot> |
994 | + <on_crash>restart</on_crash> |
995 | + <devices> |
996 | + <emulator>/usr/bin/kvm</emulator> |
997 | + <disk type='file' device='disk'> |
998 | + <driver name='qemu' type='qcow2'/> |
999 | + <source file='/home/download/orchestra-demo/cobbler-disk0.img'/> |
1000 | + <target dev='vda' bus='virtio'/> |
1001 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> |
1002 | + </disk> |
1003 | + <disk type='file' device='cdrom'> |
1004 | + <driver name='qemu' type='raw'/> |
1005 | + <source file='/home/download/orchestra-demo/cdrom-0.iso'/> |
1006 | + <target dev='hdc' bus='ide'/> |
1007 | + <readonly/> |
1008 | + <address type='drive' controller='0' bus='1' unit='0'/> |
1009 | + </disk> |
1010 | + <controller type='ide' index='0'> |
1011 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> |
1012 | + </controller> |
1013 | + <interface type='network'> |
1014 | + <mac address='00:16:3e:3e:a9:1a'/> |
1015 | + <source network='cobbler'/> |
1016 | + <model type='virtio'/> |
1017 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> |
1018 | + </interface> |
1019 | + <serial type='pty'> |
1020 | + <target port='0'/> |
1021 | + </serial> |
1022 | + <console type='pty'> |
1023 | + <target type='serial' port='0'/> |
1024 | + </console> |
1025 | + <input type='mouse' bus='ps2'/> |
1026 | + <graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/> |
1027 | + <video> |
1028 | + <model type='cirrus' vram='9216' heads='1'/> |
1029 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> |
1030 | + </video> |
1031 | + <memballoon model='virtio'> |
1032 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> |
1033 | + </memballoon> |
1034 | + </devices> |
1035 | +</domain> |
1036 | + |
1037 | |
1038 | === added file 'ref/net.xml' |
1039 | --- ref/net.xml 1970-01-01 00:00:00 +0000 |
1040 | +++ ref/net.xml 2012-03-08 06:52:22 +0000 |
1041 | @@ -0,0 +1,12 @@ |
1042 | +<network> |
1043 | + <name>default</name> |
1044 | + <uuid>ab2138ca-73d2-37d8-aeee-d89a557cfccb</uuid> |
1045 | + <forward mode='nat'/> |
1046 | + <bridge name='virbr0' stp='on' delay='0' /> |
1047 | + <ip address='192.168.122.1' netmask='255.255.255.0'> |
1048 | + <dhcp> |
1049 | + <range start='192.168.122.2' end='192.168.122.254' /> |
1050 | + </dhcp> |
1051 | + </ip> |
1052 | +</network> |
1053 | + |
1054 | |
1055 | === added file 'ref/node01.xml' |
1056 | --- ref/node01.xml 1970-01-01 00:00:00 +0000 |
1057 | +++ ref/node01.xml 2012-03-08 06:52:22 +0000 |
1058 | @@ -0,0 +1,54 @@ |
1059 | +<domain type='kvm'> |
1060 | + <name>node01</name> |
1061 | + <uuid>91ac2f39-b6c0-f7fa-1d6f-751c18eab318</uuid> |
1062 | + <memory>524288</memory> |
1063 | + <currentMemory>524288</currentMemory> |
1064 | + <vcpu>1</vcpu> |
1065 | + <os> |
1066 | + <type arch='x86_64' machine='pc-0.12'>hvm</type> |
1067 | + <boot dev='network'/> |
1068 | + </os> |
1069 | + <features> |
1070 | + <acpi/> |
1071 | + <apic/> |
1072 | + <pae/> |
1073 | + </features> |
1074 | + <clock offset='utc'/> |
1075 | + <on_poweroff>destroy</on_poweroff> |
1076 | + <on_reboot>restart</on_reboot> |
1077 | + <on_crash>restart</on_crash> |
1078 | + <devices> |
1079 | + <emulator>/usr/bin/kvm</emulator> |
1080 | + <disk type='file' device='disk'> |
1081 | + <driver name='qemu' type='qcow2'/> |
1082 | + <source file='/home/download/orchestra-demo/node01.img'/> |
1083 | + <target dev='vda' bus='virtio'/> |
1084 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> |
1085 | + </disk> |
1086 | + <controller type='ide' index='0'> |
1087 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> |
1088 | + </controller> |
1089 | + <interface type='network'> |
1090 | + <mac address='52:54:00:ed:6c:d3'/> |
1091 | + <source network='cobbler'/> |
1092 | + <model type='virtio'/> |
1093 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> |
1094 | + </interface> |
1095 | + <serial type='pty'> |
1096 | + <target port='0'/> |
1097 | + </serial> |
1098 | + <console type='pty'> |
1099 | + <target type='serial' port='0'/> |
1100 | + </console> |
1101 | + <input type='mouse' bus='ps2'/> |
1102 | + <graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/> |
1103 | + <video> |
1104 | + <model type='cirrus' vram='9216' heads='1'/> |
1105 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> |
1106 | + </video> |
1107 | + <memballoon model='virtio'> |
1108 | + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> |
1109 | + </memballoon> |
1110 | + </devices> |
1111 | +</domain> |
1112 | + |
1113 | |
1114 | === added file 'settings.cfg' |
1115 | --- settings.cfg 1970-01-01 00:00:00 +0000 |
1116 | +++ settings.cfg 2012-03-08 06:52:22 +0000 |
1117 | @@ -0,0 +1,24 @@ |
1118 | +network: |
1119 | + name: odev-net |
1120 | + bridge: virbr1 |
1121 | + ip_pre: 192.168.123 |
1122 | + ip: 1 |
1123 | + netmask: 255.255.255.0 |
1124 | + dhcp: |
1125 | + range: |
1126 | + start: 2 |
1127 | + end: 254 |
1128 | + template: libvirt-network.tmpl |
1129 | + |
1130 | +systems: |
1131 | + zimmer: |
1132 | + ip: 2 # ip address must be in dhcp range |
1133 | + mac: 00:16:3e:3e:a9:1a |
1134 | + template: libvirt-domain.tmpl |
1135 | + mem: 512 |
1136 | + |
1137 | +nodes: |
1138 | + prefix: odev-node |
1139 | + mac_pre: 00:16:3e:3e:aa |
1140 | + mem: 512 |
1141 | + template: libvirt-domain.tmpl |
1142 | |
1143 | === added file 'setup.py' |
1144 | --- setup.py 1970-01-01 00:00:00 +0000 |
1145 | +++ setup.py 2012-03-08 06:52:22 +0000 |
1146 | @@ -0,0 +1,217 @@ |
1147 | +#!/usr/bin/python |
1148 | + |
1149 | +import yaml |
1150 | +import os |
1151 | +import re |
1152 | +import sys |
1153 | +import libvirt |
1154 | +from Cheetah.Template import Template |
1155 | +import subprocess |
1156 | +import xmlrpclib |
1157 | + |
1158 | +NODES_RANGE = range(1,4) |
1159 | + |
1160 | +def yaml_loadf(fname): |
1161 | + fp = open(fname) |
1162 | + ret = yaml.load(fp) |
1163 | + fp.close() |
1164 | + return(ret) |
1165 | + |
1166 | +class Domain: |
1167 | + def __init__(self, syscfg, ident, basedir=None): |
1168 | + self.ip_pre = syscfg['network']['ip_pre'] |
1169 | + if basedir == None: |
1170 | + basedir = os.path.abspath(os.curdir) |
1171 | + self.basedir = basedir |
1172 | + self._setcfg(syscfg,ident) |
1173 | + self.network = syscfg['network']['name'] |
1174 | + |
1175 | + def __repr__(self): |
1176 | + return("== %s ==\n ip: %s\n mac: %s\n template: %s\n" % |
1177 | + (self.name, self.ipaddr, self.mac, self.template)) |
1178 | + |
1179 | + @property |
1180 | + def ipaddr(self): |
1181 | + return("%s.%s" % (self.ip_pre, self.ipnum)) |
1182 | + |
1183 | + @property |
1184 | + def disk0(self): |
1185 | + return("%s/%s-disk0.img" % (self.basedir, self.name)) |
1186 | + |
1187 | + def dictInfo(self): |
1188 | + ret = vars(self) |
1189 | + # have to add the getters |
1190 | + for prop in ( "ipaddr", "disk0" ): |
1191 | + ret[prop] = getattr(self,prop) |
1192 | + return ret |
1193 | + |
1194 | + def toLibVirtXml(self): |
1195 | + template = Template(file=self.template, searchList=[self.dictInfo()]) |
1196 | + return template.respond() |
1197 | + |
1198 | +class Node(Domain): |
1199 | + def _setcfg(self, cfg, num): |
1200 | + cfg = cfg['nodes'] |
1201 | + self.name = "%s%02i" % (cfg['prefix'],num) |
1202 | + self.mac = "%s:%02x" % (cfg['mac_pre'],num) |
1203 | + self.ipnum = num + 100 |
1204 | + self.template = cfg['template'] |
1205 | + self.mem = cfg['mem'] * 1024 |
1206 | + return |
1207 | + |
1208 | +class System(Domain): |
1209 | + def _setcfg(self, cfg, ident): |
1210 | + cfg = cfg['systems'][ident] |
1211 | + self.name = ident |
1212 | + self.mac = cfg['mac'] |
1213 | + self.ipnum = cfg['ip'] |
1214 | + self.template = cfg['template'] |
1215 | + self.mem = cfg['mem'] * 1024 |
1216 | + |
1217 | +def renderSysDom(config, syscfg, stype="node"): |
1218 | + template = Template(file=syscfg['template'], searchList=[config, syscfg]) |
1219 | + return template.respond() |
1220 | + |
1221 | +# cobbler: |
1222 | +# ip: 2 # ip address must be in dhcp range |
1223 | +# mac: 00:16:3e:3e:a9:1a |
1224 | +# template: libvirt-system.tmpl |
1225 | +# mem: 524288 |
1226 | +# |
1227 | +#nodes: |
1228 | +# prefix: node |
1229 | +# mac_pre: 00:16:3e:3e:aa |
1230 | +# mam: 256 |
1231 | + |
1232 | +def writeDomXmlFile(dom, outpre=""): |
1233 | + fname="%s%s.xml" % (outpre, dom.name) |
1234 | + output = open(fname,"w") |
1235 | + output.write(dom.toLibVirtXml()) |
1236 | + output.close() |
1237 | + return fname |
1238 | + |
1239 | +def libvirt_setup(config): |
1240 | + conn = libvirt.open("qemu:///system") |
1241 | + netname = config['network']['name'] |
1242 | + if netname in conn.listDefinedNetworks() or netname in conn.listNetworks(): |
1243 | + net = conn.networkLookupByName(netname) |
1244 | + if net.isActive(): |
1245 | + net.destroy() |
1246 | + net.undefine() |
1247 | + |
1248 | + allsys = {} |
1249 | + for system in config['systems']: |
1250 | + d = System(config, system) |
1251 | + allsys[d.name]=d.dictInfo() |
1252 | + for num in NODES_RANGE: |
1253 | + d = Node(config, num) |
1254 | + allsys[d.name]=d.dictInfo() |
1255 | + |
1256 | + conn.networkDefineXML(Template(file=config['network']['template'], |
1257 | + searchList=[config['network'], |
1258 | + {'all_systems': allsys }]).respond()) |
1259 | + |
1260 | + print "defined network %s " % netname |
1261 | + |
1262 | + cob = System(config, "zimmer") |
1263 | + systems = [ cob ] |
1264 | + |
1265 | + for node in NODES_RANGE: |
1266 | + systems.append(Node(config, node)) |
1267 | + |
1268 | + qcow_create = "qemu-img create -f qcow2 %s 2G" |
1269 | + defined_systems = conn.listDefinedDomains() |
1270 | + for system in systems: |
1271 | + if system.name in defined_systems: |
1272 | + dom = conn.lookupByName(system.name) |
1273 | + if dom.isActive(): |
1274 | + dom.destroy() |
1275 | + dom.undefine() |
1276 | + conn.defineXML(system.toLibVirtXml()) |
1277 | + if isinstance(system,Node): |
1278 | + subprocess.check_call(qcow_create % system.disk0, shell=True) |
1279 | + print "defined domain %s" % system.name |
1280 | + |
1281 | +def cobbler_addsystem(server, token, system, profile, hostip): |
1282 | + eth0 = { |
1283 | + "macaddress-eth0" : system.mac, |
1284 | + "ipaddress-eth0" : system.ipaddr, |
1285 | + "static-eth0" : False, |
1286 | + } |
1287 | + items = { |
1288 | + 'name': system.name, |
1289 | + 'hostname': system.name, |
1290 | + 'power_address': "qemu+tcp://%s:65001" % hostip, |
1291 | + 'power_id': system.name, |
1292 | + 'power_type': "virsh", |
1293 | + 'profile': profile, |
1294 | + 'netboot_enabled': True, |
1295 | + 'modify_interface': eth0, |
1296 | + 'mgmt_classes': ['orchestra-juju-available'], |
1297 | + } |
1298 | + |
1299 | + if len(server.find_system({"name": system.name})): |
1300 | + server.remove_system(system.name,token) |
1301 | + server.update() |
1302 | + print "removed existing %s" % system.name |
1303 | + |
1304 | + sid = server.new_system(token) |
1305 | + for key, val in items.iteritems(): |
1306 | + ret = server.modify_system(sid, key, val, token) |
1307 | + if not ret: |
1308 | + raise Exception("failed for %s [%s]: %s, %s" % |
1309 | + (system.name, ret, key, val)) |
1310 | + ret = server.save_system(sid,token) |
1311 | + if not ret: |
1312 | + raise Exception("failed to save %s" % system.name) |
1313 | + print "added %s" % system.name |
1314 | + |
1315 | + |
1316 | +def get_profile_arch(): |
1317 | + """Get the system architecture for use in the cobbler setup profile.""" |
1318 | + # This should, for any given system, match what the zimmer-build |
1319 | + # script does to determine the right architecture. |
1320 | + arch_text = subprocess.check_output(['/bin/uname', '-m']).strip() |
1321 | + if re.match('i.86', arch_text): |
1322 | + return 'i386' |
1323 | + else: |
1324 | + return arch_text |
1325 | + |
1326 | + |
1327 | +def cobbler_setup(config): |
1328 | + hostip = "%s.1" % config['network']['ip_pre'] |
1329 | + arch = get_profile_arch() |
1330 | + profile = "precise-%s-juju" % arch |
1331 | + |
1332 | + cob = System(config, "zimmer") |
1333 | + cobbler_url = "http://%s/cobbler_api" % cob.ipaddr |
1334 | + print("Connecting to %s." % cobbler_url) |
1335 | + server = xmlrpclib.Server(cobbler_url) |
1336 | + token = server.login("cobbler","xcobbler") |
1337 | + |
1338 | + systems = [Node(config, node) for node in NODES_RANGE] |
1339 | + |
1340 | + for system in systems: |
1341 | + cobbler_addsystem(server, token, system, profile, hostip) |
1342 | + |
1343 | +def main(): |
1344 | + outpre = "libvirt-cobbler-" |
1345 | + cfg_file = "settings.cfg" |
1346 | + |
1347 | + if len(sys.argv) == 1: |
1348 | + print( |
1349 | + "Usage: setup.py action\n" |
1350 | + "action one of: libvirt-setup, cobbler-setup") |
1351 | + sys.exit(1) |
1352 | + |
1353 | + config = yaml_loadf(cfg_file) |
1354 | + |
1355 | + if sys.argv[1] == "libvirt-setup": |
1356 | + libvirt_setup(config) |
1357 | + elif sys.argv[1] == "cobbler-setup": |
1358 | + cobbler_setup(config) |
1359 | + |
1360 | +if __name__ == '__main__': |
1361 | + main() |
1362 | + |
1363 | +# vi: ts=4 noexpandtab |
1364 | |
1365 | === added directory 'zimmer-build' |
1366 | === added file 'zimmer-build/build' |
1367 | --- zimmer-build/build 1970-01-01 00:00:00 +0000 |
1368 | +++ zimmer-build/build 2012-03-08 06:52:22 +0000 |
1369 | @@ -0,0 +1,271 @@ |
1370 | +#!/bin/bash |
1371 | + |
1372 | +# This should mirror what's in odev's setup.py, except here x86_64 is called |
1373 | +# amd64, not x86_64 because that is Ubuntu's selected name for the arch. |
1374 | +GUEST_ARCHITECTURE=$(uname -m) |
1375 | +case "$GUEST_ARCHITECTURE" in |
1376 | + i?86) GUEST_ARCHITECTURE="i386" ;; |
1377 | + x86_64) GUEST_ARCHITECTURE="amd64" ;; |
1378 | +esac |
1379 | + |
1380 | + |
1381 | +DEF_ZIMG="http://cloud-images.ubuntu.com/server/precise/current/precise-server-cloudimg-${GUEST_ARCHITECTURE}-disk1.img" |
1382 | +DEF_SAVE_D="pristine" |
1383 | +DEF_UD_FILE="ud-build.txt" |
1384 | +ZIMMER_SSH_FORWARD="" |
1385 | +#ZIMMER_SSH_FORWARD=${ZIMMER_SSH_FORWARD:-"hostfwd=tcp::2222-:22"} |
1386 | +ZIMMER_MEM="${ZIMMER_MEM:-1024}" |
1387 | +KVM_PID="" |
1388 | +TAIL_PID="" |
1389 | +LOG="output.log" |
1390 | + |
1391 | +case $(uname -m) in |
1392 | + i?86) DEF_ZIMG=${DEF_ZIMG//amd64/i386};; |
1393 | +esac |
1394 | + |
1395 | +VERBOSITY=0 |
1396 | +TEMP_D="" |
1397 | + |
1398 | +error() { echo "$@" 1>&2; } |
1399 | +errorp() { printf "$@" 1>&2; } |
1400 | +fail() { [ $# -eq 0 ] || error "$@"; exit 1; } |
1401 | +failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; } |
1402 | + |
1403 | +Usage() { |
1404 | + cat <<EOF |
1405 | +Usage: ${0##*/} [ options ] output |
1406 | + |
1407 | + build a zimmer server from a cloud image, and put it in 'output' |
1408 | + |
1409 | + options: |
1410 | + --zimg Z url or path to compressed cloud image |
1411 | + (will be uncompressed) |
1412 | + def: $DEF_ZIMG |
1413 | + --img I url or path to uncompressed cloud image |
1414 | + expected to be uncompressed. |
1415 | + default: create from zimg |
1416 | + --log L log items to LOG |
1417 | + default: $LOG |
1418 | + --save D put pristine copies of things in D |
1419 | + default: $DEF_SAVE_D |
1420 | + --ud-file F use user-data file F |
1421 | + default: $DEF_USER_DATA |
1422 | + --import-keys K import ssh keys |
1423 | + values are 'auto', 'lp:<id>', or path to file |
1424 | +EOF |
1425 | +} |
1426 | + |
1427 | +bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; } |
1428 | +cleanup() { |
1429 | + [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" |
1430 | + [ -z "$KVM_PID" ] || kill "$KVM_PID" |
1431 | + [ -z "$TAIL_PID" ] || kill "$TAIL_PID" |
1432 | +} |
1433 | + |
1434 | +log() { |
1435 | + [ -n "$LOG" ] || return |
1436 | + echo "$(date -R):" "$@" >> "$LOG" |
1437 | +} |
1438 | +debug() { |
1439 | + local level=${1}; shift; |
1440 | + log "$@" |
1441 | + [ "${level}" -gt "${VERBOSITY}" ] && return |
1442 | + error "${@}" |
1443 | +} |
1444 | + |
1445 | +# Download image file. |
1446 | +# Parameters: source URL, filename to save to |
1447 | +download() { |
1448 | + local src="$1" dest="$2" |
1449 | + |
1450 | + debug 0 "downloading $src to $dest" |
1451 | + wget --progress=dot:mega "$src" -O "$dest.partial" && |
1452 | + mv -- "$dest.partial" "$dest" || |
1453 | + fail "failed to get $src" |
1454 | +} |
1455 | + |
1456 | +short_opts="ho:v" |
1457 | +long_opts="help,img:,import-keys:,log:,ud-file:,verbose,zimg:" |
1458 | +getopt_out=$(getopt --name "${0##*/}" \ |
1459 | + --options "${short_opts}" --long "${long_opts}" -- "$@") && |
1460 | + eval set -- "${getopt_out}" || |
1461 | + bad_Usage |
1462 | + |
1463 | +img="" |
1464 | +zimg="" |
1465 | +save_d="$DEF_SAVE_D" |
1466 | +ud_file="$DEF_UD_FILE" |
1467 | +import_keys="" |
1468 | + |
1469 | +while [ $# -ne 0 ]; do |
1470 | + cur=${1}; next=${2}; |
1471 | + case "$cur" in |
1472 | + -h|--help) Usage ; exit 0;; |
1473 | + --img) img=${2}; shift;; |
1474 | + --log) LOG=${2}; shift;; |
1475 | + --save) save_d=${2}; shift;; |
1476 | + --ud-file) ud_file=${2}; shift;; |
1477 | + -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; |
1478 | + --zimg) zimg=${2}; shift;; |
1479 | + --import-keys) import_keys=${2}; shift;; |
1480 | + --) shift; break;; |
1481 | + esac |
1482 | + shift; |
1483 | +done |
1484 | + |
1485 | +## check arguments here |
1486 | +## how many args do you expect? |
1487 | +[ $# -gt 1 ] && bad_Usage "too many arguments" |
1488 | +[ $# -eq 0 ] && bad_Usage "need an output argument" |
1489 | +output="$1" |
1490 | +[ "${output%.zimg}" = "${output}" ] || fail "do not name output with .zimg" |
1491 | + |
1492 | +command -v genisoimage >/dev/null || |
1493 | + fail "you do not have genisoimage installed. install genisoimage package" |
1494 | + |
1495 | + |
1496 | +[ -f "$ud_file" ] || |
1497 | + fail "user data file $ud_file" is not a file |
1498 | + |
1499 | +TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") || |
1500 | + fail "failed to make tempdir" |
1501 | +trap cleanup EXIT |
1502 | + |
1503 | +mkdir -p "$save_d" || fail "failed to mkdir $save_d" |
1504 | + |
1505 | +# if --import-keys was specified, get the keys into a local file |
1506 | +keyf="$TEMP_D/keys" |
1507 | +if [ "$import_keys" = "auto" ]; then |
1508 | + ssh-add -L > "${keyf}" 2>/dev/null || |
1509 | + cat $HOME/.ssh/id*.pub > "$keyf" 2>/dev/null || |
1510 | + error "Warning: unable to find 'auto' keys" |
1511 | +elif [ -f "$import_keys" ]; then |
1512 | + cat "$import_keys" > "$keyf" |
1513 | +elif [ "${import_keys#lp:}" != "${import_keys}" ]; then |
1514 | + ssh-import-id -o - ${import_keys#lp:} > "$keyf" 2>/dev/null || |
1515 | + error "Warning: failed to ssh-import ${import_keys#lp:}" |
1516 | +fi |
1517 | + |
1518 | +if [ -n "$img" ]; then |
1519 | + # if img was given, then we assume good, its the backing image |
1520 | + [ -f "$img" ] || fail "$img (--img) is not a file" |
1521 | + debug 0 "using $img as uncompressed image" |
1522 | +else |
1523 | + if [ -z "$zimg" ]; then |
1524 | + zimg="$DEF_ZIMG" |
1525 | + fi |
1526 | + case "$zimg" in |
1527 | + http://*|https://*) |
1528 | + o_zimg="${zimg}" |
1529 | + zimg=${save_d}/$(basename "$o_zimg" ".img").zimg |
1530 | + [ -f "$zimg" ] && |
1531 | + fail "please delete $destfirst or use --zimg|--img" |
1532 | + download "$o_zimg" "$zimg" |
1533 | + ;; |
1534 | + file://*) |
1535 | + o_zimg=${zimg} |
1536 | + zimg=${zimg#file://} |
1537 | + debug 0 "using file $o_zimg as zimg" |
1538 | + [ -f "$zimg" ] || fail "$zimg is not a file" |
1539 | + ;; |
1540 | + *) [ -f "$zimg" ] || fail "$zimg is not a file" |
1541 | + debug 0 "using file $zimg as zimg" |
1542 | + ;; |
1543 | + esac |
1544 | + img=${zimg%.zimg}.img |
1545 | + debug 0 "creating uncompressed img $img from $zimg" |
1546 | + qemu-img convert -O qcow2 "$zimg" "$img" |
1547 | +fi |
1548 | + |
1549 | +debug 0 "making nocloud data source in iso" |
1550 | +seed_d="$TEMP_D/seed" |
1551 | +mkdir "$seed_d" || fail "failed to make 'seed' in tempdir" |
1552 | + |
1553 | +cp "$ud_file" "$seed_d/user-data" || fail "failed to copy $ud_file to $seed_d" |
1554 | +cat > "$seed_d/meta-data" <<EOF |
1555 | +instance-id: i-zimmer-build |
1556 | +local-hostname: zimmer-build |
1557 | +EOF |
1558 | + |
1559 | +# if keys were specified, dump them into meta-data |
1560 | +if [ -s "$keyf" ]; then |
1561 | + { |
1562 | + echo "public-keys:" |
1563 | + echo " zimmer-build:" |
1564 | + while read line; do |
1565 | + echo " - \"$line\"" |
1566 | + done < "$keyf" |
1567 | + } >> "$seed_d/meta-data" |
1568 | +fi |
1569 | + |
1570 | +( cd "$seed_d" && |
1571 | + genisoimage -output "$TEMP_D/build.iso" \ |
1572 | + -volid cidata -joliet -rock user-data meta-data 2>/dev/null ) || |
1573 | + fail "failed to create iso for user-data from $ud_file" |
1574 | + |
1575 | +build0="$TEMP_D/build0.img" |
1576 | +img_fp=$(readlink -f "$img") || fail "failed to get fullpath for $img" |
1577 | +qemu-img create -f qcow2 -b "$img_fp" "${build0}" || |
1578 | + fail "failed to create qcow image backed by $img" |
1579 | + |
1580 | +## on precise, you do do not need 'boot=on' in kvm commanad line |
1581 | +[ "$(lsb_release -sc)" = "precise" ] && bton="" || bton="boot=on" |
1582 | + |
1583 | +serial_out="$TEMP_D/serial.output" |
1584 | +monitor="${TEMP_D}/monitor.fifo" && mkfifo "$monitor" || |
1585 | + fail "failed to mkfifo for monitor" |
1586 | + |
1587 | +debug 0 "booting kvm guest to turn cloud-image into zimmer" |
1588 | +kvm_start=$SECONDS |
1589 | +MONITOR="-monitor null" |
1590 | +NOGRAPHIC="-nographic" |
1591 | +kvm \ |
1592 | + -drive file=${build0},if=virtio,cache=unsafe${bton:+,${bton}} \ |
1593 | + -boot c -cdrom "$TEMP_D/build.iso" \ |
1594 | + -net nic,model=virtio \ |
1595 | + -net user${ZIMMER_SSH_FORWARD:+,${ZIMMER_SSH_FORWARD}} \ |
1596 | + -m "${ZIMMER_MEM}" \ |
1597 | + $NOGRAPHIC \ |
1598 | + $MONITOR \ |
1599 | + -serial "file:$serial_out" \ |
1600 | + 2>&1 & |
1601 | + |
1602 | +KVM_PID=$! |
1603 | +tail -F "$serial_out" 2>/dev/null & |
1604 | +TAIL_PID=$! |
1605 | + |
1606 | +sleep 20 |
1607 | +[ -s "$serial_out" ] || |
1608 | + fail "no output in serial console output after 20 seconds" |
1609 | + |
1610 | +wait $KVM_PID |
1611 | +ret=$? |
1612 | +KVM_PID="" |
1613 | + |
1614 | +{ kill $TAIL_PID ; } >/dev/null 2>&1 |
1615 | +TAIL_PID="" |
1616 | + |
1617 | +{ |
1618 | + echo ===== begin serial console ==== |
1619 | + cat "$serial_out" |
1620 | + echo ===== end serial console ==== |
1621 | +} >> "$LOG" |
1622 | +[ $ret -eq 0 ] || fail "failed to build via kvm guest" |
1623 | +grep -q "ZIMMER BUILD FINISHED" "$serial_out" || |
1624 | + fail "did not find finished message in $serial_out" |
1625 | + |
1626 | +debug 0 "kvm image built in $(($SECONDS-$kvm_start))s" |
1627 | +debug 0 "creating dist image in $output" |
1628 | +## create a re-shrunk image of build0.img into 'zimmer-disk0.img.dist' |
1629 | +[ ! -f "$output" ] || rm -f "$output" || |
1630 | + fail "failed to remove existing $output" |
1631 | +qemu-img convert -O qcow2 "$TEMP_D/build0.img" "$output" && |
1632 | + chmod 444 "$output" || |
1633 | + fail "failed to create $output from build0.img" |
1634 | + |
1635 | +debug 0 "creating pristine compressed zimmer-disk0.zimg" |
1636 | +## optionally create a zip'd image for transmission |
1637 | +qemu-img convert -f qcow2 -O qcow2 -c "$output" "${output%.img}.zimg" |
1638 | + |
1639 | +debug 0 "done. took $SECONDS seconds" |
1640 | +# vi: ts=4 noexpandtab |
1641 | |
1642 | === added file 'zimmer-build/ud-build.txt' |
1643 | --- zimmer-build/ud-build.txt 1970-01-01 00:00:00 +0000 |
1644 | +++ zimmer-build/ud-build.txt 2012-03-08 06:52:22 +0000 |
1645 | @@ -0,0 +1,70 @@ |
1646 | +#cloud-config |
1647 | +password: passw0rd |
1648 | +chpasswd: { expire: False } |
1649 | +ssh_pwauth: True |
1650 | + |
1651 | +#apt_proxy: "http://local-proxy:3128/" |
1652 | +#apt_mirror: "http://us.archive.ubuntu.com/ubuntu" |
1653 | +#ssh_import_id: smoser |
1654 | + |
1655 | +bucket: |
1656 | + - &setup | |
1657 | + cd /root |
1658 | + ( |
1659 | + #ONE_TIME_PROXY=http://local-proxy:3128/ |
1660 | + |
1661 | + echo === $(date) ==== |
1662 | + debconf-set-selections <<EOF |
1663 | + ubuntu-orchestra-provisioning-server ubuntu-orchestra-provisioning-server/import-isos boolean false |
1664 | + ubuntu-orchestra-provisioning-server ubuntu-orchestra-provisioning-server/dnsmasq-dhcp-range string 10.10.10.2,10.10.10.254 |
1665 | + ubuntu-orchestra-provisioning-server ubuntu-orchestra-provisioning-server/dnsmasq-enabled boolean false |
1666 | + cobbler cobbler/server_and_next_server string zimmer-server |
1667 | + cobbler cobbler/password password xcobbler |
1668 | + cloud-init cloud-init/datasources multiselect NoCloud, OVF |
1669 | + |
1670 | + EOF |
1671 | + |
1672 | + [ -n "$ONE_TIME_PROXY" ] && export http_proxy="$ONE_TIME_PROXY" |
1673 | + export DEBIAN_FRONTEND=noninteractive; |
1674 | + dpkg-reconfigure cloud-init |
1675 | + |
1676 | + read oldhost < /etc/hostname |
1677 | + sed -i "/$oldhost/d;/zimmer/d" /etc/hosts |
1678 | + echo zimmer > /etc/hostname |
1679 | + hostname zimmer |
1680 | + |
1681 | + echo "127.0.1.2 zimmer-server" >> /etc/hosts |
1682 | + |
1683 | + echo === $(date): starting apt ==== |
1684 | + apt_get() { |
1685 | + DEBIAN_FRONTEND=noninteractive apt-get \ |
1686 | + --option "Dpkg::Options::=--force-confold" --assume-yes "$@" |
1687 | + } |
1688 | + apt_get update |
1689 | + apt_get install ubuntu-orchestra-provisioning-server libvirt-bin cobbler-web |
1690 | + |
1691 | + case $(uname -m) in |
1692 | + i?86) arches="i386";; |
1693 | + *) arches="amd64";; |
1694 | + esac |
1695 | + cat >> /etc/orchestra/import_isos <<END |
1696 | + RELEASES="oneiric precise" |
1697 | + ARCHES="${arches}" |
1698 | + END |
1699 | + |
1700 | + echo === $(date): starting import ==== |
1701 | + orchestra-import-isos |
1702 | + |
1703 | + sed -i '/zimmer-server/d' /etc/hosts |
1704 | + |
1705 | + echo === $(date): starting cleanup ==== |
1706 | + apt_get clean |
1707 | + time sh -c 'dd if=/dev/zero of=/out.img; rm /out.img' |
1708 | + |
1709 | + echo === $(date): poweroff === |
1710 | + echo === ZIMMER BUILD FINISHED === |
1711 | + ) 2>&1 | tee out.log |
1712 | + |
1713 | +runcmd: |
1714 | + - [ sh, -c, *setup ] |
1715 | + - [ /sbin/poweroff ] |