MyPLC: portable self-contained PLC installation
[myplc.git] / build.sh
1 #!/bin/bash
2 #
3 # Builds a Fedora based PLC image. You should be able to run this
4 # script multiple times without a problem.
5 #
6 # Mark Huang <mlhuang@cs.princeton.edu>
7 # Copyright (C) 2006 The Trustees of Princeton University
8 #
9 # $Id$
10 #
11
12 PATH=/sbin:/bin:/usr/sbin:/usr/bin
13
14 # In a normal CVS environment, the requisite CVS modules (including
15 # build/) are located at the same level we are. In a PlanetLab RPM
16 # build environment (see the RPM spec file), they are checked out into
17 # a subdirectory.
18 if [ -d ./build ] ; then
19     PATH=$PATH:./build
20     srcdir=.
21 elif [ -d ../build ] ; then
22     PATH=$PATH:../build
23     srcdir=..
24 else
25     echo "Error: Could not find sources in either . or .."
26     exit 1
27 fi
28
29 export PATH
30
31 # PLC configuration file
32 config=plc_config.xml
33
34 # Release and architecture to install
35 releasever=2
36 basearch=i386
37
38 # Data directory base
39 usr_share=/usr/share
40
41 # Initial size of the image
42 size=1000000000
43
44 usage()
45 {
46     echo "Usage: build.sh [OPTION]..."
47     echo "      -c file         PLC configuration file (default: $config)"
48     echo "      -r release      Fedora release number (default: $releasever)"
49     echo "      -a arch         Fedora architecture (default: $basearch)"
50     echo "      -d datadir      Data directory base (default: $usr_share)"
51     echo "      -s size         Approximate size of the installation (default: $size)"
52     echo "      -h              This message"
53     exit 1
54 }
55
56 # Get options
57 while getopts "c:r:a:d:s:h" opt ; do
58     case $opt in
59         c)
60             config=$OPTARG
61             ;;
62         r)
63             releasever=$OPTARG
64             ;;
65         a)
66             basearch=$OPTARG
67             ;;
68         d)
69             usr_share=$OPTARG
70             ;;
71         s)
72             size=$OPTARG
73             ;;
74         h|*)
75             usage
76             ;;
77     esac
78 done
79
80 root=fc$releasever
81 data=data$releasever
82
83 if [ ! -f $root.img ] ; then
84     bs=4096
85     count=$(($size / 4096))
86     dd bs=$bs count=$count if=/dev/zero of=$root.img
87     mkfs.ext3 -j -F $root.img
88 fi
89
90 mkdir -p $root $data
91 mount -o loop $root.img $root
92 trap "umount $root; exit 1" ERR
93
94 #
95 # Build
96 #
97
98 # Get package list
99 while read package ; do
100     packages="$packages -p $package"
101 done < <(./plc-config --packages $config)
102
103 # Install base system
104 mkfedora -v -r $releasever -a $basearch $packages $root
105
106 # FC2 minilogd starts up during shutdown and makes unmounting
107 # impossible. Just get rid of it.
108 rm -f $root/sbin/minilogd
109 ln -nsf /bin/true $root/sbin/minilogd
110
111 # Build schema
112 make -C $srcdir/pl_db
113
114 #
115 # Install
116 #
117
118 # Install configuration scripts
119 install -D -m 755 plc_config.py $root/tmp/plc_config.py
120 chroot $root sh -c 'cd /tmp; python plc_config.py build; python plc_config.py install'
121 install -D -m 755 plc-config $root/usr/bin/plc-config
122 install -D -m 755 api-config $root/usr/bin/api-config
123
124 # Install init script
125 install -D -m 755 guest.init $root/etc/init.d/plc
126 chroot $root sh -c 'chkconfig --add plc; chkconfig plc on'
127
128 # Install DB schema and API code
129 mkdir -p $root/usr/share
130 rsync -a $srcdir/pl_db $srcdir/plc_api $root/usr/share/
131
132 # Install web scripts
133 mkdir -p $root/usr/bin
134 install -m 755 \
135     plc/scripts/gen-sites-xml.py \
136     plc/scripts/gen-slices-xml-05.py \
137     plc/scripts/gen-static-content.py \
138     $root/usr/bin/
139
140 # Install web pages
141 mkdir -p $root/var/www/html
142 rsync -a $srcdir/plc_www/ $root/var/www/html/
143
144 # Install configuration file
145 install -D -m 644 $config $data/etc/planetlab/plc_config.xml
146
147 # Move "data" directories out of the installation
148 datadirs=(
149 /etc/planetlab
150 /var/lib/pgsql
151 /var/www/html/alpina-logs
152 /var/www/html/boot
153 /var/www/html/download
154 /var/www/html/generated
155 /var/www/html/install-rpms
156 /var/www/html/xml
157 )
158
159 mkdir -p $root/data
160 for datadir in "${datadirs[@]}" ; do
161     mkdir -p ${data}$datadir
162     if [ -d $root/$datadir -a ! -h $root/$datadir ] ; then
163         (cd $root && find ./$datadir | cpio -p -d -u ../$data/)
164     fi
165     rm -rf $root/$datadir
166     mkdir -p $(dirname $root/$datadir)
167     ln -nsf /data$datadir $root/$datadir
168 done
169
170 # Shrink to 100 MB free space
171 kb=$(python <<EOF
172 import os
173 df = os.statvfs('$root')
174 target = 100 * 1024 * 1024 / df.f_bsize
175 if df.f_bavail > target:
176     print (df.f_blocks - (df.f_bavail - target)) * df.f_bsize / 1024
177 EOF
178 )
179
180 umount $root
181 trap - ERR
182
183 if [ -n "$kb" ] ; then
184     # Setup loopback association. Newer versions of losetup have a -f
185     # option which finds an unused loopback device, but we must
186     # support FC2 for now.
187     # dev_loop=$(losetup -f)
188     for i in `seq 1 7` ; do
189         if ! grep -q "^/dev/loop$i" /proc/mounts ; then
190             dev_loop="/dev/loop$i"
191             break
192         fi
193     done
194     losetup $dev_loop $root.img
195     trap "losetup -d $dev_loop" ERR
196
197     # Resize the filesystem
198     e2fsck -f $dev_loop
199     resize2fs $dev_loop ${kb}K
200
201     # Tear down loopback association
202     losetup -d $dev_loop
203     trap - ERR
204
205     # Truncate the image file
206     perl -e "truncate '$root.img', $kb*1024"
207 fi
208
209 # Write sysconfig
210 cat >plc.sysconfig <<EOF
211 PLC_ROOT=$usr_share/plc/$root
212 PLC_DATA=$usr_share/plc/$data
213 #PLC_OPTIONS="-v"
214 EOF
215
216 exit $RETVAL