vserver & ctx_migrate workaround : more numerous (20) attempts, wait for only 3 sec
[build.git] / vbuild-init-vserver.sh
1 #!/bin/bash
2 # -*-shell-*-
3
4 COMMAND=$(basename $0)
5 DIRNAME=$(dirname $0)
6
7 # pkgs parsing utilities
8 PATH=$(dirname $0):$PATH . build.common
9
10 DEFAULT_FCDISTRO=f8
11 DEFAULT_PLDISTRO=planetlab
12 DEFAULT_PERSONALITY=linux32
13
14 function failure () {
15     echo "$COMMAND : Bailing out"
16     exit 1
17 }
18
19 # overwrite vserver's internal yum config from what is in
20 # .distributions/<distrib>/yum/yum.conf and /yum.repos.d 
21
22 function configure_yum_in_vserver () {
23     set -x 
24     set -e 
25     trap failure ERR INT
26
27     vserver=$1; shift
28     fcdistro=$1; shift
29
30     pushd /etc/vservers/.distributions/${fcdistro}
31     if [ -f yum/yum.conf ] ; then
32         echo "Initializing yum.conf in $vserver from $(pwd)/yum"
33         sed -e "s!@YUMETCDIR@!/etc!g;
34                 s!@YUMCACHEDIR@!/var/cache/yum!g;
35                 s!@YUMLOGDIR@!/var/log!g;
36                 s!@YUMLOCKDIR@!/var/lock!g;
37                " yum/yum.conf > /vservers/$vserver/etc/yum.conf
38
39         # post process the various @...@ variables from this yum.conf file.
40     else
41         echo "Using $fcdistro default for yum.conf"
42     fi
43
44     if [ -d yum.repos.d ] ; then
45         echo "Initializing yum.repos.d in $vserver from $(pwd)/yum.repos.d"
46         rm -rf /vservers/$vserver/etc/yum.repos.d
47         tar cf - yum.repos.d | tar -C /vservers/$vserver/etc -xvf -
48     else
49         echo "Cannot initialize yum.repos.d in $vserver"
50     fi
51
52     if [ -n "$MYPLC_MODE" ] ; then
53         if [ ! -d /vservers/$vserver/etc/yum.repos.d ] ; then
54             echo "WARNING : cannot create myplc repo"
55         else
56             # exclude kernel from fedora repos 
57             for i in /vservers/$vserver/etc/yum.repos.d/* ; do
58                 [ -f $i ] && echo "exclude=kernel* ulogd iptables" >> $i
59             done
60             # the build repo is not signed at this stage
61             cat > /vservers/$vserver/etc/yum.repos.d/myplc.repo <<EOF
62 [myplc]
63 name= MyPLC
64 baseurl=$REPO_URL
65 enabled=1
66 gpgcheck=0
67 EOF
68         fi
69     fi
70     popd
71 }    
72
73 function setup_vserver () {
74
75     set -x
76     set -e
77     trap failure ERR INT
78
79     vserver=$1; shift
80     fcdistro=$1; shift
81     personality=$1; shift
82
83     if [ -d /vservers/$vserver ] ; then
84         echo "$COMMAND : vserver $vserver seems to exist - bailing out"
85         exit 1
86     fi
87
88     # create it
89     # try to work around the vserver issue:
90     # vc_ctx_migrate: No such process
91     # rpm-fake.so: failed to initialize communication with resolver
92     for i in $(seq 20) ; do
93         $personality vserver $VERBOSE $vserver build $VSERVER_OPTIONS -m yum -- -d $fcdistro && break || true
94         echo "* ${i}-th attempt to 'vserver build' failed - waiting for 3 seconds"
95         sleep 3
96     done
97     # check success
98     [ -d /vservers/$vserver ] 
99
100     if [ ! -z "$personality" ] ; then
101         if [ -f "/etc/vservers/$vserver/personality" ] ; then
102             registered_personality=$(grep $personality /etc/vservers/$vserver/personality | wc -l)
103         else
104             registered_personality=0
105         fi
106         if [ $registered_personality -eq 0 -a "$personality" != "linux64" ] ; then
107             echo $personality >> /etc/vservers/$vserver/personality
108         fi
109     fi
110
111     if [ -n "$VBUILD_MODE" ] ; then 
112         ### capabilities required for a build vserver
113         # set up appropriate vserver capabilities to mount, mknod and IPC_LOCK
114         BCAPFILE=/etc/vservers/$vserver/bcapabilities
115         touch $BCAPFILE
116         cap=$(grep ^CAP_SYS_ADMIN /etc/vservers/$vserver/bcapabilities | wc -l)
117         [ $cap -eq 0 ] && echo 'CAP_SYS_ADMIN' >> /etc/vservers/$vserver/bcapabilities
118         cap=$(grep ^CAP_MKNOD /etc/vservers/$vserver/bcapabilities | wc -l)
119         [ $cap -eq 0 ] && echo 'CAP_MKNOD' >> /etc/vservers/$vserver/bcapabilities
120         cap=$(grep ^CAP_IPC_LOCK /etc/vservers/$vserver/bcapabilities | wc -l)
121         [ $cap -eq 0 ] && echo 'CAP_IPC_LOCK' >> /etc/vservers/$vserver/bcapabilities
122     else
123         ### capabilities required for a myplc vserver
124         # for /etc/plc.d/gpg - need to init /dev/random
125         cap=$(grep ^CAP_MKNOD /etc/vservers/$vserver/bcapabilities | wc -l)
126         [ $cap -eq 0 ] && echo 'CAP_MKNOD' >> /etc/vservers/$vserver/bcapabilities
127         cap=$(grep ^CAP_NET_BIND_SERVICE /etc/vservers/$vserver/bcapabilities | wc -l)
128         [ $cap -eq 0 ] && echo 'CAP_NET_BIND_SERVICE' >> /etc/vservers/$vserver/bcapabilities
129     fi
130
131     $personality vyum $vserver -- -y install yum
132     # ditto
133     for i in $(seq 20) ; do
134         $personality vserver $VERBOSE $vserver pkgmgmt internalize && break || true
135         echo "* ${i}-th attempt to 'vserver pkgmgmt internalize' failed - waiting for 3 seconds"
136         sleep 3
137     done
138
139     # start the vserver so we can do the following operations
140     $personality vserver $VERBOSE $vserver start
141     $personality vserver $VERBOSE $vserver exec sh -c "rm -f /var/lib/rpm/__db*"
142     $personality vserver $VERBOSE $vserver exec rpm --rebuilddb
143
144     # with vserver 2.3, granting the vserver CAP_MKNOD is not enough
145     # check whether we run vs2.3 or above
146     vs_version=$(uname -a  | sed -e 's,.*[\.\-]vs\([0-9]\)\.\([0-9]\)\..*,\1\2,')
147     # at this stage we have here 22 or 23
148     need_vdevmap=$(( $vs_version >= 23 ))
149
150     if [ "$need_vdevmap" == 1 ] ; then
151         util_vserver_215=0
152         vdevmap --help | grep -- --set &> /dev/null && util_vserver_215=1
153         
154         if [ "$util_vserver_215" == 1 ] ; then
155             ctx=$(cat /etc/vservers/$vserver/context)
156             vdevmap --set --xid $ctx --open --create --target /dev/null
157             vdevmap --set --xid $ctx --open --create --target /dev/root
158         else
159             echo "You seem to be running vs2.3 with util-vserver < 0.30.215"
160             echo "This combination is not supported by $COMMAND"
161             echo "Please upgrade your environment"
162             exit 1
163 # this supposedly is an equivalent to using vdevmap as invoked above
164 # but it's not going to work in this case
165 #           mkdir -p /etc/vservers/$vserver/apps/vdevmap/default-{block,char}
166 #           touch /etc/vservers/$vserver/apps/vdevmap/default-{block,char}/{open,create}
167 #           echo /dev/root > /etc/vservers/$vserver/apps/vdevmap/default-block/target
168 #           echo /dev/null > /etc/vservers/$vserver/apps/vdevmap/default-char/target
169         fi
170     fi
171             
172     # minimal config in the vserver for yum to work
173     configure_yum_in_vserver $vserver $fcdistro 
174
175     # set up resolv.conf
176     cp /etc/resolv.conf /vservers/$vserver/etc/resolv.conf
177     # and /etc/hosts for at least localhost
178     [ -f /vservers/$vserver/etc/hosts ] || echo "127.0.0.1 localhost localhost.localdomain" > /vservers/$vserver/etc/hosts
179 }
180
181 function devel_or_vtest_tools () {
182
183     set -x 
184     set -e 
185     trap failure ERR INT
186
187     vserver=$1; shift
188     fcdistro=$1; shift
189     pldistro=$1; shift
190     personality=$1; shift
191
192     # check for .pkgs file based on pldistro
193     if [ -n "$VBUILD_MODE" ] ; then
194         pkgsname=devel.pkgs
195     else
196         pkgsname=vtest.pkgs
197     fi
198     pkgsfile=$(pl_locateDistroFile $DIRNAME $pldistro $pkgsname)
199
200     # install individual packages, then groups
201     packages=$(pl_getPackages $fcdistro $pldistro $pkgsfile)
202     groups=$(pl_getGroups $fcdistro $pldistro $pkgsfile)
203
204     [ -n "$packages" ] && $personality vserver $vserver exec yum -y install $packages
205     [ -n "$groups" ] && $personality vserver $vserver exec yum -y groupinstall $groups
206     return 0
207 }
208
209 function post_install () {
210     if [ -n "$VBUILD_MODE" ] ; then
211         post_install_vbuild "$@" 
212     else
213         post_install_myplc "$@"
214     fi
215 }
216
217 function post_install_vbuild () {
218
219     set -x 
220     set -e 
221     trap failure ERR INT
222
223     vserver=$1; shift
224     personality=$1; shift
225
226 ### From myplc-devel-native.spec
227 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
228     cat << EOF | $personality vserver $VERBOSE $vserver exec bash -x
229     # set up /dev/loop* in vserver
230     for i in \$(seq 0 255) ; do
231         mknod -m 640 /dev/loop\$i b 7 \$i
232     done
233     
234     # create symlink for /dev/fd
235     [ ! -e "/dev/fd" ] && ln -s /proc/self/fd /dev/fd
236
237     # modify /etc/rpm/macros to not use /sbin/new-kernel-pkg
238     sed -i 's,/sbin/new-kernel-pkg:,,' /etc/rpm/macros
239     if [ -h "/sbin/new-kernel-pkg" ] ; then
240         filename=\$(readlink -f /sbin/new-kernel-pkg)
241         if [ "\$filename" == "/sbin/true" ] ; then
242                 echo "WARNING: /sbin/new-kernel-pkg symlinked to /sbin/true"
243                 echo "\tmost likely /etc/rpm/macros has /sbin/new-kernel-pkg declared in _netsharedpath."
244                 echo "\tPlease remove /sbin/new-kernel-pkg from _netsharedpath and reintall mkinitrd."
245                 exit 1
246         fi
247     fi
248     
249     # customize root's prompt
250     cat << PROFILE > /root/.profile
251 export PS1="[$vserver] \\w # "
252 PROFILE
253
254     uid=2000
255     gid=2000
256     
257     # add a "build" user to the system
258     builduser=\$(grep "^build:" /etc/passwd | wc -l)
259     if [ \$builduser -eq 0 ] ; then
260         groupadd -o -g \$gid build;
261         useradd -o -c 'Automated Build' -u \$uid -g \$gid -n -M -s /bin/bash build;
262     fi
263
264 # Allow build user to build certain RPMs as root
265     if [ -f /etc/sudoers ] ; then
266         buildsudo=\$(grep "^build.*ALL=(ALL).*NOPASSWD:.*ALL"  /etc/sudoers | wc -l)
267         if [ \$buildsudo -eq 0 ] ; then
268             echo "build   ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers
269         fi
270         sed -i 's,^Defaults.*requiretty,#Defaults requiretty,' /etc/sudoers
271     fi
272 #
273 EOF
274
275 }
276
277 function post_install_myplc  () {
278     set -x 
279     set -e 
280     trap failure ERR INT
281
282     vserver=$1; shift
283     personality=$1; shift
284
285 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
286     cat << EOF | $personality vserver $VERBOSE $vserver exec bash -x
287
288     # create symlink for /dev/fd
289     [ ! -e "/dev/fd" ] && ln -s /proc/self/fd /dev/fd
290
291     # customize root's prompt
292     cat << PROFILE > /root/.profile
293 export PS1="[$vserver] \\w # "
294 PROFILE
295
296 EOF
297 }
298
299 COMMAND_VBUILD="vbuild-init-vserver.sh"
300 COMMAND_MYPLC="vtest-init-vserver.sh"
301 function usage () {
302     set +x 
303     echo "Usage: $COMMAND_VBUILD [options] vserver-name [ -- vserver-options ]"
304     echo "Usage: $COMMAND_MYPLC [options] vserver-name repo-url [ -- vserver-options ]"
305     echo "Requirements: you need to have a vserver-compliant kernel,"
306     echo "   as well as the util-vserver RPM installed"
307     echo "Description:"
308     echo "   This command creates a fresh vserver instance, for building, or running, myplc"
309     echo "Supported options"
310     echo " -f fcdistro - for creating the root filesystem - defaults to $DEFAULT_FCDISTRO"
311     echo " -d pldistro - defaults to $DEFAULT_PLDISTRO"
312     echo " -p personality - defaults to $DEFAULT_PERSONALITY"
313     echo " -v : verbose - passes -v to calls to vserver"
314     echo "vserver-options"
315     echo "  all args after the optional -- are passed to vserver <name> build <options>"
316     echo "  typical usage is e.g. --interface eth0:200.150.100.10/24"
317     exit 1
318 }
319
320 ### parse args and 
321 function main () {
322
323     set -e
324     trap failure ERR INT
325
326     case "$COMMAND" in
327         $COMMAND_VBUILD)
328             VBUILD_MODE=true ;;
329         $COMMAND_MYPLC)
330             MYPLC_MODE=true;;
331         *)
332             usage ;;
333     esac
334
335     VERBOSE=
336     while getopts "f:d:p:v" opt ; do
337         case $opt in
338             f) fcdistro=$OPTARG;;
339             d) pldistro=$OPTARG;;
340             p) personality=$OPTARG;;
341             v) VERBOSE="-v" ;;
342             *) usage ;;
343         esac
344     done
345         
346     shift $(($OPTIND - 1))
347
348     # parse fixed arguments
349     [[ -z "$@" ]] && usage
350     vserver=$1 ; shift
351     if [ -n "$MYPLC_MODE" ] ; then
352         [[ -z "$@" ]] && usage
353         REPO_URL=$1 ; shift
354     fi
355
356     # parse vserver options
357     if [[ -n "$@" ]] ; then
358         if [ "$1" == "--" ] ; then
359             shift
360             VSERVER_OPTIONS="$@"
361         else
362             usage
363         fi
364     fi
365
366     [ -z "$fcdistro" ] && fcdistro=$DEFAULT_FCDISTRO
367     [ -z "$pldistro" ] && pldistro=$DEFAULT_PLDISTRO
368     [ -z "$personality" ] && personality=$DEFAULT_PERSONALITY
369
370     setup_vserver $vserver $fcdistro $personality 
371     devel_or_vtest_tools $vserver $fcdistro $pldistro $personality
372     post_install $vserver $personality
373
374 }
375
376 main "$@"