On 02/20/2012 06:32 AM, Peter Krempa wrote:
This patch modifies the libvirt-guests init script to enable
parallel
shiutdown on guest machines and gets rid of error messages if the client
s/shiutdown/shutdown/
is unable connect to the URI specified in the config file.
---
Simultaneous shutdown of machines may speed up the shutdown process as the shutdown
sequence
of guests often consists of timeouts and storage un-intensive tasks. Simultaneous resume
of machines was already supported, although not documented well enough.
This patch also checks if connection to the URI can be done, and prints a error
message if it's not the case. This get's rid of unrelevant and repeated error
messages
s/unrelevant/irrelevant/
(Stupid English, for being inconsistent on whether un- or ir- negates a
word :)
if the URI is unreachable.
The last improvement is while using managed-save. Transient domains are excluded
from the save sequence to get rid of error messages and a list of domains that are left
behind is printed.
Please tell me your suggestions how to improve this, as I'm not a bash "native
speaker".
Actually, we want this to be stricter than bash, since people are using
libvirt-guests on debian-based systems where /bin/sh is dash. But no
fears - I'm fluent in shell.
+test_connect()
I find it helpful to document ALL shell functions; it makes maintenance
easier down the road (it doesn't help that we haven't been doing this in
the rest of the file). Here, it looks like you are doing:
# test_connect URI
# check if URI is reachable
test_connect() {
+{
+ uri=$1
+
+ run_virsh "$uri" connect 2>/dev/null
Any reason for the two spaces?
+ if [ $? -ne 0 ]; then
+ eval_gettext "Can't connect to \$uri. Skipping."
+ echo
+ return 1
+ fi
+}
+
+# "persistent" argument options:
+# yes: list only persistent guests
+# no: list only transient guests
+# all: list both persistent and transient guests
list_guests() {
Here, I would use:
# list_guests URI PERSISTENT
prior to the documentation of valid PERSISTENT values.
uri=$1
+ persistent=$2
list=$(run_virsh_c "$uri" list)
if [ $? -ne 0 ]; then
@@ -89,12 +106,19 @@ list_guests() {
uuids=
for id in $(echo "$list" | awk 'NR > 2 {print $1}'); do
- uuid=$(run_virsh_c "$uri" dominfo "$id" | awk
'/^UUID:/{print $2}')
<aside>
Remind me again why we are doing an inefficient shell loop? In fact,
why were we using 'dominfo | awk' to convert id to uuid? It's faster to
use 'run_virsh_c "$uri" virsh domuuid $id" to get the same
information.
Taking it one step further, I'd rather see us enhance 'virsh list' to
give us what we want up front. That is, I think it would be nice to
have 'virsh list { [--table] | --uuid | --name | --id } ...', where
--table is default (for back-compat), but listing --uuid, --name, or
--id drops the header line, and lists just one identifier per line
rather than a full table. Also, I'd also like to see 'virsh list {
[--running] | --all | --inactive | --persistent | --transient } ...';
that is, we ought to have virsh list fine-tune which domains it lists,
by adding new options such as --persistent and --transient.
By improving virsh, we could skip out on the awk loop altogether, and
have the initial virsh list give us what we want in the first place.
</aside>
- if [ -z "$uuid" ]; then
+ dominfo=$(run_virsh_c "$uri" dominfo "$id")
+ uuid=$(echo "$dominfo" | awk '/^UUID:/{print $2}')
+ dompersist=$(echo "$dominfo" | awk '/^Persistent:/{print
$2}')
This sets $dompersist to yes or no,...
+
+ if [ -z "$uuid" ] || [ -z "$dompersist" ]; then
RETVAL=1
return 1
fi
- uuids="$uuids $uuid"
+
+ if [ "$persistent" == "$dompersist" ] ||
For portability to dash, you must use '=', not '==', inside [].
+ [ "$persistent" == "all" ]; then
+ uuids="$uuids $uuid"
...if persistent is 'all', then you wasted an awk call above for a
result you don't care about, since you plan on using the uuid anyway.
Again, more reason to have virsh list give us what we want in the first
place.
+shutdown_guest_async()
+{
+ uri=$1
+ guest=$2
+
+ name=$(guest_name "$uri" "$guest")
+ label=$(eval_gettext "Starting shutdown on guest: \$name")
+ echo $label
Missing quotes around $label. Probably simpler to just:
name=$(guest_name "$uri" "$guest")
eval_gettext "Starting shutdown on guest: \$name"
echo
+ retval run_virsh "$uri" shutdown "$guest"
>/dev/null || return
No need for the ||return - since this is the last statement in the
function, you will return anyway, with the same status.
+}
+
+set_add()
+{
+ item=$1
+ items=$2
+
+ echo "$items $item"
Should you be checking for duplicates before adding into a set? I'm not
sure without reviewing further to see how this is used. Also, this
particular usage requires that the user capture the output of the shell
function using $(), which wastes a subshell; there are tricks for
passing the name of a variable which holds a set, where you can then
modify the variable in place with fewer forks, but I don't think we're
at the point where optimizing a few forks will help matters.
+}
+
+set_remove()
+{
+ item=$1
+ items=$2
+
+ newitems=
+ for nit in $items; do
+ if [ "$nit" != "$domain" ]; then
Where did "$domain" come from? Don't you instead mean to be comparing
against "$item"?
+ newitems="$newitems $nit"
The resulting $newitems will always have a leading space, even if $items
on entry did not. Is that intentional?
+ fi
+ done
+
+ echo "$newitems"
+}
+
+set_count()
+{
+ items=$1
+
+ count="0"
+ for item in $items; do
+ count=$((count+1))
It's slightly more portable to do $(($count+1)). But even that is slow;
why not let the shell do it for you:
set_count() {
set -- $1
echo $#
}
+ done
+
+ echo $count
+}
+
+set_head()
+{
+ items=$1
+
+ for item in $items; do
+ echo $item
+ return 0
+ done
+}
I sure hope that the sets you are using have no whitespace or glob
characters (that is, a set of domain ids or uuids is safe, a set of
domain names or of URIs is not).
+
+remove_shutdown_domains()
+{
+ uri=$1
+ domains=$2
+
+ newlist=
+ for dom in $domains; do
+ guest_is_on "$uri" "$dom" 2>&1 > /dev/null ||
return
Do you really want to break out of the entire for loop on the first
guest where you encounter failure? Also, this redirection looks fishy -
it says 'make the error output of guest_is_on go to my stdout, and
discard the normal output of guest_is_on'. Did you mean '>/dev/null
2>&1' which says to discard both output and error messages from guest_is_on?
+ if "$guest_running"; then
+ newlist="$newlist $dom"
+ fi
+ done
+
+ echo "$newlist"
+}
I ran out of time to finish my review today, but hope this gives you
some things to think about.
--
Eric Blake eblake(a)redhat.com +1-919-301-3266
Libvirt virtualization library
http://libvirt.org