43 for f in "/etc/$ME.conf" ~/.$ME; do test -r "$f" && source "$f"; done |
45 for f in "/etc/$ME.conf" ~/.$ME; do test -r "$f" && source "$f"; done |
44 |
46 |
45 |
47 |
46 die() { echo $ME: "$@" >&2; exit 1; } |
48 die() { echo $ME: "$@" >&2; exit 1; } |
47 warn() { echo $ME: "$@" >&2; } |
49 warn() { echo $ME: "$@" >&2; } |
48 silent() { "$@" &>/dev/null; } |
50 silently() { "$@" &>/dev/null; } |
49 |
51 |
|
52 debug() { echo "DEBUG: $@" >&2; } |
50 |
53 |
51 unique_ids() { |
54 unique_ids() { |
52 local dups=$(cat $BASE/*/conf/id 2>/dev/null | sort -n | uniq -c \ |
55 local dups=$(cat $BASE/*/conf/id 2>/dev/null | sort -n | uniq -c \ |
53 | egrep -v '^[[:space:]]+1 ' | tr -s ' ' | cut -f2 -d:) |
56 | egrep -v '^[[:space:]]+1 ' | tr -s ' ' | cut -f2 -d:) |
54 test "$dups" || return 0 |
57 test "$dups" || return 0 |
55 ERR="$dups" && return 1 |
58 ERR="$dups" && return 1 |
56 } |
59 } |
|
60 |
57 convert_dirs() { |
61 convert_dirs() { |
58 for dir in $BASE/*; do |
62 for dir in $BASE/*; do |
59 test -d $dir/kvm || test -d $dir/conf || continue |
63 test -d $dir/kvm || test -d $dir/conf || continue |
60 local old=$dir/kvm |
64 local old=$dir/kvm |
61 local new=$dir/conf |
65 local new=$dir/conf |
62 test -d $old && mv $old $new |
66 test -d $old && mv $old $new |
63 test -f $new/cmdline && mv $new/cmdline $new/options |
67 test -f $new/cmdline && mv $new/cmdline $new/options |
64 done |
68 done |
|
69 } |
|
70 |
|
71 monitor() { |
|
72 local port=$1; shift |
|
73 local command="$1"; shift |
|
74 |
|
75 # check, if the monitor is available, kill if somebody |
|
76 # else is using it |
|
77 local client=$(netstat -tn | egrep ":$port[[:space:]]+EST" | tr -s ' ' | cut -f4 -d' ') |
|
78 test "${client%:*}" = 127.0.0.1 && fuser -k ${client#*:}/tcp |
|
79 |
|
80 local pid0 pid1 |
|
81 ( |
|
82 local a=$tmp/a.fifo; mkfifo $a |
|
83 trap "rm -v $a" EXIT |
|
84 exec 10<>$a |
|
85 $NC localhost $port <&10 | { |
|
86 read || exit # banner |
|
87 while read -d' '; do test "$REPLY" = "(qemu)" && break; done |
|
88 echo "$command" >&10 |
|
89 while read -d' '; do test "$REPLY" = "(qemu)" && break; done |
|
90 } |
|
91 ) & pid0=$! |
|
92 ( sleep $TIMEOUT; kill $pid0 ) & pid1=$! |
|
93 wait $pid0 |
|
94 silently kill $pid0 $pid1 |
65 } |
95 } |
66 |
96 |
67 ### MAIN |
97 ### MAIN |
68 |
98 |
69 # sanity |
99 # sanity |
107 $@" |
137 $@" |
108 options=$(echo "" $options) # shorten it |
138 options=$(echo "" $options) # shorten it |
109 echo "$options" > $var/running_options |
139 echo "$options" > $var/running_options |
110 test -f $var/frozen && options="$options $(cat $var/frozen)" |
140 test -f $var/frozen && options="$options $(cat $var/frozen)" |
111 |
141 |
112 if silent fuser $var/pid; then |
142 if silently fuser $var/pid; then |
113 echo "running, pid: $pid, display :$id, monitor tcp:127.0.0.1:$port" |
143 echo "running, pid: $pid, display :$id, monitor tcp:127.0.0.1:$port" |
114 else |
144 else |
115 ( cd $BASE/$vm && $KVM $options -daemonize ) |
145 ( cd $BASE/$vm && $KVM $options -daemonize ) |
116 pid=$(cat $var/pid 2>/dev/null) |
146 pid=$(cat $var/pid 2>/dev/null) |
117 test "$pid" || { warn "serious problem ($vm), no pid" && continue; } |
147 test "$pid" || { warn "serious problem ($vm), no pid" && continue; } |
118 echo "started, pid: $pid, display :$id, monitor tcp:127.0.0.1:$port" |
148 echo "started, pid: $pid, display :$id, monitor tcp:127.0.0.1:$port" |
119 fi |
149 fi |
120 |
150 |
121 test "$DISPLAY" && test "$VNCVIEWER" && test -t \ |
151 test "$DISPLAY" && test "$VNCVIEWER" && test -t \ |
122 && ( silent exec $VNCVIEWER :$id </dev/null & ) |
152 && ( silently exec $VNCVIEWER :$id </dev/null & ) |
123 |
153 |
124 ;; |
154 ;; |
125 stop) |
155 stop) |
126 { |
156 { |
127 echo "stopping (powerdown) $vm" |
157 echo "stopping (powerdown) $vm" |
128 a=$tmp/a; b=$tmp/b; mkfifo $a $b |
158 monitor $port "system_powerdown" |
129 ( $NC localhost $port 0<>$a 1<>$b ) & pid0=$! |
159 silently fuser $var/pid && $0 quit $vm |
130 read <$b # we should not send anything before we got the first line |
|
131 echo -e 'system_powerdown\n' >$a |
|
132 ( cat <$b & sleep $TIMEOUT; silent kill $! $pid0 ) & pid1=$! |
|
133 wait $pid0 |
|
134 kill $pid1 2>/dev/null |
|
135 silent fuser $var/pid && $0 quit $vm |
|
136 } & |
160 } & |
137 ;; |
161 ;; |
138 quit) |
162 quit) |
139 { |
163 { |
140 echo "quit $vm" |
164 echo "quit $vm" |
141 a=$tmp/a; b=$tmp/b; mkfifo $a $b |
165 monitor $port "quit" |
142 ( $NC localhost $port 0<>$a 1<>$b ) & pid0=$! |
166 silently fuser $var/pid && $0 kill $vm |
143 read <$b |
|
144 echo -e 'quit\n' >$a |
|
145 ( cat <$b & sleep $TIMEOUT; silent kill $! $0 ) & pid1=$! |
|
146 wait $pid0 |
|
147 kill $pid1 2>/dev/null |
|
148 silent fuser $var/pid && $0 kill $vm |
|
149 } & |
167 } & |
150 ;; |
168 ;; |
151 kill) |
169 kill) |
152 echo "killing $vm" |
170 echo "killing $vm" |
153 kill $pid |
171 kill $pid |
154 ;; |
172 ;; |
155 freeze) echo "freezing $vm" |
173 freeze) |
156 fuser -k $port/tcp |
174 { |
157 echo -e "savevm HIBERNATE\nquit" | $NC localhost $port & |
175 echo "freezing $vm" |
158 echo "-loadvm HIBERNATE" >$var/frozen |
176 monitor $port "savevm HIBERNATED" |
159 ;; |
177 monitor $port "quit" |
160 #status) echo "status $vm: " |
178 echo "-loadvm HIBERNATED" >$var/frozen |
|
179 } & |
|
180 ;; |
161 qemu) |
181 qemu) |
162 echo "DO *NOT* USE \"quit\", use ^C for exiting!" |
182 echo "DO *NOT* USE \"quit\", use ^C for exiting!" |
163 $NC localhost $port |
183 $NC localhost $port |
164 ;; |
184 ;; |
165 |
185 |
166 list) |
186 list) |
167 echo "$vm:" $(silent fuser $var/pid \ |
187 echo "$vm:" $(silently fuser $var/pid \ |
168 && echo "running (pid: $pid)" \ |
188 && echo "running (pid: $pid)" \ |
169 || echo "not running") |
189 || echo "not running") |
170 ;; |
190 ;; |
171 |
191 |
172 *) die "unknown command \"$action\"" |
192 *) die "unknown command \"$action\"" |