- create a planetlab-v3 symlink for backward compatibility
[myplc.git] / guest.init
1 #!/bin/bash
2 #
3 # plc   Manages all PLC services on this machine
4 #
5 # chkconfig: 2345 5 99
6 #
7 # description:  Manages all PLC services on this machine
8 #
9 # $Id: guest.init,v 1.9 2006/03/31 00:41:03 mlhuang Exp $
10 #
11
12 PATH=/sbin:/bin:/usr/bin:/usr/sbin
13
14 # Source function library.
15 . /etc/init.d/functions
16
17 # Verbosity
18 verbose=0
19
20 # Keep in order! All steps should be idempotent. This means that you
21 # should be able to run them multiple times without depending on
22 # anything previously being run. The idea is that when the
23 # configuration changes, "service plc restart" is called, all
24 # dependencies are fixed up, and everything just works.
25 steps=(
26 network
27 syslog
28 postgresql
29 ssl
30 gpg
31 ssh
32 apache
33 api
34 cron
35 bootcd
36 bootmanager
37 )
38 nsteps=${#steps[@]}
39
40 # Total number of errors
41 ERRORS=0
42
43 # Count the exit status of the last command
44 check ()
45 {
46     ERRORS=$(($ERRORS+$?))
47 }
48
49 # Return IP address of hostname if resolvable
50 gethostbyname ()
51 {
52     perl -MSocket -e '($a,$b,$c,$d,@addrs) = gethostbyname($ARGV[0]); print inet_ntoa($addrs[0]) . "\n";' $1 2>/dev/null
53 }
54
55 # Regenerate configuration files
56 reload ()
57 {
58     # Load configuration
59     plc-config --shell >/etc/planetlab/plc_config
60     . /etc/planetlab/plc_config
61
62     # Generate various defaults
63     if [ -z "$PLC_DB_PASSWORD" ] ; then
64         PLC_DB_PASSWORD=$(uuidgen)
65         plc-config --category=plc_db --variable=password --value="$PLC_DB_PASSWORD" --save
66     fi
67
68     if [ -z "$PLC_API_MAINTENANCE_PASSWORD" ] ; then
69         PLC_API_MAINTENANCE_PASSWORD=$(uuidgen)
70         plc-config --category=plc_api --variable=maintenance_password --value="$PLC_API_MAINTENANCE_PASSWORD" --save
71     fi
72
73     # Need to configure network before resolving hostnames
74     config_network start
75
76     PLC_API_MAINTENANCE_SOURCES=$(
77         for server in API BOOT WWW ; do
78             hostname=PLC_${server}_HOST
79             gethostbyname ${!hostname}
80         done | sort -u
81     )
82     plc-config --category=plc_api --variable=maintenance_sources --value="$PLC_API_MAINTENANCE_SOURCES" --save
83
84     # Save configuration
85     mkdir -p /etc/planetlab/php
86     plc-config --php >/etc/planetlab/php/plc_config.php
87     plc-config --shell >/etc/planetlab/plc_config
88
89     # For backward compatibility, until we can convert all code to use
90     # the now standardized variable names.
91
92     # DB constants are all named the same
93     ln -sf plc_config /etc/planetlab/plc_db
94
95     # API constants
96     cat >/etc/planetlab/plc_api <<EOF
97 PL_API_SERVER='$PLC_API_HOST'
98 PL_API_PATH='$PLC_API_PATH'
99 PL_API_PORT=$PLC_API_PORT
100 PL_API_CAPABILITY_AUTH_METHOD='capability'
101 PL_API_CAPABILITY_PASS='$PLC_API_MAINTENANCE_PASSWORD'
102 PL_API_CAPABILITY_USERNAME='$PLC_API_MAINTENANCE_USER'
103 PL_API_TICKET_KEY_FILE='$PLC_API_SSL_KEY'
104 PLANETLAB_SUPPORT_EMAIL='$PLC_MAIL_SUPPORT_ADDRESS'
105 BOOT_MESSAGES_EMAIL='$PLC_MAIL_BOOT_ADDRESS'
106 WWW_BASE='$PLC_WWW_HOST'
107 BOOT_BASE='$PLC_BOOT_HOST'
108 EOF
109
110     # The format is
111     #
112     # ip:max_role_id:organization_id:password
113     #
114     # It is unlikely that we will let federated sites use the
115     # maintenance account to access each others' APIs, so we always
116     # set organization_id to -1.
117     (
118         echo -n "PL_API_CAPABILITY_SOURCES='"
119         first=1
120         for ip in $PLC_API_MAINTENANCE_SOURCES ; do
121             if [ $first -ne 1 ] ; then
122                 echo -n " "
123             fi
124             first=0
125             echo -n "$ip:-1:-1:$PLC_API_MAINTENANCE_PASSWORD"
126         done
127         echo "'"
128     ) >>/etc/planetlab/plc_api
129
130     cat >/etc/planetlab/php/site_constants.php <<"EOF"
131 <?php
132 include('plc_config.php');
133
134 DEFINE('PL_API_SERVER', PLC_API_HOST);
135 DEFINE('PL_API_PATH', PLC_API_PATH);
136 DEFINE('PL_API_PORT', PLC_API_PORT);
137 DEFINE('PL_API_CAPABILITY_AUTH_METHOD', 'capability');
138 DEFINE('PL_API_CAPABILITY_PASS', PLC_API_MAINTENANCE_PASSWORD);
139 DEFINE('PL_API_CAPABILITY_USERNAME', PLC_API_MAINTENANCE_USER);
140 DEFINE('WWW_BASE', PLC_WWW_HOST);
141 DEFINE('BOOT_BASE', PLC_BOOT_HOST);
142 DEFINE('DEBUG', PLC_WWW_DEBUG);
143 DEFINE('API_CALL_DEBUG', PLC_API_DEBUG);
144 DEFINE('SENDMAIL', PLC_MAIL_ENABLED);
145 DEFINE('PLANETLAB_SUPPORT_EMAIL', PLC_NAME . 'Support <' . PLC_MAIL_SUPPORT_ADDRESS . '>');
146 DEFINE('PLANETLAB_SUPPORT_EMAIL_ONLY', PLC_MAIL_SUPPORT_ADDRESS);
147 ?>
148 EOF
149 }
150
151 config_network ()
152 {
153     case "$1" in
154         start)
155             # Minimal /etc/hosts
156             echo "127.0.0.1     localhost.localdomain localhost" >/etc/hosts
157             (
158                 for server in API BOOT WWW ; do
159                     hostname=PLC_${server}_HOST
160                     ip=$(gethostbyname ${!hostname})
161                     if [ -n "$ip" ] ; then
162                         echo "$ip       $hostname"
163                     fi
164                 done
165             ) >>/etc/hosts
166
167             # Set up nameservers
168             (
169                 [ -n "$PLC_NET_DNS1" ] && echo "nameserver $PLC_NET_DNS1"
170                 [ -n "$PLC_NET_DNS2" ] && echo "nameserver $PLC_NET_DNS2"
171             ) >/etc/resolv.conf
172             ;;
173     esac
174 }
175
176 config_syslog ()
177 {
178     service syslog $1
179     check
180 }
181
182 config_postgresql ()
183 {
184     # Default locations
185     PGDATA=/var/lib/pgsql/data
186     postgresql_conf=$PGDATA/postgresql.conf
187     pghba_conf=$PGDATA/pg_hba.conf
188
189     # Export so that we do not have to specify -p to psql invocations
190     export PGPORT=$PLC_DB_PORT
191
192     case "$1" in
193         start)
194             if [ "$PLC_DB_ENABLED" != "1" ] ; then
195                 return 0
196             fi
197
198             # Set data directory and redirect startup output to /var/log/pgsql
199             mkdir -p /etc/sysconfig/pgsql
200             (
201                 echo "PGDATA=$PGDATA"
202                 echo "PGLOG=/var/log/pgsql"
203                 echo "PGPORT=$PLC_DB_PORT"
204             ) >>/etc/sysconfig/pgsql/postgresql
205
206             # Fix ownership (rpm installation may have changed it)
207             chown -R -H postgres:postgres $(dirname $PGDATA)
208
209             # PostgreSQL must be started at least once to bootstrap
210             # /var/lib/pgsql/data
211             if [ ! -f $postgresql_conf ] ; then
212                 service postgresql start
213                 service postgresql stop
214             fi
215
216             # Enable DB server. PostgreSQL >=8.0 defines listen_addresses,
217             # PostgreSQL 7.x uses tcpip_socket.
218             if grep -q listen_addresses $postgresql_conf ; then
219                 sed -i -e '/^listen_addresses/d' $postgresql_conf
220                 echo "listen_addresses = '*'" >>$postgresql_conf
221             elif grep -q tcpip_socket $postgresql_conf ; then
222                 sed -i -e '/^tcpip_socket/d' $postgresql_conf
223                 echo "tcpip_socket = true" >>$postgresql_conf
224             fi
225
226             # Disable access to all DBs from all hosts
227             sed -i -e '/^\(host\|local\)/d' $pghba_conf
228
229             # Enable passwordless localhost access
230             echo "local all all trust" >>$pghba_conf
231
232             # Enable access from the API and web servers
233             PLC_API_IP=$(gethostbyname $PLC_API_HOST)
234             PLC_WWW_IP=$(gethostbyname $PLC_WWW_HOST)
235             (
236                 echo "host $PLC_DB_NAME $PLC_DB_USER $PLC_API_IP/32 password"
237                 echo "host $PLC_DB_NAME $PLC_DB_USER $PLC_WWW_IP/32 password"
238             ) >>$pghba_conf
239
240             # Fix ownership (sed -i changes it)
241             chown postgres:postgres $postgresql_conf $pghba_conf
242
243             # Start up the server
244             service postgresql start
245             # /etc/init.d/postgresql always returns 0, even on failure
246             status postmaster && [ -f /var/lock/subsys/postgresql ]
247             check
248
249             # Create/update the unprivileged database user and password
250             if ! psql -U $PLC_DB_USER -c "" template1 >/dev/null 2>&1 ; then
251                 psql -U postgres -c "CREATE USER $PLC_DB_USER PASSWORD '$PLC_DB_PASSWORD'" template1
252             else
253                 psql -U postgres -c "ALTER USER $PLC_DB_USER WITH PASSWORD '$PLC_DB_PASSWORD'" template1
254             fi
255
256             # Create the database if necessary
257             if ! psql -U $PLC_DB_USER -c "" $PLC_DB_NAME >/dev/null 2>&1 ; then
258                 createdb -U postgres $PLC_DB_NAME
259                 psql -U $PLC_DB_USER -f /usr/share/pl_db/plc_schema_3.sql $PLC_DB_NAME
260             fi
261             ;;
262
263         stop)
264             # Drop the current user in case the username changes
265             psql -U postgres -c "DROP USER $PLC_DB_USER" template1
266
267             # WARNING: If the DB name changes, the old DB will be left
268             # intact and a new one will be created. If it changes
269             # back, the old DB will not be re-created.
270
271             # Shut down the server
272             service postgresql stop
273             check
274             ;;
275     esac
276 }
277
278 # Generate GPG keys
279 config_gpg ()
280 {
281     case "$1" in
282         start)
283             # Generate GPG keyrings
284             if [ ! -f $PLC_ROOT_GPG_KEY_PUB -o ! -f $PLC_ROOT_GPG_KEY ] ; then
285                 mkdir -p $(dirname $PLC_ROOT_GPG_KEY_PUB)
286                 mkdir -p $(dirname $PLC_ROOT_GPG_KEY)
287
288                 # Temporarily replace /dev/random with /dev/urandom to
289                 # avoid running out of entropy.
290                 rm -f /dev/random
291                 mknod /dev/random c 1 9
292                 gpg --homedir=/root --batch --gen-key <<EOF
293 Key-Type: DSA
294 Key-Length: 1024
295 Subkey-Type: ELG-E
296 Subkey-Length: 1024
297 Name-Real: $PLC_NAME Central
298 Name-Comment: http://$PLC_WWW_HOST/
299 Name-Email: $PLC_MAIL_SUPPORT_ADDRESS
300 Expire-Date: 0
301 %pubring $PLC_ROOT_GPG_KEY_PUB
302 %secring $PLC_ROOT_GPG_KEY
303 %commit
304 EOF
305                 check
306                 rm -f /dev/random
307                 mknod /dev/random c 1 8
308                 chmod 600 $PLC_ROOT_GPG_KEY_PUB $PLC_ROOT_GPG_KEY
309             fi
310             ;;
311     esac
312 }
313
314 ssl_cname ()
315 {
316     openssl x509 -noout -in $1 -subject | \
317         sed -n -e 's@.*/CN=\([^/]*\).*@\1@p'
318 }
319
320 symlink ()
321 {
322     mkdir -p $(dirname $2)
323     rm -f $2
324     ln -s $1 $2
325 }
326
327 # Generate SSL certificates
328 config_ssl ()
329 {
330     case "$1" in
331         start)
332             # Generate self-signed SSL certificate(s). These nice
333             # commands come from the mod_ssl spec file for Fedora Core
334             # 2. We generate a certificate for each enabled server
335             # with a different hostname. These self-signed
336             # certificates may be overridden later.
337             for server in WWW API BOOT ; do
338                 ssl_key=PLC_${server}_SSL_KEY
339                 ssl_crt=PLC_${server}_SSL_CRT
340                 hostname=PLC_${server}_HOST
341
342                 # Check if we have already generated a certificate for
343                 # the same hostname.
344                 for previous_server in WWW API BOOT ; do
345                     if [ "$server" = "$previous_server" ] ; then
346                         break
347                     fi
348                     previous_ssl_key=PLC_${previous_server}_SSL_KEY
349                     previous_ssl_crt=PLC_${previous_server}_SSL_CRT
350                     previous_hostname=PLC_${previous_server}_HOST
351
352                     if [ -f ${!previous_ssl_crt} ] && \
353                         [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
354                         cp -a ${!previous_ssl_key} ${!ssl_key}
355                         cp -a ${!previous_ssl_crt} ${!ssl_crt}
356                         break
357                     fi
358                 done
359
360                 # Generate new SSL private key
361                 if [ ! -f ${!ssl_key} ] ; then
362                     mkdir -p $(dirname ${!ssl_key})
363                     openssl genrsa -rand /proc/apm:/proc/cpuinfo:/proc/dma:/proc/filesystems:/proc/interrupts:/proc/ioports:/proc/pci:/proc/rtc:/proc/uptime 1024 >${!ssl_key}
364                     check
365                     chmod 600 ${!ssl_key}
366                 fi
367
368                 # Check if self signed certificate is valid
369                 if [ -f ${!ssl_crt} ] ; then
370                     verify=$(openssl verify ${!ssl_crt})
371                     # If self signed
372                     if grep -q "self signed certificate" <<<$verify ; then
373                         # Delete if expired or hostname changed
374                         if grep -q "expired" <<<$verify || \
375                             [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then
376                             rm -f ${!ssl_crt}
377                         fi
378                     else
379                         echo "$verify" >&2
380                     fi
381                 fi
382
383                 # Generate new self signed certificate
384                 if [ ! -f ${!ssl_crt} ] ; then
385                     mkdir -p $(dirname ${!ssl_crt})
386                     openssl req -new -x509 -days 365 -set_serial $RANDOM \
387                         -key ${!ssl_key} -out ${!ssl_crt} <<EOF
388 --
389 State
390 City
391 Organization
392 $PLC_NAME Central
393 ${!hostname}
394 $PLC_MAIL_SUPPORT_ADDRESS
395 EOF
396                     check
397                     chmod 644 ${!ssl_crt}
398                 fi
399             done
400
401             # API requires a public key for slice ticket verification
402             if [ ! -f $PLC_API_SSL_KEY_PUB ] ; then
403                 openssl rsa -pubout <$PLC_API_SSL_KEY >$PLC_API_SSL_KEY_PUB
404                 check
405             fi
406
407             # Install into both /etc/pki (Fedora Core 4) and
408             # /etc/httpd/conf (Fedora Core 2). If the API, boot, and
409             # web servers are all running on the same machine, the web
410             # server certificate takes precedence.
411             for server in API BOOT WWW ; do
412                 enabled=PLC_${server}_ENABLED
413                 if [ "${!enabled}" != "1" ] ; then
414                     continue
415                 fi
416                 ssl_key=PLC_${server}_SSL_KEY
417                 ssl_crt=PLC_${server}_SSL_CRT
418
419                 symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
420                 symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
421                 symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
422                 symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
423             done
424             ;;
425     esac
426 }
427
428 # Generate SSH keys
429 config_ssh ()
430 {
431     # XXX Could make these configurable
432     KEY_TYPE_ROOT=rsa
433     KEY_LEN_ROOT=1024
434     KEY_TYPE_DEBUG=rsa
435     KEY_LEN_DEBUG=2048  
436
437     case "$1" in
438         start)
439             tmp=$(mktemp -d /tmp/ssh.XXXXXX)
440
441             # Generate root SSH key
442             if [ ! -f $PLC_ROOT_SSH_KEY_PUB -o ! -f $PLC_ROOT_SSH_KEY ] ; then
443                 ssh-keygen -N "" -C "$PLC_NAME Central <$PLC_MAIL_SUPPORT_ADDRESS>" \
444                     -b $KEY_LEN_ROOT -t $KEY_TYPE_ROOT -f $tmp/root
445                 check
446                 install -D -m 600 $tmp/root $PLC_ROOT_SSH_KEY
447                 install -D -m 600 $tmp/root.pub $PLC_ROOT_SSH_KEY_PUB
448             fi
449
450             # Generate debug SSH key
451             if [ ! -f $PLC_DEBUG_SSH_KEY_PUB -o ! -f $PLC_DEBUG_SSH_KEY ] ; then
452                 ssh-keygen -N "" -C "$PLC_NAME Central <$PLC_MAIL_SUPPORT_ADDRESS>" \
453                     -b $KEY_LEN_DEBUG -t $KEY_TYPE_DEBUG -f $tmp/debug
454                 check
455                 install -D -m 600 $tmp/debug $PLC_DEBUG_SSH_KEY
456                 install -D -m 600 $tmp/debug.pub $PLC_DEBUG_SSH_KEY_PUB
457             fi
458
459             rm -rf $tmp
460             ;;
461     esac
462 }
463
464 # Configure Apache web server
465 config_apache ()
466 {
467     # Default locations
468     DocumentRoot=/var/www/html
469     php_ini=/etc/php.ini
470     httpd_conf=/etc/httpd/conf/httpd.conf
471     ssl_conf=/etc/httpd/conf.d/ssl.conf
472     plc_conf=/etc/httpd/conf.d/plc.conf
473
474     case "$1" in
475         start)
476             if [ "$PLC_API_ENABLED" != "1" -a \
477                  "$PLC_BOOT_ENABLED" != "1" -a \
478                  "$PLC_WWW_ENABLED" != "1" ] ; then
479                 return 0
480             fi
481
482             # Set the default include path
483             include_path=".:$DocumentRoot/includes:$DocumentRoot/generated:/etc/planetlab/php"
484             sed -i -e "s@;include_path = \"\.:.*\"@include_path = \"$include_path\"@" $php_ini
485
486             # Disable default Listen directive
487             sed -i -e '/^Listen/d' $httpd_conf
488
489             # Set the port numbers
490             for server in WWW API BOOT ; do
491                 enabled=PLC_${server}_ENABLED
492                 if [ "${!enabled}" != "1" ] ; then
493                     continue
494                 fi
495                 hostname=PLC_${server}_HOST
496                 http_port=PLC_${server}_PORT
497                 https_port=PLC_${server}_SSL_PORT
498
499                 # API should always be accessed via SSL
500                 if [ "$server" = "API" ] ; then
501                     https_port=${!http_port}
502                     http_port=
503                 fi
504
505                 # Check if we are already listening on these ports
506                 skip_http=0
507                 skip_https=0
508                 for previous_server in WWW API BOOT ; do
509                     if [ "$server" = "$previous_server" ] ; then
510                         break
511                     fi
512                     previous_hostname=PLC_${previous_server}_HOST
513                     previous_http_port=PLC_${previous_server}_PORT
514                     previous_https_port=PLC_${previous_server}_SSL_PORT
515
516                     if [ "${!http_port}" = "${!previous_http_port}" ] ; then
517                         skip_http=1
518                     fi
519                     if [ "${!https_port}" = "${!previous_https_port}" ] ; then
520                         skip_https=1
521                     fi
522                 done
523
524                 # Listen on these ports
525                 if [ $skip_http -eq 0 -a -n "${!http_port}" ] ; then
526                     cat <<EOF
527 Listen ${!http_port}
528 <VirtualHost *:${!http_port}>
529     Redirect /db https://$PLC_WWW_HOST:$PLC_WWW_SSL_PORT/db
530     # XXX Not yet until we can get rid of oldapi
531     # Redirect /$PLC_API_PATH https://$PLC_API_HOST:$PLC_API_PORT/$PLC_API_PATH
532 </VirtualHost>
533 EOF
534                 fi
535                 if [ $skip_https -eq 0 -a -n "${!https_port}" ] ; then
536                     # XXX Cannot support NameVirtualHost over SSL. If
537                     # the API, boot, and web servers are all running
538                     # on the same machine, the web server certificate
539                     # takes precedence.
540                     sed -i \
541                         -e "s/^Listen .*/Listen ${!https_port}/" \
542                         -e "s/<VirtualHost _default_:.*>/<VirtualHost _default_:${!https_port}>/" \
543                         $ssl_conf
544                 fi
545             done >$plc_conf
546
547             # Set custom Apache directives
548             (
549                 if [ "$PLC_API_ENABLED" = "1" ] ; then
550                     cat <<EOF
551 <Location $PLC_API_PATH>
552     SetHandler python-program
553     PythonPath "sys.path + ['/usr/share/plc_api']"
554     PythonHandler mod_pythonXMLRPC
555 </Location>
556 EOF
557                 else
558                     cat <<EOF
559 <Location $PLC_API_PATH>
560     Deny from all
561 </Location>
562 EOF
563                 fi
564
565                 if [ "$PLC_WWW_ENABLED" != "1" ] ; then
566                     cat <<EOF
567 <Location /db>
568     Deny from all
569 </Location>
570 EOF
571                 fi
572             ) >>$plc_conf
573
574             # Make alpina-logs directory writable for bootmanager log upload
575             chown apache:apache $DocumentRoot/alpina-logs/nodes
576
577             service httpd start
578             check
579             ;;
580
581         stop)
582             service httpd stop
583             check
584             ;;
585     esac
586 }
587
588 config_api ()
589 {
590     case "$1" in
591         start)
592             if [ "$PLC_API_ENABLED" != "1" ] ; then
593                 return
594             fi
595
596             # Update the maintenance account username. This can't be
597             # done through the api-config script since it uses the
598             # maintenance account to access the API. The maintenance
599             # account should be person_id 1 since it is created by the
600             # DB schema itself.
601             psql -U $PLC_DB_USER -c "UPDATE persons SET email='$PLC_API_MAINTENANCE_USER' WHERE person_id=1" $PLC_DB_NAME
602
603             # Bootstrap the DB
604             api-config
605             check
606             ;;
607     esac
608 }
609
610 config_cron ()
611 {
612     case "$1" in
613         start)
614             if [ "$PLC_MAIL_ENABLED" = "1" ] ; then
615                 MAILTO=$PLC_MAIL_SUPPORT_ADDRESS
616             else
617                 MAILTO=
618             fi
619             cat >/etc/cron.d/plc.cron <<EOF
620 SHELL=/bin/bash
621 PATH=/sbin:/bin:/usr/sbin:/usr/bin
622 MAILTO=$MAILTO
623 HOME=/
624
625 # minute hour day-of-month month day-of-week user command
626 */5 * * * * root gen-slices-xml-05.py
627 */15 * * * * root gen-sites-xml.py
628 */15 * * * * root gen-static-content.py
629 EOF
630
631             # Run them once at startup
632             gen-slices-xml-05.py
633             check
634             gen-sites-xml.py
635             check
636             gen-static-content.py
637             check
638
639             service crond start
640             check
641             ;;
642
643         stop)
644             service crond stop
645             check
646             ;;
647     esac
648 }
649
650 config_bootcd ()
651 {
652     case "$1" in
653         start)
654             if [ "$PLC_BOOT_ENABLED" != "1" -a \
655                  "$PLC_WWW_ENABLED" != "1" ] ; then
656                 return 0
657             fi
658
659             # Customize the BootCD
660             pushd /var/www/html/download
661             /usr/share/bootcd/build.sh
662             check
663             popd
664             ;;
665     esac
666 }
667
668 config_bootmanager ()
669 {
670     case "$1" in
671         start)
672             if [ "$PLC_BOOT_ENABLED" != "1" -a \
673                  "$PLC_WWW_ENABLED" != "1" ] ; then
674                 return 0
675             fi
676
677             # Customize the Boot Manager
678             pushd /var/www/html/boot
679             /usr/share/bootmanager/build.sh
680             check
681             popd
682             ;;
683     esac
684 }
685
686 usage()
687 {
688     echo "Usage: $0 [OPTION]... [COMMAND]"
689     echo "      -v              Be verbose"
690     echo "      -h              This message"
691     echo
692     echo "Commands:"
693     echo "      start           Start all PLC subsystems"
694     echo "      stop            Stop all PLC subsystems"
695     echo "      reload          Regenerate configuration files"
696     echo "      restart         Restart all PLC subsystems"
697     exit 1
698 }
699
700 # Get options
701 while getopts "vh" opt ; do
702     case $opt in
703         v)
704             verbose=1
705             set -x
706             ;;
707         h|*)
708             usage
709             ;;
710     esac
711 done
712
713 shift $(($OPTIND - 1))
714 if [ -z "$1" ] ; then
715     usage
716 fi
717
718 exec 3>&1
719 exec 4>&2
720 if [ $verbose -eq 0 ] ; then
721     exec 1>>/var/log/boot.log
722     exec 2>>/var/log/boot.log
723 fi
724
725 # Generate and load configuration
726 reload
727 . /etc/planetlab/plc_config
728
729 RETVAL=0
730
731 start ()
732 {
733     for step in "${steps[@]}" ; do
734         echo -n $"PLC: Starting $step: " >&3
735         RETVAL=$ERRORS
736         config_$step start
737         if [ $RETVAL -eq $ERRORS ] ; then
738             success $"PLC: $step startup" >&3
739         else
740             failure $"PLC: $step startup" >&3
741         fi
742         echo >&3
743     done
744 }
745
746 stop ()
747 {
748     for i in $(seq 1 $nsteps) ; do
749         step=${steps[$(($nsteps - $i))]}
750         echo -n $"PLC: Shutting down $step: " >&3
751         RETVAL=$ERRORS
752         config_$step stop
753         if [ $RETVAL -eq $ERRORS ] ; then
754             success $"PLC: $step shutdown" >&3
755         else
756             failure $"PLC: $step shutdown" >&3
757         fi
758         echo >&3
759     done
760 }
761
762 case "$1" in
763     start|stop)
764         $1
765         ;;
766
767     restart)
768         stop
769         start
770         ;;
771
772     reload)
773         ;;
774
775     *)
776         usage >&3
777         ;;
778 esac
779
780 exit $RETVAL