diff options
| author | Marc Vertes <mvertes@free.fr> | 2021-03-17 16:17:42 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2021-03-17 16:17:42 +0100 |
| commit | 556754fb516ff84965a510d0205f3c1d6cf64505 (patch) | |
| tree | 9f3022000e825f91dbafd5743346ebdf03009b0a /bin/vm | |
| parent | 5c75618ff26969654a0572ae00b01f77d1898a71 (diff) | |
improved vm
Diffstat (limited to 'bin/vm')
| -rwxr-xr-x | bin/vm | 133 |
1 files changed, 88 insertions, 45 deletions
@@ -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 "$@" |
