aboutsummaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rwxr-xr-xbin/vm88
1 files changed, 68 insertions, 20 deletions
diff --git a/bin/vm b/bin/vm
index 12fd6c8..42b673b 100755
--- a/bin/vm
+++ b/bin/vm
@@ -5,7 +5,7 @@ set -eu
usage() {
cat <<-'EOF'
Usage:
- vm [-G] [-n] [-S] [-v] ACTION [OS [-- QEMU_OPTIONS...]]
+ vm [-G] [-i IMAGE ] [-n] [-p PORTMAP ] [-S] [-v] ACTION [OS [-- QEMU_OPTIONS...]]
vm -h
EOF
}
@@ -16,8 +16,12 @@ help() {
Options:
-G use graphics
+ -i IMAGE provide a custom QCoW2 image file
+ -m MEMORY memory (default: 1G)
-n dry-run: don't execute any code, assumes -v
-S don't write to VM image (snapshot on)
+ -p PORTMAP map the host port $HOSTP to the guest port
+ $GUESTP using the $HOSTP:$GUESTP syntax
-v verbose mode
-h, --help show this message
@@ -51,9 +55,10 @@ help() {
Examples:
- Start the VM for Alpine in verbose mode:
+ Start the VM for Alpine in verbose mode, with guest port 8000
+ becoming available to the host via port 5555:
- $ vm -v up alpine
+ $ vm -v -p 5555:8000 up alpine
Stop the VM for Slackware, which was already down:
@@ -93,19 +98,31 @@ for flag in "$@"; do
esac
done
+IMAGE=''
DRY_RUN=false
GRAPHICS=false
+MEMORY=1G
+PORTMAPS=''
SNAPSHOT=false
VERBOSE=false
-while getopts 'GnSvh' flag; do
+while getopts 'Gi:m:np:Svh' flag; do
case "$flag" in
G)
GRAPHICS=true
;;
+ i)
+ IMAGE="$OPTARG"
+ ;;
+ m)
+ MEMORY="$OPTARG"
+ ;;
n)
DRY_RUN=true
VERBOSE=true
;;
+ p)
+ PORTMAPS="$PORTMAPS $OPTARG"
+ ;;
S)
SNAPSHOT=true
;;
@@ -152,12 +169,32 @@ guess_name() {
printf '%s\n' "$(basename "$IMAGES" .qcow2)"
}
+guess_arch() {
+ NAME="$(echo "$1" | cut -d- -f2)"
+ case "$NAME" in
+ amd64)
+ printf 'x86_64'
+ ;;
+ *)
+ printf '%s' "$NAME"
+ ;;
+ esac
+}
+
+hostfwd() {
+ for m in "$@"; do
+ HOST="$( echo "$m" | cut -d: -f1)"
+ GUEST="$(echo "$m" | cut -d: -f2)"
+ printf ',hostfwd=tcp::%s-:%s' "$HOST" "$GUEST"
+ done
+}
+
write_ssh_config() {
- for port in "$RUNDIR"/*.port; do
+ for port in "$RUNDIR"/*.ssh; do
if [ ! -e "$port" ]; then
break
fi
- NAME="$(basename "$port" .port)"
+ NAME="$(basename "$port" .ssh)"
PORT="$(cat "$port")"
cat <<-EOF
Host $NAME
@@ -196,12 +233,14 @@ case "$ACTION" in
break
fi
NAME="$(basename "$img" .qcow2)"
+ PORTS=''
if [ -e "$RUNDIR/$NAME.pid" ]; then
STATUS=up
+ PORTS="$(sed 's/ /,/g' "$RUNDIR/$NAME.ports")"
else
STATUS=down
fi
- printf '%s\t%s\n' "$NAME" "$STATUS"
+ printf '%s\t%s\t%s\n' "$NAME" "$STATUS" "$PORTS"
done
;;
up)
@@ -212,8 +251,10 @@ case "$ACTION" in
fi
OS="$(guess_name "$OS")"
+ ARCH="$(guess_arch "$OS")"
PID_F="$RUNDIR/$OS.pid"
- PORT_F="$RUNDIR/$OS.port"
+ SSH_PORT_F="$RUNDIR/$OS.ssh"
+ PORTMAPS_F="$RUNDIR/$OS.ports"
if [ -e "$PID_F" ]; then
printf 'The VM for "%s" is already running with PID %s.\n' \
@@ -221,15 +262,20 @@ case "$ACTION" in
exit 1
fi
- PORT="$(free-port)"
- QCOW="$QCOW_DIR"/"$OS".qcow2
+ if [ -z "$IMAGE" ]; then
+ IMAGE="$QCOW_DIR"/"$OS".qcow2
+ fi
+
+ SSH_PORT="$(free-port)"
+ PORTMAPS="$SSH_PORT:22${PORTMAPS}"
+ HOSTFWD="$(hostfwd $PORTMAPS)"
# shellcheck disable=2086
- set -- qemu-system-x86_64 \
- -m 1G \
- -nic user,model=virtio,hostfwd=tcp::"$PORT"-:22 \
- -drive file="$QCOW",media=disk,if=virtio \
- -enable-kvm \
+ set -- qemu-system-"$ARCH" \
+ -m "$MEMORY" \
+ -nic user,model=virtio"$HOSTFWD" \
+ -drive file="$IMAGE",media=disk,if=virtio \
+ -enable-kvm \
$FLAGS "$@"
if [ "$DRY_RUN" = true ]; then
@@ -244,8 +290,9 @@ case "$ACTION" in
"$@" 1>>"$LOGS" 2>&1 &
PID=$!
set +x
- printf '%s' "$PID" > "$PID_F"
- printf '%s' "$PORT" > "$PORT_F"
+ printf '%s' "$PID" > "$PID_F"
+ printf '%s' "$SSH_PORT" > "$SSH_PORT_F"
+ printf '%s' "$PORTMAPS" > "$PORTMAPS_F"
write_ssh_config
;;
@@ -258,7 +305,8 @@ case "$ACTION" in
OS="$(guess_name "$OS")"
PID_F="$RUNDIR/$OS.pid"
- PORT_F="$RUNDIR/$OS.port"
+ SSH_PORT_F="$RUNDIR/$OS.ssh"
+ PORTMAPS_F="$RUNDIR/$OS.port"
if [ ! -e "$PID_F" ]; then
printf 'The VM for "%s" is not running, already.\n' "$OS" >&2
@@ -268,10 +316,10 @@ case "$ACTION" in
PID="$(cat "$PID_F")"
if [ "$DRY_RUN" = true ]; then
- echo rm -f "$PID_F" "$PORT_F"
+ echo rm -f "$PID_F" "$SSH_PORT_F" "$PORTMAPS_F"
echo kill "$PID"
else
- rm -f "$PID_F" "$PORT_F"
+ rm -f "$PID_F" "$SSH_PORT_F" "$PORTMAPS_F"
kill "$PID"
fi