merge with 0.30.213
[util-vserver.git] / scripts / vshelper
1 #! /usr/lib/util-vserver/sigexec /bin/bash
2
3 # Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 #  
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
8 #  
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #  
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 ## Usage: vshelper <xid> <action> <args>
19
20 : ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
21 test -e "$UTIL_VSERVER_VARS" || {
22     echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2
23     exit 1
24 }
25 . "$UTIL_VSERVER_VARS"
26 . "$_LIB_FUNCTIONS"
27
28 function showHelp
29 {
30     echo $"\
31 Usage: vshelper <xid> <event> <args>*
32
33 Report bugs to <$PACKAGE_BUGREPORT>."
34     exit 0
35 }
36
37 function showVersion
38 {
39     echo $"\
40 vshelper $PACKAGE_VERSION -- userspace reboot helper
41 This program is part of $PACKAGE_STRING
42
43 Copyright (C) 2004 Enrico Scholz
44 This program is free software; you may redistribute it under the terms of
45 the GNU General Public License.  This program has absolutely no warranty."
46     exit 0
47 }
48
49 function doInternalMethod
50 {
51     local method=$1
52     case "$method" in
53         (restart)
54             case "$ACTION" in
55                 (restart)
56                     logging $"Restarting vserver '$VSERVER'"
57
58                     local sync_dir
59                     vshelper.initStopSync sync_dir
60
61                     spawn $_VSERVER --defaulttty "$VSERVER" restart &
62
63                     disown %%
64                     vshelper.waitForStopSync "$sync_dir"
65                     ;;
66                 (halt|poweroff)
67                     logging $"Stopping vserver '$VSERVER'"
68
69                     local sync_dir
70                     vshelper.initStopSync sync_dir
71
72                     spawn $_VSERVER --defaulttty "$VSERVER" stop &
73
74                     disown %%
75                     vshelper.waitForStopSync "$sync_dir"
76                     spawn killContext "$XID"
77                     ;;
78                 (swsusp)
79                     ## TODO: any senseful action here? Perhaps shutdown scheduler for it?
80                     exit 0
81                     ;;
82                 (restart2)      ;;
83                 (shutdown)
84                     logging $"Cleaning up after vserver '$VSERVER'"
85                     spawn $_VSERVER --defaulttty "$VSERVER" stop
86                     ;;
87                 (*)
88                     warning $"Unknown action '$ACTION' for vserver '$VSERVER'"
89                     exit 1
90             esac
91             ;;
92
93         (async)
94             spawn killContext "$XID"
95             ;;
96             
97         (sync)
98             local f=${METHOD_ARGS[0]}
99             test -n "$f" ||
100                 panic $"Insufficent arguments for method '$method' and vserver '$VSERVER'"
101
102             test -p "$f" ||
103                 panic $"File '$f' which is required for synchronisation of vserver '$VSERVER' is not a pipe"
104
105             spawn killContext "$XID"
106             echo "$ACTION" >"$f"
107             ;;
108
109         (*)
110             local script
111             findObject -x script "$__CONFDIR"/.defaults/apps/vshelper-methods/"$method" "$__PKGLIBDIR"/vshelper-methods/"$method" ''
112             
113             test -n '$script' || {
114                 warning $"No handler for internal method '$method' found"
115                 exit 1
116             }
117
118             export VSERVER
119             execute "$script" "${ARGS[@]}"
120     esac
121 }
122     
123 function doDefaultMethod
124 {
125     local handler
126
127     vshelper.getHandler handler "$VSERVER" "$ACTION" || {
128         warning $"No handler configured for action '$ACTION' on vserver '$VSERVER'"
129         exit 1
130     }
131
132     case "$handler" in
133         (/*)    execute "$handler" "${ARGS[@]}";;
134         (:*)    doInternalMethod "${handler##:}" "$@";;
135     esac
136 }
137
138 #===========
139
140 test "$1" != '--version' || showVersion
141 test "$1" != '--help'    || showHelp
142
143 if ! tty -s; then
144     findObject -e _VS_LOGFILE "$__CONFDIR"/.defaults/apps/vshelper/logfile /dev/null
145     findObject -e _VS_ERRFILE "$__CONFDIR"/.defaults/apps/vshelper/logfile /dev/null
146
147     exec   </dev/null
148     exec  >>$_VS_LOGFILE
149     exec 2>>$_VS_ERRFILE
150 fi
151
152 logging "$(date): vshelper $*"
153     
154 test "$#" -ge 2 ||
155     panic $"vshelper called with missing arguments; try '--help' for more information"
156
157     
158 vshelper.isEnabled || exit 0
159 ! vshelper.isDebug || set -x
160     
161 set -eu
162
163 if $_VSERVER_INFO - FEATURE vshelper0; then
164     declare -r XID=$1
165     declare -r ACTION=$2
166 elif $_VSERVER_INFO - FEATURE vshelper; then
167     declare -r ACTION=$1
168     declare -r XID=$2
169 else
170     panic $"vshelper functionality not supported by kernel"
171 fi
172
173 findObject -x delegate "$__CONFDIR"/.defaults/apps/vshelper-delegate/"$ACTION" "$__PKGLIBDIR"/vshelper-delegate/"$ACTION" ''
174 test -e "$delegate" && exec -a "$ACTION" "$delegate" "$@"
175
176 this_xid=$($_VSERVER_INFO - XID)
177 pxid=
178 responsible_xid=$XID
179 while true; do
180     pxid=$($_VSERVER_INFO "$responsible_xid" PXID) || break
181     test "$pxid" -ne "$this_xid"                   || break
182     responsible_xid=$pxid
183 done
184
185 vserver_id=$($_VSERVER_INFO "$responsible_xid" ID) || test "$ACTION" = "shutdown" ||
186     panic $"No responsible vserver found for xid '$responsible_xid' ($XID); aborting..."
187     
188 test "$XID" = "$responsible_xid" || {
189     logging "Giving 'vshelper' task for '$XID' to parent vserver '$vserver_id' ($responsible_xid)"
190     execute $_VSERVER "$vserver_id" exec $_VSHELPER "$@"
191 }
192
193 #===========
194
195 ARGS=( "$@" )
196
197 declare -a state
198 getFileArray state "$__VSHELPERSTATEDIR/$XID" && test ${#state[@]} -ge 2 || {
199     logging "'vshelper' not configured for xid '$XID'"
200     exit 0
201 }
202
203 declare -r VSERVER=${state[0]}
204
205 cfg_xid=$($_VSERVER_INFO "${state[0]}" CONTEXT false) ||
206     panic $"Configured vserver '$VSERVER' does not seem to run; aborting..."
207
208 test "$cfg_xid" = "$XID" ||
209     panic $"Configured ($cfg_xid) and actual ($XID) xid for vserver '$VSERVER' are mismatching; aborting..."
210
211 cur_xid=$($_VSERVER_INFO "$VSERVER" CONTEXT false) ||
212     panic $"Vserver '$VSERVER' with '$XID' does not seem to run; strange..."
213
214 test "$cur_xid" = "$XID" ||
215     panic $"Expected ($XID) and actual ($cur_xid) xid for vserver '$VSERVER' are mismatching; strange..."
216
217
218 method=${state[1]}
219 if test "${#state[@]}" -gt 2; then
220     unset state[0] state[1]
221     declare -ra METHOD_ARGS=( "${state[@]}" )
222 else
223     declare -ra METHOD_ARGS=()
224 fi
225
226 case "$method" in
227     (default)           doDefaultMethod "$@";;
228     (sync|async)        doInternalMethod "$method" "$@";;
229     (*)                 panic $"Unknown method '$method' used by vserver '$VSERVER'";;
230 esac