diff options
author | EuAndreh <eu@euandre.org> | 2022-12-03 10:10:14 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2022-12-03 10:10:14 -0300 |
commit | 471f2ff8a665b6aaa0aa9f6282aee04f1709e89d (patch) | |
tree | 06b37684f0841a1d9f5cf12e928417173e53751a | |
parent | bin/vm: Bail out when given a bad prefix (diff) | |
download | dotfiles-471f2ff8a665b6aaa0aa9f6282aee04f1709e89d.tar.gz dotfiles-471f2ff8a665b6aaa0aa9f6282aee04f1709e89d.tar.xz |
bin/vm: Support portmapping, custom memory and partial custom image
-rwxr-xr-x | bin/vm | 88 |
1 files changed, 68 insertions, 20 deletions
@@ -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 |