#!/usr/bin/env bash # le-lab: set up, grade and reset LINUXexpert practice labs on a throwaway VM. # Run "le-lab help" for usage. set -uo pipefail ROOT=$(cd "$(dirname "$(readlink -f "$0")")" && pwd) . "$ROOT/lib/lab.sh" MARKER=/etc/le-lab/throwaway-vm CURRENT=$LE_STATE/current usage() { cat </dev/null) || virt=none if systemd-detect-virt --container >/dev/null 2>&1; then die "this is a container ($virt); labs need a full virtual machine" fi if [ "$virt" = none ]; then die "this doesn't look like a virtual machine; labs only run on a throwaway VM" fi cat <"$MARKER" } # Attaches the spare disks again at boot; installed once, harmless when # there are none. install_disk_unit() { local unit=/etc/systemd/system/le-lab-disks.service old='' [ -f "$unit" ] && old=$(cat "$unit") cat >"$unit" <"$CURRENT" exit 1 ;; esac printf '%s\n' "$id" >"$CURRENT" say '' cmd_tasks say '' say "When you're ready: ${C_B}sudo $0 check${C_0}" } current_dir() { [ -f "$CURRENT" ] || die "no lab is set up (try: le-lab list, then le-lab start LAB)" lab_dir "$(cat "$CURRENT")" } cmd_tasks() { local dir; dir=$(current_dir) # Print the README's "Before you start" and "Tasks" sections as plain # text. awk '/^## /{p = ($0 ~ /^## (Before you start|Tasks)/); if (p) print toupper(substr($0, 4)); next} p' "$dir/README.md" local url; url=$(conf_get "$dir" CHAPTER) [ -n "$url" ] && say "Study guide chapter: https://linuxexpert.net$url" true } cmd_check() { need_root check local dir id dir=$(current_dir); id=$(lab_id "$dir") export LAB_DIR=$dir LAB_STATE=$LE_STATE/labs/${id//\//_} say "${C_B}$id: $(conf_get "$dir" TITLE)${C_0} on $OS_NAME" say '' bash -c '. "$1/lib/lab.sh"; . "$2/check.sh"; grade_report' _ "$ROOT" "$dir" } cmd_reset() { need_root reset local dir id dir=$(current_dir); id=$(lab_id "$dir") export LAB_DIR=$dir LAB_STATE=$LE_STATE/labs/${id//\//_} say "Resetting $id..." if [ -f "$dir/reset.sh" ]; then bash -c '. "$1/lib/lab.sh"; . "$2/reset.sh"' _ "$ROOT" "$dir" || warn "Some of the reset failed; see above." fi bash -c '. "$1/lib/lab.sh"; users_remove; disks_remove; peer_down; nodes_down' _ "$ROOT" rm -rf "$LAB_STATE" "$CURRENT" /root/lab-answers say "Done. Anything you changed outside the lab's own files is still there;" say "roll back to your snapshot for a completely clean VM." } cmd_status() { if [ -f "$CURRENT" ]; then local dir; dir=$(lab_dir "$(cat "$CURRENT")") say "Set up: $(cat "$CURRENT") ($(conf_get "$dir" TITLE))" [ -f "$LE_STATE/last-score" ] && say "Last check: $(cut -d' ' -f2 "$LE_STATE/last-score") tasks" else say "No lab is set up." fi } case ${1:-help} in list) shift; cmd_list "$@" ;; start) shift; cmd_start "$@" ;; tasks) cmd_tasks ;; check) cmd_check ;; reset) cmd_reset ;; status) cmd_status ;; help | -h | --help) usage ;; *) usage >&2; exit 2 ;; esac