oops
[build.git] / build.common
1 # -*-Shell-script-*-
2 #
3 # Common functions for build scripts used by various packages
4 # incorporated (e.g., build, myplc, myplc-devel, vserver-reference)
5 #
6 # Marc E. Fiuczynski <mef@cs.princeton.edu>
7 # Copyright (C) 2007 The Trustees of Princeton University
8 #
9 # $Id$
10 #
11
12 function pl_getDefaultDistro() {
13     # FC4 is currently the default release
14     echo "Fedora"
15     return 0
16 }
17
18 function pl_getDefaultRelease() {
19     # FC4 is currently the default release
20     echo "4"
21     return 0
22 }
23
24 function pl_getDistro() {
25     defaultDistro=$(pl_getDefaultDistro)
26     if [ -f "/etc/redhat-release" ] ; then
27         distro=$(awk ' { print $1 } ' /etc/redhat-release)
28     else
29         distro=$defaultDistro
30     fi
31     echo "$distro"
32     return 0
33 }
34
35 function pl_getRelease() {
36     defaultRelease=$(pl_getDefaultRelease)
37     if [ -f "/etc/redhat-release" ] ; then
38         release=$(awk ' { if ($1=="Fedora" && $2=="Core") print $4 ; if (($1=="Fedora" && $2!="Core")||$1=="CentOS") print $3 } ' /etc/redhat-release)
39         [ $release -lt $defaultRelease ] && release=$defaultRelease
40     else
41         release=$defaultRelease
42     fi
43     echo "$release"
44     return 0
45 }
46
47 # vserver expects something like fc4 or f7
48 # for fedora and centos only for now
49 function pl_getReleaseName () {
50     distro=$1; shift
51     release=$1; shift
52     case $distro in
53         [Ff]edora*)
54             if [ "$release" -le 6 ] ; then
55                 releasename=fc$release
56             else
57                 releasename=f$release
58             fi ;;
59         [Cc]entOS*)
60             if [ "$release" = "4.5" ] ; then
61             # centos 4.5 is just centos4 + enhancements
62                 releasename=centos4
63             else
64                 releasename=centos$release
65             fi ;;
66         *)
67             releasename="unknown-name-for-${pl_DISTRO}-please-edit-build.common"
68             echo 1>&2 "build.common: WARNING - releasename not set for distro=$distro" 
69             return 1
70             ;;
71     esac
72     echo "$releasename"
73     return 0
74 }
75
76 # figure out which redhat distro we are using (fedora, centos, redhat)
77 pl_DISTRO=$(pl_getDistro)
78
79 # select basearch of the host devel environment - protected for macos for local tests
80 pl_DISTRO_ARCH=$(uname -i 2>/dev/null|| echo unknownarch)
81
82 # let mkfedora select one of its mirrors
83 pl_DISTRO_URL=""
84
85 # the release number (plain number)
86 pl_DISTRO_RELEASE=$(pl_getRelease)
87
88 # the release name - for vserver build - like fc4, f8 or centos4
89 pl_DISTRO_NAME=$(pl_getReleaseName $pl_DISTRO $pl_DISTRO_RELEASE)
90
91 # get path to appropriate yumgroups.xml file
92 # Thierry: quick & dirty improvement 
93 # this file is updated by the toplevel build, from groups/<pldistro>.xml
94 pl_DISTRO_YUMGROUPS="../../../RPMS/yumgroups.xml"
95
96 function pl_process_fedora_options () {
97     # Get options
98     shiftcount=0
99     while getopts "l:r:a:h" opt ; do
100         case $opt in
101             l)
102                 pl_DISTRO_URL=$OPTARG
103                 let shiftcount=$shiftcount+2
104                 ;;
105             r)
106                 pl_DISTRO_RELEASE=$OPTARG
107                 let shiftcount=$shiftcount+2
108                 ;;
109             a)
110                 pl_DISTRO_ARCH=$OPTARG
111                 let shiftcount=$shiftcount+2
112                 ;;
113             h|*)
114                 echo "Usage: $0 [OPTION]..."
115                 echo "  -l url          distro mirror location (default: $pl_DISTRO_URL)"
116                 echo "  -r release      distro release number (default: $pl_DISTRO_RELEASE)"
117                 echo "  -a arch         distro architecture (default: $pl_DISTRO_ARCH)"
118                 echo "where distro can be either fedora, centos, or redhat"
119                 echo "  -h              This message"
120                 exit 1
121                 ;;
122         esac
123     done
124     return $shiftcount
125 }
126
127 ######################################## handling a root image
128 function pl_makedevs() {
129     vroot=$1
130     # Clean ${vroot}/dev, but only when ${vroot}!=""
131     [ -n $vroot ] && rm -rf $vroot/dev
132     
133     mkdir -p $vroot/dev
134     mknod -m 666 $vroot/dev/null c 1 3
135     mknod -m 666 $vroot/dev/zero c 1 5
136     mknod -m 666 $vroot/dev/full c 1 7
137     mknod -m 644 $vroot/dev/random c 1 8
138     mknod -m 644 $vroot/dev/urandom c 1 9
139     mknod -m 666 $vroot/dev/tty c 5 0
140     mknod -m 666 $vroot/dev/ptmx c 5 2
141     # For bash command substitution
142     ln -nsf ../proc/self/fd $vroot/dev/fd
143
144     # For df and linuxconf
145     touch $vroot/dev/hdv1
146
147     # For pseudo ttys
148     mkdir -p $vroot/dev/pts
149
150     # (Might have to remove the following for vserver-reference.)
151
152     # for tmpfs mount
153     mkdir -p $vroot/dev/shm
154
155     # For TUN/TAP
156     mkdir -p $vroot/dev/net
157     mknod -m 600 $vroot/dev/net/tun c 10 200
158
159     # For mkinitrd (in case a kernel is being installed)
160     # As well for loop back mounting within a vserver. 
161     for i in $(seq 0 255) ; do
162         mknod -m 640 $vroot/dev/loop$i b 7 $i
163     done
164 }
165
166 function pl_mkfedora() {
167     root=$1
168     shift
169     options=$@
170
171     pl_makedevs $root
172
173     [ -n "$pl_DISTRO_URL" ] && options="$options -l $pl_DISTRO_URL"
174     [ -n "$pl_DISTRO_ARCH" ] && options="$options -a $pl_DISTRO_ARCH"
175     [ -n "$pl_DISTRO_RELEASE" ] && options="$options -r $pl_DISTRO_RELEASE"
176     # echo "mkfedora -v $options $root"
177     eval mkfedora -v $options $root
178 }
179
180 function pl_setup_chroot() {
181     root=$1; shift
182     options="$@"
183
184     pl_mkfedora $root $options
185
186     # Disable all services in reference image
187     chroot $root sh -c "/sbin/chkconfig --list | awk '{ print \$1 }' | xargs -i /sbin/chkconfig {} off"
188
189     # FC2 minilogd starts up during shutdown and makes unmounting
190     # impossible. Just get rid of it.
191     rm -f $root/sbin/minilogd
192     ln -nsf /bin/true $root/sbin/minilogd
193
194     # This tells the Boot Manager that it is okay to update
195     # /etc/resolv.conf and /etc/hosts whenever the network configuration
196     # changes. Users are free to delete this file.
197     touch $vroot/etc/AUTO_UPDATE_NET_FILES
198 }
199
200 # Move specified directories out of a src tree into a dst tree, and
201 # then for each moved directory create a symlink in src to dst.
202 function pl_move_dirs() {
203     root=$1
204     data=$2
205     store=$3
206     shift 3
207
208     mkdir -p $root/data
209     for datadir in "$@" ; do
210         mkdir -p ${data}${datadir}
211         if [ -d ${root}/${datadir} -a ! -h ${root}/${datadir} ] ; then
212             (cd ${root} && find ./${datadir} | cpio -p -d -u ../${data}/)
213         fi
214         rm -rf ${root}/${datadir}
215         mkdir -p $(dirname ${root}/${datadir})
216         ln -nsf /${store}/${datadir} ${root}/${datadir}
217     done
218 }
219
220 # Construct an image file from given some directory
221 # XXX in the future maybe use livecdtools?
222 function pl_make_image() {
223     root=$1
224     image=$2
225     extraspace=$3
226
227     # Leave about 100 MB free space and allow for about 20% inode overhead
228     bytes=$((($(du -sb $root | cut -f1) + $extraspace) * 120 / 100))
229     bs=4096
230     blocks=$(($bytes / $bs))
231     dd bs=$bs count=$blocks if=/dev/zero of=$image
232     mkfs.ext3 -b $bs -j -F $image
233
234     # Temporarily mount it
235     tmp=$(mktemp -d tmp.XXXXXX)
236     mount -o loop $image $tmp
237     trap "umount $tmp; rmdir $tmp" ERR INT
238
239     # Move files to it
240     (cd $root && tar cpf - .) | (cd $tmp && tar xpf -)
241
242     # Unmount it
243     umount -l $tmp
244     rmdir $tmp
245     trap - ERR INT
246 }
247
248 # Fix permissions on tmp directories
249 function pl_fixtmp_permissions() {
250     root=$1
251     chmod 1777 $root/tmp $root/usr/tmp $root/var/tmp
252 }
253
254 function pl_fixdirs() {
255     root=$1
256     datadirs=$2
257     for datadir in datadirs ; do
258         if [ -h ${root}/${datadir} ] ; then
259             rm -f ${root}/${datadir}
260             mkdir -p ${root}/${datadir}
261         fi
262     done
263 }
264
265 ########## .pkgs format
266 # comments start with a # - this is needed only if you use a keyword in a comment
267 # for a given keyword like 'package' :
268 # we support fcdistro-dependant format, for tokens (pkgname) without whitespace
269 # you can e.g. use
270 # package: pkg1 .. pkgn 
271 # package+f8: pkg1 .. pkgn
272 # package-f8: pkg1 .. pkgn
273
274 function pl_parsePkgs () {
275
276     keyword=$1;shift
277     fcdistro=$1; shift
278     # remaining arguments are paths to the pkgs files
279
280     # grab regular descriptions
281     all=$(grep -v '^#' "$@" | grep --regexp="^${keyword}:" | sed -e "s,${keyword}:,,")
282     # grab additions
283     add=$(grep -v '^#' "$@" | grep --regexp="^${keyword}+${fcdistro}:" | sed -e "s,${keyword}\+${fcdistro}:,,")
284     # grab exclusions
285     sub=$(grep -v '^#' "$@" | grep --regexp="^${keyword}\-${fcdistro}:" | sed -e "s,${keyword}\-${fcdistro}:,,")
286
287     for i in $all $add; do
288         for exclude in $sub; do
289             [ "$i" = "$exclude" ] && continue 2
290         done
291         echo "$i "
292     done
293     return 0
294 }
295
296 function pl_getPackages() { fcdistro=$1; shift ; pl_parsePkgs package $fcdistro "$@" ; }
297 function pl_getGroups() { fcdistro=$1; shift ; pl_parsePkgs group $fcdistro "$@" ; }
298
299 # locates a pldistro-dependant file
300 # tries first in build/<pldistro>/, then in build/planetlab/
301 function pl_locateDistroFile () {
302     builddir=$1; shift
303     pldistro=$1; shift
304     pkgsfile=$1; shift
305
306     pkgspath=""
307     # locate it
308     paths="$builddir/config.$pldistro/$pkgsfile $builddir/config.planetlab/$pkgsfile"
309     for path in $paths; do
310         if [ -f $path ] ; then
311             pkgspath=$path
312             break
313         fi
314     done
315     if [ -z "$pkgspath" ] ; then
316         echo 1>&2 "pl_locateDistroFile - in $(pwd) : cannot locate $pkgsfile in $builddir"
317         echo 1>&2 "candidates were $paths"
318         echo "not-found-by-pl_locateDistroFile"
319         return 1
320     else
321         echo 1>&2 "pl_locateDistroFile: using $pkgspath"
322         echo $pkgspath
323         return 0
324     fi
325 }