summaryrefslogtreecommitdiff
path: root/bin/vm
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2021-03-17 16:17:42 +0100
committerMarc Vertes <mvertes@free.fr>2021-03-17 16:17:42 +0100
commit556754fb516ff84965a510d0205f3c1d6cf64505 (patch)
tree9f3022000e825f91dbafd5743346ebdf03009b0a /bin/vm
parent5c75618ff26969654a0572ae00b01f77d1898a71 (diff)
improved vm
Diffstat (limited to 'bin/vm')
-rwxr-xr-xbin/vm133
1 files changed, 88 insertions, 45 deletions
diff --git a/bin/vm b/bin/vm
index 5a8ea8d..e8f7684 100755
--- a/bin/vm
+++ b/bin/vm
@@ -1,32 +1,50 @@
#!/bin/sh
-# vm is a tool to manage virtual machines.
+# vm is a tool to manage and operate virtual machines.
vm_version='vm-0.1'
+
+# TODO:
+# - DONE: fetch, build and install vftool in .vm/vftool
+# - setup a config file per VM
+# - creation of hdd image
+# - script install from CDROM iso:
+# - setup system, including static IP address
+# - setup user account from host
+# - setup ssh from host
+# - time synchronization from host
+#
+
unset CDPATH
export LC_ALL=C IFS='
'
add() {
usage 'add name' 'Add a new VM' && return
- [ -d "$idir/$1" ] && die "vm $1 already exists in $idir/$1"
+ [ -d "$dir/$1" ] && die "vm $1 already exists in $dir/$1"
init_alpine || die "could not init alpine iso"
- mkdir -p "$idir/$1" && cd "$idir/$1" || die "add $1 failed"
+ mkdir -p "$dir/$1" && cd "$dir/$1" || die "add $1 failed"
pwd
}
+console() {
+ usage 'console name' 'Attach a console to a VM' && return
+ [ "$1" ] || die 'console: name is missing'
+ cd "$dir/$1" || die 'console $1 failed'
+ [ -f vftool.pid ] || die "vm $1 is not active"
+ screen -r "$1"
+}
+
del() {
usage 'del name' 'Delete a VM' && return
echo 'not implemented yet'
}
-die() { echo "$0: fatal: $@" >&2; exit 1; }
+die() { [ "$1" ] && echo "$@" >&2; exit 1; }
help() {
usage 'help' 'Print this help text' && return
- echo "$vm_version
-Manage virtual machines
-Usage: vm command [options] [args]"
+ echo "$vm_version\nManage virtual machines\nUsage: vm command [options] [args]"
Opth=1; for c in $Cmdlist; do $c; done
}
@@ -35,16 +53,9 @@ info() {
echo 'not implemented yet'
}
-init() {
- :
-}
-
-init_alpine() {
- mkdir -p "$sdir/alpine" && cd "$sdir/alpine" || die "init alpine failed"
- [ -f Makefile ] || cat << \EOT > Makefile
-# Do no edit. This file is generated by vm.
-# Install a run a native AlpineLinux VM in Apple silicon MacOS
+# CAUTION: be careful to preserve tabs in the following Makefile template string.
+alpine_makefile='# Generated by "vm". DO NOT EDIT.
# Check https://alpinelinux.org/downloads for possible upgrades
iso_url = https://dl-cdn.alpinelinux.org/alpine/v3.13/releases/aarch64/alpine-virt-3.13.2-aarch64.iso
iso = $(notdir $(iso_url))
@@ -52,9 +63,6 @@ isoinfo ?= /opt/homebrew/bin/isoinfo
all: initrd vmlinux
-runiso: initrd vmlinux $(iso)
- vftool -k vmlinux -i initrd -d hdd.img -c $(iso)
-
initrd: $(iso) $(isoinfo)
isoinfo -i $(iso) -J -x /boot/initramfs-virt > $@
@@ -63,36 +71,79 @@ vmlinux: $(iso) $(isoinfo)
$(iso):
curl -LO $(iso_url) || { rm -f $@; false; }
+ ln -sf $(iso) iso
$(isoinfo):
brew install cdrtools
-EOT
+'
+init_alpine() {
+ mkdir -p "$dir/alpine-iso" && cd "$dir/alpine-iso" || die 'init alpine failed'
+ [ -f 'Makefile' ] || echo "$alpine_makefile" > Makefile
make -s all
}
+init_vftool() {
+ [ -x "$dir/vftool" ] && return
+ cd '/tmp' &&
+ git clone --depth=1 'https://github.com/evansm7/vftool' &&
+ cd 'vftool' &&
+ make &&
+ cp 'build/vftool' "$dir/vftool"
+ rm -rf '/tmp/vftool'
+}
+
+log() {
+ usage 'log name' 'print logs of a VM' && return
+ [ "$1" ] || die "log failed: name missing"
+ cd "$dir/$1" || die "log $1 failed"
+ cat vftool.log.old vftool.log 2>/dev/null
+}
+
ls() {
usage 'ls' 'list VMs' && return
- [ -d "$idir" ] && cd "$idir" || return
- for i in *; do
- echo "$i"
+ [ -d "$dir" ] && cd "$dir" || return
+ for i in */; do
+ i=${i%/}
+ [ -f "$i/vftool.pid" ] && state=active || state=stopped
+ printf "%-20s %s\n" "$i" "$state"
done
}
-runiso() {
- usage 'runiso [isoname]' 'run a cdrom iso' && return
- init_alpine
- make runiso
-}
-
start() {
- usage 'start name' 'Start a VM' && return
- echo 'not implemented yet'
+ usage 'start [-a][-c vm] name' 'Start a VM' && return
+ while getopts :ac: opt; do
+ case $opt in
+ (a) attach=1 ;;
+ (c) from=$OPTARG ;;
+ (*) Opth=1 start; exit;;
+ esac
+ done
+ shift $((OPTIND - 1))
+
+ [ "$1" ] || die "start failed: name missing"
+ init_vftool
+ cd "$dir/$1" || die "start $1 failed"
+ [ -f vftool.pid ] && die "Error: process $(cat vftool.pid) is active or $PWD/vftool.pid should be removed"
+ start_vm &
}
+start_vm() (
+ trap 'rm -f vftool.pid' EXIT
+ [ -f vftool.log ] && cat vftool.log >> vftool.log.old
+ "$dir/vftool" -k vmlinux -i initrd -c iso >vftool.log 2>&1 & sleep 1
+ exec 1>>vftool.log 2>&1
+ echo "$!" >vftool.pid
+ screen -S "${PWD##*/}" -d -m "$(grep -om 1 '\/dev\/tty.*' vftool.log)"
+ wait
+)
+
stop() {
usage 'stop name' 'Stop a VM' && return
- echo 'not implemented yet'
+ [ "$1" ] || die 'stop: name missing'
+ cd "$dir/$1" || die 'stop $1 failed'
+ [ -f vftool.pid ] || die "stop: vm $1 is not active"
+ kill $(cat vftool.pid)
}
usage() { [ "$Opth" ] && printf " %-34s %s\n" "$1" "$2"; }
@@ -103,21 +154,13 @@ version() {
}
# Main starts here.
-pdir="$HOME/.vm"
-sdir="$pdir/iso"
-edir="$pdir/engine"
-idir="$pdir/img"
-
-engines="vftool" # Todo: add qemu (when supported on m1)
-isos="alpine" # Todo: add freebsd, openbsd, archlinux, debian, ubuntu, macOS, win10, etc...
-
-Cmdlist='add del info help ls runiso start stop version'
+dir="$HOME/.vm"
+Cmdlist='add console del info help ls log start stop version'
[ "$1" ] && C=$1 && shift 1 || { help; exit 1; }
-for c in $Cmdlist
-do
+for c in $Cmdlist; do
case $c in
- ($C) cmd=$c; break;;
- ($C*) [ "$cmd" ] && die "ambiguous command $C" || cmd=$c;;
+ ($C) cmd=$c; break ;;
+ ($C*) [ "$cmd" ] && die "ambiguous command $C" || cmd=$c ;;
esac
done
[ "$cmd" ] || { help; exit 1; } && $cmd "$@"