summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rwxr-xr-xbin/byo4
-rwxr-xr-xbin/gauth7
-rwxr-xr-xbin/hdmi8
-rwxr-xr-xbin/vm431
-rwxr-xr-xbin/xt1
5 files changed, 212 insertions, 239 deletions
diff --git a/bin/byo b/bin/byo
index bc09fb8..93bb7f0 100755
--- a/bin/byo
+++ b/bin/byo
@@ -26,8 +26,8 @@ yoda_uuid='8c463221-6bb7-414e-9060-c9570bb3a6bb'
dest=/mnt/backup/$(hostname)
[ -b /dev/mapper/yoda ] && noclose=1 || cryptsetup open "$dev" yoda
findmnt /dev/mapper/yoda /mnt >/dev/null && noumount=1 || mount /dev/mapper/yoda /mnt
-time backup -v -d "$dest"
-[ ! "$optC" ] || backup -v -d "$dest" clean
+time backup -v "$dest"
+# [ ! "$optC" ] || backup -v -d "$dest" clean
[ ! "$optd" ] || time duperemove -drh --hashfile="$dest/.hashfile" "$dest"
df -h / "$dest"
ls -v "$dest"
diff --git a/bin/gauth b/bin/gauth
index 699cd84..b18f73d 100755
--- a/bin/gauth
+++ b/bin/gauth
@@ -1,10 +1,9 @@
#!/bin/sh
# Use backup from andOTP
-#gpg -qd ~/otp_accounts.json.gpg.pgp |
-#gpg -qd ~/.otp_accounts.json.gpg |
-cat ~/otp_accounts.json |
+# cat ~/.otp_accounts.json |
+gpg -qd ~/.otp_accounts.json.gpg 2>/dev/null |
jq -r '.[] | "\(.label) \(.secret)"' |
while read -r l s; do
echo "$l $(oathtool --totp -b "$s")"
-done
+done | column -t
diff --git a/bin/hdmi b/bin/hdmi
index d6f206a..e6e3094 100755
--- a/bin/hdmi
+++ b/bin/hdmi
@@ -2,8 +2,8 @@
# Toggle auxiliary HDMI screen on/off when connected/disconnected.
opt="--auto --left-of eDP1"
-#opt="--auto --right-of eDP-1"
-#opt="--auto --above eDP-1"
+#opt="--auto --right-of eDP1"
+#opt="--auto --above eDP1"
# Also add the following rule to /etc/udev/rules.d/hdmi.rules
# KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/marc/.Xauthority", RUN+="/home/marc/bin/hdmi"
@@ -11,5 +11,5 @@ opt="--auto --left-of eDP1"
# wait for the screen to settle
sleep 3
-xrandr | grep -q 'HDMI1 connected' || opt="--off"
-xrandr --output HDMI1 $opt
+xrandr | grep -q '^DP1 connected' || opt="--off"
+xrandr --output DP1 $opt
diff --git a/bin/vm b/bin/vm
index 6b03d0e..8b4da42 100755
--- a/bin/vm
+++ b/bin/vm
@@ -1,285 +1,258 @@
#!/bin/sh
-# vm is a command line tool to manage and operate virtual machines.
-
-vm_version='vm-0.1'
-
+# Manage virtual machines
+#
+# Prereq:
+# - curl
+# - cdrtools (isoinfo)
+# - expect
+# - qemu
+# - screen
+#
# TODO:
-# - DONE: fetch, build and install vftool in .vm/vftool
-# - DONE: setup a config file per VM
-# - DONE: creation of hdd image
-# - DONE: delete a VM
-# - DONE: import iso, kernel, initrd from existing vm
-# - when no vm is specified, apply command to last one
-# - script install from CDROM iso:
-# - patch alpine setup-disk
-# - setup system, including static IP address
-# - setup user account from host
-# - setup ssh from host
-# - time synchronization from host
+# - extract bzImage and initrd.gz with isoinfo
+# - ssh scripts to finish install (once ssh is ready)
+#
+# DONE:
+# - setup vde and networking
+# - setup ssh keys so it is possible to ssh in vm from host
#
-
unset CDPATH
export LC_ALL=C IFS='
'
-add() {
- usage 'add [Options] name' 'Add a new VM' && return
- while getopts :c:i:k:p:s: opt; do
- case $opt in
- [cikps]) eval "$opt=$OPTARG";;
- *) Opth=1 add "$1"; exit ;;
- esac
- done
- shift $((OPTIND - 1))
+version='vm-0.1'
- [ -d "$dir/$1" ] && die "vm $1 already exists in $dir/$1"
- init_alpine || die "could not init alpine iso"
- [ "$1" = 'alpine-iso' ] && return
- mkdir -p "$dir/$1" && cd "$dir/$1" || die "add $1 failed"
- hdd=${p-$1.raw}
- [ -f "$hdd" ] || dd if=/dev/zero of="$hdd" bs=1 count=0 seek="${s-32g}" 2>/dev/null
- echo "hdd=\"$hdd\"" > config
- [ "$c" ] && {
- [ -d "../$c" ] || die "invalid directory: $dir/$c"
- iso=$(getconf "$c" iso)
- cp "../$c/vmlinux" "../$c/initrd" .
- [ "$iso" ] && echo "iso=\"../$c/$iso\"" >> config
- cat <<- EOT >> config
- kernel=${k-vmlinux}
- initrd=initrd
- cpu=1
- ram=512
- arg="console=hvc0"
- EOT
- }
-}
+arch=$(uname -m)
+sys=$(uname -s)
+alpine_version='3.15.0'
+pubkey=$HOME/.ssh/id_rsa.pub
+dir="${VM_DIR:-$HOME/.vm}"
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"
+ usage 'console name' 'Attach a console to a virtual machine' && return
+ [ "$1" ] || die "missing argument"
+ is_running "$1" && screen -r "vm!$1!"
}
-del() {
- usage 'del name' 'Delete a VM' && return
- case $1 in ''|*/*|.*) die "invalid VM name: $1" ;; esac
- [ -d "$dir/$1" ] || die "$dir/$1 not found"
- [ -f "$dir/$1/vftool.pid" ] && die "vm $1 is still active, stop it first"
- rm -rf "${dir:?}/$1"
+create() {
+ usage 'create [-s size] name' 'Create an alpinelinux disk image' && return
+ size=8g
+ while getopts :s: opt; do
+ case $opt in
+ s) size=$OPTARG ;;
+ *) Opth=2 create_alpine_image; return ;;
+ esac
+ done
+ shift $((OPTIND - 1))
+ [ -d "$dir/$1" ] && die "create failed: $dir/$1 already exists"
+ mkdir "$dir/$1"
+ cd "$dir/$1" || die "create failed: invalid directory $dir/$1"
+ qemu-img create "$1.raw" "$size" || die "create failed"
+ mac=$(new_macaddr)
+ ip=$(new_ip)
+ hdd="$1.raw"
+ echo "hdd=$hdd
+mac=$mac
+ip=$ip" >> config
+
+ # Before install do not use virtio, as devices may not recognized as bootable
+ # TODO: alternate way: extract kernel and initrd files and pass them directly to qemu
+ screen -S "vm!$1!" -d -m qemu-system-$arch -nographic \
+ -cdrom ../alpine-iso/alpine-virt-$alpine_version-$arch.iso \
+ -hdd "$hdd" -net nic,macaddr=$mac -net vde
+ setup_alpine "$1"
+ post_setup_alpine "$1"
}
die() { [ "$1" ] && echo "$0: $*" >&2; exit 1; }
-edit() {
- usage 'edit name' 'Edit a VM configuration' && return
- [ -f "$dir/$1/config" ] || die "$dir/$1/config not found"
- ${EDITOR-vi} "$dir/$1/config"
-}
-
-exp() {
- usage 'exp name' 'experiment on a VM' && return
- cd "$dir/$1" || die "invalid VM: $1"
- [ -f vftool.pid ] || die "vm $1 is not active"
-
- sleep 1 && screen -X stuff 'root
-'
- sleep 1 && screen -X stuff 'sed -i.bak "s/die..Bootloader/;; # die \"Bootloader/" /sbin/setup-disk
-'
- sleep 1 && screen -X stuff 'setup-alpine -e
-'
- sleep 1 && screen -X stuff 'none
-'
- sleep 1 && screen -X stuff "$1
-"
- sleep 1 && screen -X stuff 'eth0
-'
- sleep 1 && screen -X stuff '192.168.64.2
-'
- sleep 1 && screen -X stuff '255.255.255.0
-'
- sleep 1 && screen -X stuff '192.168.64.1
-'
- sleep 1 && screen -X stuff 'n
-'
- sleep 3 && screen -X stuff '
-'
- sleep 1 && screen -X stuff '192.168.64.1
-'
- sleep 1 && screen -X stuff 'Europe/Paris
-'
- sleep 5 && screen -X stuff 'none
-'
- sleep 1 && screen -X stuff 'chrony
-'
- sleep 5 && screen -X stuff '1
-'
- sleep 1 && screen -X stuff 'openssh
-'
- sleep 5 && screen -X stuff 'vda
-'
- sleep 3 && screen -X stuff 'sys
-'
- sleep 1 && screen -X stuff 'y
-'
- sleep 20 && screen -X stuff 'blkid /dev/vda3
-'
-}
-
-finalize() {
- tty=$(vftool_tty)
- printf 'root\nuname -a\n' >> "$tty"
-}
-
-getconf() { awk -F '=' -v k="$2" '$1 == k {print $2}' "$dir/$1/config"; }
-
help() {
usage 'help' 'Print this help text' && return
- printf '%s\n' "$vm_version\nManage virtual machines\nUsage: vm command [options] [args]"
+ printf "$version\n Manage virtual machines\n\nUsage: vm command [options] [args]\n"
Opth=1; for c in $Cmdlist; do $c; done
}
-info() {
- usage 'info name' 'Print informations on a VM' && return
- echo 'not implemented yet'
+init() {
+ mkdir -p "$dir"
}
-# 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.3-aarch64.iso
-iso = $(notdir $(iso_url))
-isoinfo ?= /opt/homebrew/bin/isoinfo
-
-all: initrd vmlinux config
+init_alpine_iso() {
+ usage init_alpine_iso '' && return
+ mkdir -p "$dir/alpine-iso"
+ iso_url="https://dl-cdn.alpinelinux.org/alpine/v${alpine_version%.*}/releases/$arch"
+ iso="alpine-virt-$alpine_version-$arch.iso"
+ cd "$dir/alpine-iso"
+ [ -f "$iso" ] || curl -LO "$iso_url/$iso" || rm -f "$iso"
+ echo "iso=$iso
+" > config
+ echo 10 > ../index
+}
-initrd: $(iso) $(isoinfo)
- isoinfo -i $(iso) -J -x /boot/initramfs-virt > $@
+is_running() { screen -ls "vm!$1!" >/dev/null 2>&1; }
-vmlinux: $(iso) $(isoinfo)
- isoinfo -i $(iso) -J -x /boot/vmlinuz-virt | gunzip > $@
+ls() {
+ usage 'ls' 'list virtual machines' && return
+ init && cd "$dir" || die "could not change dir to $dir"
+ for i in */; do
+ i=${i%/}
+ [ "$i" = '*' ] && continue
+ is_running "$i" && state=active || state=stopped
+ printf "%-20s %s\n" "$i" "$state"
+ done
+}
-config: $(iso)
- @echo "iso=$(iso)" >config
- @echo "initrd=initrd" >>config
- @echo "kernel=vmlinux" >>config
- @echo "cpu=1" >> config
- @echo "ram=512" >> config
- @echo "arg=\"console=hvc0\"" >> config
+new_ip() {
+ read index < $dir/index
+ index=$((index + 1))
+ echo "$index" > $dir/index
+ echo "10.0.2.$index/24"
+}
-$(iso):
- curl -LO $(iso_url) || { rm -f $@; false; }
+new_macaddr() { printf 'de:ad:be:ef:%02x:%02x\n' $((RANDOM % 256)) $((RANDOM % 256)); }
-$(isoinfo):
- brew install cdrtools
-'
+pidof() {
+ usage 'pidof name' 'print the PID of a virtual machine' && return
+ p=$(screen -ls "vm!$1!" | awk 'NR==2 {print substr($1, 1, index($1, ".")-1)}')
+ [ "$p" ] && pgrep -P $p
+}
-init_alpine() {
- mkdir -p "$dir/alpine-iso" && cd "$dir/alpine-iso" || die 'init alpine failed'
- [ -f 'Makefile' ] || printf '%s' "$alpine_makefile" > Makefile
- make -s all
+post_setup_alpine() {
+ start "$1"
+ read proto key id < "$pubkey"
+ # echo '
+ expect -c '
+ set timeout -1
+ spawn screen -x "vm!'$1'!"
+ expect {
+ " login: " { send "root\r"; exp_continue }
+ "Password: " { send "root\r"; exp_continue }
+ ":~# "
+ }
+ send "mkdir -pm 0700 .ssh\r"
+ expect ":~# "
+ send "echo '$proto' '$key' '$id' >.ssh/authorized_keys\r"
+ expect ":~# "
+ send "exit\r"
+ '
}
-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'
+# setup_alpine automates alpine installation from iso to image.
+# When done, base image system is ready, with storage and network up.
+# No user nor ssh access configured yet.
+# TODO: custom network (in case of no dhcp).
+setup_alpine() {
+ usage 'setup_alpine' && return
+ expect -c '
+ set timeout -1
+ spawn screen -x "vm!'$1'!"
+ expect {
+ "localhost login: " { send "root\r"; exp_continue }
+ "localhost:~# " { send "SWAP_SIZE=0 setup-alpine\r"; exp_continue }
+ "Select keyboard layout: " { send "\r"; exp_continue }
+ "Enter system hostname" { send "'$1'\r"; exp_continue }
+ "Which one do you want to initialize?" { send "\r"; exp_continue }
+ "Ip address for eth0?" { send "'$ip'\r"; exp_continue }
+ "Gateway?" { send "10.0.2.2\r"; exp_continue }
+ "manual network configuration?" { send "\r"; exp_continue }
+ "DNS domain name?" { send "lan\r"; exp_continue }
+ "DNS nameserver(s)?" { send "10.0.2.2 1.1.1.1\r"; exp_continue }
+ "New password:" { send "root\r"; exp_continue }
+ "Retype password:" { send "root\r"; exp_continue }
+ "Which timezone are you in?" { send "\r"; exp_continue }
+ "HTTP/FTP proxy URL?" { send "\r"; exp_continue }
+ "Enter mirror number " { send "\r"; exp_continue }
+ "Which SSH server?" { send "\r"; exp_continue }
+ "Which disk(s) would you like to use?" { send "sda\r"; exp_continue }
+ "How would you like to use it?" { send "sys\r"; exp_continue }
+ "Erase the above disk(s) and continue?" { send "y\r"; exp_continue }
+ "Installation is complete" { send "poweroff\r" }
+ }
+ interact
+ '
}
-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
+start_vde() {
+ usage start_vde && return
+ sudo sh <<- EOT
+ vde_switch -tap tap0 -sock /tmp/vde.ctl -daemon -mod 666
+ sleep 1
+ ip address add 10.0.2.2/24 dev tap0
+ ip link set tap0 up
+ echo 1 > /proc/sys/net/ipv4/ip_forward
+ iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -o eth0 -j MASQUERADE
+ iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -o wlan0 -j MASQUERADE
+ EOT
+ #slirpvde --dhcp --daemon
}
-ls() {
- usage 'ls' 'list VMs' && return
- [ -d "$dir" ] && cd "$dir" || return
- for i in */; do
- i=${i%/}
- [ "$i" = '*' ] && continue
- [ -f "$i/vftool.pid" ] && state=active || state=stopped
- printf "%-20s %s\n" "$i" "$state"
- done
+stop_vde() {
+ # killall slirpvde
+ sudo sh <<- EOT
+ iptables -t nat -D POSTROUTING -s 10.0.2.0/24 -o eth0 -j MASQUERADE
+ iptables -t nat -D POSTROUTING -s 10.0.2.0/24 -o wlan0 -j MASQUERADE
+ ip link set tap0 down
+ killall vde_switch
+ EOT
}
start() {
- usage 'start [-afs] name' 'Start a VM' && return
- while getopts :afs opt; do
+ usage 'start [-acd] name' 'start a virtual machine' && return
+ while getopts :acd opt; do
case $opt in
- (a) a=1 ;;
- (f) f=1 ;;
- (s) s=1 ;;
- (*) Opth=1 start "$1"; exit;;
+ a) opta=1 ;;
+ c) boot=c ;;
+ d) boot=d ;;
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 & sleep 2
- ! [ "$f" ] || finalize
- ! [ "$a" ] || vm console "$1"
- ! [ "$s" ] || exec ssh "$1"
+ shift $((OPTIND -1))
+ [ "$1" ] || die 'start failed: name missing'
+ cd "$dir/$1" || die "start failed: invalid directory $dir/$1"
+ is_running "$1" || start_qemu "$1"
+ [ "$opta" ] && console "$1"
}
-start_vm() (
- [ -f vftool.log ] && cat vftool.log >> vftool.log.old
- exec 1>vftool.log 2>&1
- . config || die "vm: could not source $PWD/config"
- trap 'rm -f vftool.pid' EXIT
-
- "$dir/vftool" \
- ${kernel+-k "$kernel"} \
- ${initrd+-i "$initrd"} \
- ${hda+-d "$hda"} \
- ${hdb+-d "$hdb"} \
- ${iso+-c "$iso"} \
- ${cpu+-p "$cpu"} \
- ${ram+-m "$ram"} \
- -a "${arg-console=hvc0}" \
- >>vftool.log 2>&1 & sleep 1
-
- echo "$!" >vftool.pid
- screen -S "${PWD##*/}" -d -m "$(vftool_tty)"
- wait
+start_qemu() (
+ opt='-nographic -cpu max'
+ [ "$sys" = Linux ] && opt="$opt -enable-kvm"
+ . ./config || die "could not source $PWD/config"
+ exec 1>>qemu.log 2>&1
+ date +%F_%T
+ set -x
+ screen -S "vm!$1!" -d -m qemu-system-$arch $opt \
+ ${smp+-smp $smp} \
+ ${ram+-m $ram} \
+ ${mac+-net nic,macaddr=$mac,model=virtio-net-pci} -net vde \
+ ${hdd+-drive file="$hdd",if=virtio,media=disk,format=raw} \
+ ${iso+-drive file="$iso",if=virtio,media=cdrom,format=raw} \
+ ${boot+-boot $boot}
)
stop() {
- usage 'stop name' 'Stop a VM' && return
- [ "$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)" || rm -f vftool.pid
+ usage 'stop name' 'stop a virtual machine' && return
+ is_running "$1" && kill "$(pidof "$1")"
}
-usage() { [ "$Opth" ] && printf " %-34s %s\n" "$1" "$2"; }
+usage() {
+ case $Opth in
+ 1) printf " %-34s %s\n" "$1" "$2" ;;
+ 2) printf "$0 $1\n\t$2\n" ;;
+ *) return 1 ;;
+ esac
+}
version() {
usage 'version' 'Print version' && return
- echo "$vm_version"
+ echo "$version"
}
-vftool_tty() { grep -om 1 '\/dev\/tty.*' 'vftool.log'; }
-
-# Main starts here.
-dir="$HOME/.vm"
-Cmdlist='add console del edit exp info help ls log start stop version'
+Cmdlist='console create help init_alpine_iso ls pidof setup_alpine start start_vde stop version'
[ "$1" ] && C=$1 && shift 1 || { help; exit 1; }
-for c in $Cmdlist; do
- case $c in
- ("$C") cmd=$c; break ;;
- ("$C"*) [ "$cmd" ] && die "ambiguous command $C" || cmd=$c ;;
- esac
-done
+#for c in $Cmdlist; do
+# case $c in
+# ("$C") cmd=$c; break ;;
+# ("$C"*) [ "$cmd" ] && die "ambiguous command $C" || cmd=$c ;;
+# esac
+#done
+cmd=$C
[ "$cmd" ] || { help; exit 1; } && $cmd "$@"
diff --git a/bin/xt b/bin/xt
index 9395b3e..98f6ac6 100755
--- a/bin/xt
+++ b/bin/xt
@@ -2,4 +2,5 @@
#exec xterm -sl 500 -j -cr red "$@" &
exec xterm "$@" &
#cmd="urxvtc ${@:--T $HOSTNAME}"
+#cmd="urxvtc $@"
#eval "$cmd" || { [ $? = 2 ] && urxvtd -q -o -f && eval "$cmd"; }