really fix domain
[tridge/autocluster.git] / autocluster
1 #!/bin/bash
2 # main autocluster script
3 #
4 # Copyright (C) Andrew Tridgell  2008
5 # Copyright (C) Martin Schwenke  2008
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #   
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #   
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20 if [ -f "$0" ]; then
21     installdir="`dirname \"$0\"`"
22 else
23     autocluster=`which $0`
24     installdir="`dirname \"$autocluster\"`"
25 fi
26
27 config="config"
28 set -e
29
30 ####################
31 # show program usage
32 usage ()
33 {
34     cat >&2 <<EOF
35 Usage: autocluster [OPTION] ... <COMMAND>
36   options:
37     -c <file>  specify config file (default is "config")
38     -x         enable script debugging
39
40   commands:
41      create base
42            create a base image
43
44      create cluster CLUSTERNAME
45            create a full cluster
46
47      create node CLUSTERNAME NODENUMBER
48            create one cluster node
49
50      create tsm CLUSTERNAME
51            create a TSM server node
52
53      mount DISK
54            mount a qemu disk on mnt/
55
56      unmount
57            unmount a qemu disk from mnt/
58
59      bootbase
60            boot the base image
61
62      testproxy
63            test your proxy setup
64 EOF
65     exit 1
66 }
67
68
69 ###############################
70 # create a single node
71 create_node() {
72     CLUSTER="$1"
73     NODENUMBER="$2"
74     NAME="$CLUSTER""n$NODENUMBER"
75     BASE="$VIRTBASE/$BASENAME.img"
76     DISK="$VIRTBASE/$CLUSTER/$NAME.qcow2"
77     NUMSHARED=3
78
79     # first node might need more memory for SoFS GUI
80     if [ $NODENUMBER = 1 -a $GUIMEM -gt $MEM ]; then
81         NODEMEM=$GUIMEM
82     else
83         NODEMEM=$MEM
84     fi
85     echo "Creating cluster node $NAME"
86
87     mkdir -p $VIRTBASE/$CLUSTER
88
89     echo "Creating the disk"
90     rm -f "$DISK"
91     qemu-img create -b "$BASE" -f qcow2 "$DISK"
92
93     IPNUM=`expr $FIRSTIP + $NODENUMBER`
94
95     mount_disk $DISK
96     setup_base
97     setup_network
98     unmount_disk
99
100     mkdir -p tmp
101
102     MAC1=`get_macaddr $CLUSTER $NODENUMBER 1`
103     MAC2=`get_macaddr $CLUSTER $NODENUMBER 2`
104     MAC3=`get_macaddr $CLUSTER $NODENUMBER 3`
105     UUID=`uuidgen`
106     
107     echo "Creating $NAME.xml"
108     substitute_vars $NODE_TEMPLATE tmp/$NAME.xml
109     
110     # install the XML file
111     $VIRSH undefine $NAME > /dev/null 2>&1 || true
112     $VIRSH define tmp/$NAME.xml
113 }
114
115
116 ###############################
117 # create a TSM node
118 create_tsm() {
119     CLUSTER="$1"
120     NAME="$CLUSTER""tsm"
121     BASE="$VIRTBASE/$BASENAME.img"
122     DISK="$VIRTBASE/$CLUSTER/$NAME.qcow2"
123     TSMDISK="$VIRTBASE/$CLUSTER/tsmstorage.qcow2"
124     
125     echo "Creating TSM cluster node $NAME"
126     
127     mkdir -p $VIRTBASE/$CLUSTER tmp
128     
129     echo "Creating the disk"
130     rm -f "$DISK"
131     qemu-img create -b "$BASE" -f qcow2 "$DISK"
132     
133     echo "Creating tsm disk"
134     qemu-img create -f qcow2 "$TSMDISK" $TSMDISKSIZE
135     
136     # TSM server is first IP in the cluster
137     IPNUM=$FIRSTIP
138
139     mount_disk $DISK
140     setup_base
141     setup_network
142     unmount_disk
143     
144     UUID=`uuidgen`
145     MAC1=`get_macaddr $CLUSTER 0 0`
146     
147     echo "Creating $NAME.xml"
148     substitute_vars $TSM_TEMPLATE tmp/$NAME.xml
149     
150     # install the XML file
151     $VIRSH undefine $NAME > /dev/null 2>&1 || true
152     $VIRSH define tmp/$NAME.xml
153 }
154
155
156 ###############################
157 # create a whole cluster
158 create_cluster() {
159     CLUSTER="$1"
160
161     mkdir -p $VIRTBASE/$CLUSTER tmp
162     mkdir -p $KVMLOG
163
164     echo "Creating 3 shared disks"
165     for i in `seq 1 3`; do
166         qemu-img create -f raw $VIRTBASE/$CLUSTER/shared$i $SHAREDDISKSIZE
167         # setup a nice ID at the start of the disk
168         echo "SOFS-`uuidgen`" > tmp/diskid
169         dd if=tmp/diskid of=$VIRTBASE/$CLUSTER/shared$i conv=notrunc bs=1 > /dev/null 2>&1
170     done
171
172     echo "Creating $NUMNODES base nodes"
173     for i in `seq 1 $NUMNODES`; do
174         create_node "$CLUSTER" $i
175     done
176
177     echo "Creating TSM server node"
178     create_tsm "$CLUSTER"
179
180     echo "# autocluster $CLUSTER" > hosts.$CLUSTER
181     echo "$IPBASE.0.$FIRSTIP ${CLUSTER}tsm.$LOWDOMAIN ${CLUSTER}tsm" >> hosts.$CLUSTER
182     for i in `seq 1 $NUMNODES`; do
183         echo "$IPBASE.0.`expr $FIRSTIP + $i` ${CLUSTER}n$i.$LOWDOMAIN ${CLUSTER}n$i" >> hosts.$CLUSTER
184     done
185     echo >> hosts.$CLUSTER
186
187     echo "Cluster $CLUSTER created"
188     echo "You may want to add this to your /etc/hosts file:"
189     cat hosts.$CLUSTER
190
191     echo
192 }
193
194 ###################
195 # create base image
196 create_base() {
197
198     NAME="$BASENAME"
199     DISK="$VIRTBASE/$NAME.img"
200
201     mkdir -p $KVMLOG
202
203     echo "Creating the disk"
204     qemu-img create -f raw "$DISK" $DISKSIZE
205
206     rm -rf tmp
207     mkdir -p mnt tmp tmp/ISO
208
209     setup_timezone
210     setup_repos
211
212
213     echo "Creating kickstart file from template"
214     substitute_vars "$KICKSTART" "tmp/ks.cfg"
215
216     echo "Creating kickstart floppy"
217     dd if=/dev/zero of=tmp/floppy.img bs=1024 count=1440
218     mkdosfs tmp/floppy.img
219     mount -o loop -t msdos tmp/floppy.img mnt
220     cp tmp/ks.cfg mnt
221     mount -o loop,ro $ISO tmp/ISO
222     
223     echo "Setting up bootloader"
224     cp tmp/ISO/isolinux/isolinux.bin tmp
225     cp tmp/ISO/isolinux/vmlinuz tmp
226     cp tmp/ISO/isolinux/initrd.img tmp
227     umount tmp/ISO
228     umount mnt
229
230     UUID=`uuidgen`
231
232     substitute_vars $INSTALL_TEMPLATE tmp/$NAME.xml
233
234     rm -f $KVMLOG/serial.$NAME
235
236     # boot the install CD
237     $VIRSH create tmp/$NAME.xml
238
239     echo "Waiting for install to start"
240     sleep 2
241     
242     # wait for the install to finish
243     cat <<EOF > tmp/wait.exp
244 spawn tail -f $KVMLOG/serial.$NAME
245 expect -timeout 3600 "you may safely reboot your system"
246 EOF
247
248     expect tmp/wait.exp
249     $VIRSH destroy $NAME
250     
251     if ! grep "you may safely reboot your system" $KVMLOG/serial.$NAME > /dev/null; then
252         echo "Failed to create base image $DISK"
253         exit 1
254     fi
255
256     ls -l $DISK
257     cat <<EOF
258
259 Install finished, base image $DISK created
260
261 You may wish to run
262    chattr +i $DISK
263 To ensure that this image does not change
264
265 EOF
266 }
267
268
269
270 ###############################
271 # boot the base disk
272 boot_base() {
273     CLUSTER="$1"
274
275     NAME="$BASENAME"
276     DISK="$VIRTBASE/$NAME.img"
277
278     rm -rf tmp
279     mkdir -p tmp
280
281     IPNUM=$FIRSTIP
282     CLUSTER="base"
283
284     mount_disk $DISK
285     setup_base
286     unmount_disk
287
288     UUID=`uuidgen`
289     
290     echo "Creating $NAME.xml"
291     substitute_vars $BOOT_TEMPLATE tmp/$NAME.xml
292     
293     # boot the base system
294     $VIRSH create tmp/$NAME.xml
295 }
296
297 ###############################
298 # test the proxy setup
299 test_proxy() {
300     export http_proxy=$WEBPROXY
301     wget -O /dev/null $INSTALL_SERVER
302     echo "Proxy OK"
303 }
304
305 ######################################################################
306
307
308 ############################
309 # parse command line options
310 temp=$(getopt -n "$prog" -o "c:xh" -l help -- "$@")
311
312 [ $? != 0 ] && usage
313
314 eval set -- "$temp"
315
316 while true ; do
317     case "$1" in
318         -c) config="$2" ; shift; shift ;;
319         -x) set -x; shift ;;
320         --) shift ; break ;;
321         -h|--help|*) usage ;; # Shouldn't happen, so this is reasonable.
322     esac
323 done
324
325 . "`dirname $config`/$config"
326 . "$installdir/functions"
327
328 LOWDOMAIN=`echo $DOMAIN | tr A-Z a-z`
329
330 # check for needed programs 
331 check_command nbd-client
332 check_command expect
333 check_command qemu-nbd
334
335 [ $# -lt 1 ] && usage
336
337 command="$1"
338 shift
339
340 case $command in
341     create)
342         type=$1
343         shift
344         case $type in
345             base)
346                 [ $# != 0 ] && usage
347                 create_base;
348                 ;;
349             cluster)
350                 [ $# != 1 ] && usage
351                 create_cluster "$1";
352                 ;;
353             node)
354                 [ $# != 2 ] && usage
355                 create_node "$1" "$2";
356                 ;;
357             tsm)
358                 [ $# != 1 ] && usage
359                 create_tsm "$1";
360                 ;;
361             *)
362                 usage;
363                 ;;
364         esac
365         ;;
366     mount)
367         [ $# != 1 ] && usage
368         mount_disk "$1"
369         ;;
370     unmount)
371         [ $# != 0 ] && usage
372         unmount_disk
373         ;;
374     bootbase)
375         boot_base;
376         ;;
377     testproxy)
378         test_proxy;
379         ;;
380     *)
381         usage;
382         ;;
383 esac
384
385