Skip to content

Instantly share code, notes, and snippets.

@tarao
Created November 29, 2012 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tarao/4169176 to your computer and use it in GitHub Desktop.
Save tarao/4169176 to your computer and use it in GitHub Desktop.
Register start hook to libvirt
#!/bin/sh -e
# /etc/libvirt/hooks/qemu
guest="$1"
action="$2"
try=60
wait=1
lf='
'
app='virt-start-hook'
# find qemu-kvm user
passwd='/etc/passwd'
conf='/etc/libvirt/qemu.conf'
[ -f "$conf" ] && {
pat="s/^user\\s*=\\s*\"\\([^\"]\\+\\)\".*\$/\\1/p"
user=$(sed -n -e "$pat" "$conf")
}
[ -z "$user" ] && grep "^libvirt-qemu:" "$passwd" >/dev/null && {
user="libvirt-qemu" # debian default
}
# find home directory and locate config
home=$(grep "^$user:" "$passwd" | cut -f 6 -d :)
auth_command_dir="$home/$app"
auth_command_config="$auth_command_dir/config"
auth_command="$auth_command_dir/auth-command"
ssh_options='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
error() {
echo "$1" >&2
exit 1
}
reachable() {
ping -c 1 -W 1 "$1" >/dev/null && return 0
return 1
}
entries() {
file="$2"
[ -z "$file" ] && file="$auth_command_config"
grep "^Host\\s\\+$1/.*\$" "$file" | sed -e "s/^Host\\s\\+//g"
}
shell_escape() {
printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
}
auth_command() {
action="$1"; shift
args=''
for x in "$@"; do
args="$args $(shell_escape "$x")"
done
eval "\"$auth_command\" $action $ssh_options$args"
}
start() {
[ -x "$auth_command" ] || error "Could not run \"$auth_command\""
auth_command run -c "$auth_command_config" "$1"
}
start_entries() {
for x in $entries; do
start "$x"
done
}
case "$action" in
start)
# find config and entries
test -f "$auth_command_config" && entries=$(entries "$guest")
( [ -n "$entries" ] && {
# wait for up
running=0
for t in `seq $try`; do
reachable "$guest" && {
running=1
break
}
done
[ "$running" = 0 ] && {
error "Request timed out: could not reach to $guest"
}
# run
IFS="$lf" start_entries
} || true ) </dev/null 2>/dev/null 1>&2 & # async
;;
esac
# run the original hook
dir=$(dirname "$0")
base=$(basename "$0")
original="$dir/$base.original"
[ -x "$original" ] && exec "$original" "$@" || true
exit
#!/bin/sh -e
base=`basename "$0"`
app='virt-start-hook'
lf='
'
hook='/etc/libvirt/hooks/qemu'
hook_url='http://raw.github.com/gist/4169176/qemu.sh'
auth_command_url='http://raw.github.com/gist/4108520/auth-command.sh'
auth_command_user='root'
ssh_options='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
# find qemu-kvm user
passwd='/etc/passwd'
conf='/etc/libvirt/qemu.conf'
[ -f "$conf" ] && {
pat="s/^user\\s*=\\s*\"\\([^\"]\\+\\)\".*\$/\\1/p"
user=$(sed -n -e "$pat" "$conf")
}
[ -z "$user" ] && grep "^libvirt-qemu:" "$passwd" >/dev/null && {
user="libvirt-qemu" # debian default
}
group=$(id -gn "$user")
# find home directory and locate config
home=$(grep "^$user:" "$passwd" | cut -f 6 -d :)
auth_command_dir="$home/$app"
auth_command_config="$auth_command_dir/config"
auth_command="$auth_command_dir/auth-command"
test=0
verbose=0
help() {
cat <<EOF
Usage: $base init OPTIONS
$base add OPTIONS <host> <guest>/<feature> <command> <arg>...
Options:
-v Verbose messages.
-t Test mode; print what will be done instead of actually doing it.
Arguments:
<host> The virtualization guest.
<guest> The virtualization guest registered name.
<feature> The name of feature.
<name> Name of the command and key file.
<command> Command to run.
EOF
exit $1
}
testing() {
[ $test != 0 ] && return 0
}
shell_escape() {
printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
}
run() {
cmd=$(shell_escape "$1"); shift
for x in "$@"; do
[ "x$x" = 'x|' ] && {
cmd="$cmd |"
} || {
cmd="$cmd $(shell_escape "$x")"
}
done
testing && echo "$cmd" || eval "$cmd"
}
info() {
[ $verbose != 0 ] && echo $1 >&2
return 0
}
make_directory() {
info "Make \"$auth_command_dir\""
[ -d "$auth_command_dir" ] || run mkdir -p "$auth_command_dir"
run chown "$user":"$group" "$auth_command_dir"
run chmod go-rwx "$auth_command_dir"
}
download_auth_command() {
run wget -O "$1/auth-command" "$auth_command_url"
run chmod a+x "$1/auth-command"
}
require_auth_command() {
[ -x "$auth_command" ] && return 0
make_directory
download_auth_command "$auth_command_dir"
# initialize
info "Initialize \"$auth_command_config\""
[ -f "$auth_command_config" ] || {
run sudo -u "$user" "$auth_command" init -l "$auth_command_user" \
-c "$auth_command_config"
}
return 0
}
auth_command() {
require_auth_command
auth_command_options="-c $(shell_escape "$auth_command_config")"
[ $verbose != 0 ] && auth_command_options="-v $auth_command_options"
action="$1"; shift
args=''
for x in "$@"; do
args="$args $(shell_escape "$x")"
done
run="run sudo -u \"$user\""
eval "$run $auth_command $action $auth_command_options $ssh_options$args"
}
install_hook() {
( [ -x "$hook" ] && grep "app='virt-start-hook'" "$hook" >/dev/null ) || {
[ -f "$hook" ] && {
[ -f "$hook.original" ] && {
run mv "$hook.original" "$hook.original.bak"
}
run mv "$hook" "$hook.original"
}
info "Download \"$hook_url\""
run wget -O "$hook" "$hook_url"
run chown "$user:$group" "$hook"
run chmod a+x "$hook"
}
}
action="$1"
[ -z "$action" ] && help
shift
parsing=1
while [ $parsing = 1 ] && [ -n "$1" ]; do
case "$1" in
-v) shift
verbose=1
;;
-t)
shift
test=1
;;
*) parsing=0
;;
esac
done
case "$action" in
init)
install_hook
require_auth_command
;;
add)
install_hook
auth_command add "$@"
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment