better usage message
[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=f7
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     cd /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                 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     cd -
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 1 2 3 4 5 ; do
93         $personality vserver $VERBOSE $vserver build $VSERVER_OPTIONS -m yum -- -d $fcdistro && break || true
94         echo "Waiting for one minute"
95         sleep 60
96     done
97     # check success
98     [ -d /vservers/$vserver ] 
99
100     if [ ! -z "$personality" ] ; then
101         registered_personality=$(grep $personality /etc/vservers/$vserver/personality | wc -l)
102         if [ $registered_personality -eq 0 -a "$personality" != "linux64" ] ; then
103             echo $personality >> /etc/vservers/$vserver/personality
104         fi
105     fi
106
107     if [ -n "$VBUILD_MODE" ] ; then 
108     # set up appropriate vserver capabilities to mount, mknod and IPC_LOCK
109         BCAPFILE=/etc/vservers/$vserver/bcapabilities
110         touch $BCAPFILE
111         cap=$(grep ^CAP_SYS_ADMIN /etc/vservers/$vserver/bcapabilities | wc -l)
112         [ $cap -eq 0 ] && echo 'CAP_SYS_ADMIN' >> /etc/vservers/$vserver/bcapabilities
113         cap=$(grep ^CAP_MKNOD /etc/vservers/$vserver/bcapabilities | wc -l)
114         [ $cap -eq 0 ] && echo 'CAP_MKNOD' >> /etc/vservers/$vserver/bcapabilities
115         cap=$(grep ^CAP_IPC_LOCK /etc/vservers/$vserver/bcapabilities | wc -l)
116         [ $cap -eq 0 ] && echo 'CAP_IPC_LOCK' >> /etc/vservers/$vserver/bcapabilities
117     fi
118
119     $personality vyum $vserver -- -y install yum
120     $personality vserver $VERBOSE $vserver pkgmgmt internalize
121
122     # start the vserver so we can do the following operations
123     $personality vserver $VERBOSE $vserver start
124     $personality vserver $VERBOSE $vserver exec rm -f /var/lib/rpm/__db*
125     $personality vserver $VERBOSE $vserver exec rpm --rebuilddb
126
127     # minimal config in the vserver for yum to work
128     configure_yum_in_vserver $vserver $fcdistro 
129
130     # set up resolv.conf
131     cp /etc/resolv.conf /vservers/$vserver/etc/resolv.conf
132 }
133
134 function devel_tools () {
135
136     set -x 
137     set -e 
138     trap failure ERR INT
139
140     vserver=$1; shift
141     fcdistro=$1; shift
142     pldistro=$1; shift
143     personality=$1; shift
144
145     # check for .pkgs file based on pldistro
146     if [ -n "$VBUILD_MODE" ] ; then
147         pkgsname=devel.pkgs
148     else
149         pkgsname=native-shell.pkgs
150     fi
151     pkgsfile=$(pl_locateDistroFile $DIRNAME $pldistro $pkgsname)
152
153     # install individual packages, then groups
154     packages=$(pl_getPackages ${fcdistro} $pkgsfile)
155     groups=$(pl_getGroups ${fcdistro} $pkgsfile)
156
157     [ -n "$packages" ] && $personality vserver $vserver exec yum -y install $packages
158     [ -n "$groups" ] && $personality vserver $vserver exec yum -y groupinstall $groups
159     return 0
160 }
161
162 function post_install () {
163     if [ -n "$VBUILD_MODE" ] ; then
164         post_install_vbuild "$@" 
165     else
166         post_install_myplc "$@"
167     fi
168 }
169
170 function post_install_vbuild () {
171
172     set -x 
173     set -e 
174     trap failure ERR INT
175
176     vserver=$1; shift
177     personality=$1; shift
178
179 ### From myplc-devel-native.spec
180 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
181     cat << EOF | $personality vserver $VERBOSE $vserver exec bash -x
182     # set up /dev/loop* in vserver
183     for i in \$(seq 0 255) ; do
184         mknod -m 640 /dev/loop\$i b 7 \$i
185     done
186     
187     # create symlink for /dev/fd
188     ln -fs /proc/self/fd /dev/fd
189
190     # modify /etc/rpm/macros to not use /sbin/new-kernel-pkg
191     sed -i 's,/sbin/new-kernel-pkg:,,' /etc/rpm/macros
192     if [ -h "/sbin/new-kernel-pkg" ] ; then
193         filename=\$(readlink -f /sbin/new-kernel-pkg)
194         if [ "\$filename" == "/sbin/true" ] ; then
195                 echo "WARNING: /sbin/new-kernel-pkg symlinked to /sbin/true"
196                 echo "\tmost likely /etc/rpm/macros has /sbin/new-kernel-pkg declared in _netsharedpath."
197                 echo "\tPlease remove /sbin/new-kernel-pkg from _netsharedpath and reintall mkinitrd."
198                 exit 1
199         fi
200     fi
201     
202     # customize root's prompt
203     cat << PROFILE > /root/.profile
204 export PS1="[$vserver] \\w # "
205 PROFILE
206
207     uid=2000
208     gid=2000
209     
210     # add a "build" user to the system
211     builduser=\$(grep "^build:" /etc/passwd | wc -l)
212     if [ \$builduser -eq 0 ] ; then
213         groupadd -o -g \$gid build;
214         useradd -o -c 'Automated Build' -u \$uid -g \$gid -n -M -s /bin/bash build;
215     fi
216
217 # Allow build user to build certain RPMs as root
218     if [ -f /etc/sudoers ] ; then
219         buildsudo=\$(grep "^build.*ALL=(ALL).*NOPASSWD:.*ALL"  /etc/sudoers | wc -l)
220         if [ \$buildsudo -eq 0 ] ; then
221             echo "build   ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers
222         fi
223         sed -i 's,^Defaults.*requiretty,#Defaults requiretty,' /etc/sudoers
224     fi
225 #
226 EOF
227
228 }
229
230 function post_install_myplc  () {
231     set -x 
232     set -e 
233     trap failure ERR INT
234
235     vserver=$1; shift
236     personality=$1; shift
237
238 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
239     cat << EOF | $personality vserver $VERBOSE $vserver exec bash -x
240
241     # customize root's prompt
242     cat << PROFILE > /root/.profile
243 export PS1="[$vserver] \\w # "
244 PROFILE
245
246 EOF
247 }
248
249 COMMAND_VBUILD="vbuild-init-vserver.sh"
250 COMMAND_MYPLC="myplc-init-vserver.sh"
251 function usage () {
252     set +x 
253     echo "Usage: $COMMAND_VBUILD [options] vserver-name [ -- vserver-options ]"
254     echo "Usage: $COMMAND_MYPLC [options] vserver-name repo-url [ -- vserver-options ]"
255     echo "Requirements: you need to have a vserver-compliant kernel,"
256     echo "   as well as the util-vserver RPM installed"
257     echo "Description:"
258     echo "   This command creates a fresh vserver instance, for building, or running, myplc"
259     echo "Supported options"
260     echo " -f fcdistro - for creating the root filesystem - defaults to $DEFAULT_FCDISTRO"
261     echo " -d pldistro - defaults to $DEFAULT_PLDISTRO"
262     echo " -p personality - defaults to $DEFAULT_PERSONALITY"
263     echo " -v : verbose - passes -v to calls to vserver"
264     echo "vserver-options"
265     echo "  all args after the optional -- are passed to vserver <name> build <options>"
266     echo "  typical usage is e.g. --interface eth0:200.150.100.10/24"
267     exit 1
268 }
269
270 ### parse args and 
271 function main () {
272
273     set -e
274     trap failure ERR INT
275
276     case "$COMMAND" in
277         $COMMAND_VBUILD)
278             VBUILD_MODE=true ;;
279         $COMMAND_MYPLC)
280             MYPLC_MODE=true;;
281         *)
282             usage ;;
283     esac
284
285     VERBOSE=
286     while getopts "f:d:p:v" opt ; do
287         case $opt in
288             f) fcdistro=$OPTARG;;
289             d) pldistro=$OPTARG;;
290             p) personality=$OPTARG;;
291             v) VERBOSE="-v" ;;
292             *) usage ;;
293         esac
294     done
295         
296     shift $(($OPTIND - 1))
297
298     # parse fixed arguments
299     [[ -z "$@" ]] && usage
300     vserver=$1 ; shift
301     if [ -n "$MYPLC_MODE" ] ; then
302         [[ -z "$@" ]] && usage
303         REPO_URL=$1 ; shift
304     fi
305
306     # parse vserver options
307     if [[ -n "$@" ]] ; then
308         if [ "$1" == "--" ] ; then
309             shift
310             VSERVER_OPTIONS="$@"
311         else
312             usage
313         fi
314     fi
315
316     [ -z "$fcdistro" ] && fcdistro=$DEFAULT_FCDISTRO
317     [ -z "$pldistro" ] && pldistro=$DEFAULT_PLDISTRO
318     [ -z "$personality" ] && personality=$DEFAULT_PERSONALITY
319
320     setup_vserver $vserver $fcdistro $personality 
321     devel_tools $vserver $fcdistro $pldistro $personality
322     post_install $vserver $personality
323
324 }
325
326 main "$@"