#!/usr/bin/env bash # libvirt wrappers for Sysadmin Chronicles. # Source this file; do not execute directly. # Expects LIBVIRT_DEFAULT_URI to be set by the caller. # # SC_VIRSH_SUDO=true — prefix all virsh calls with sudo. # Set this in install.sh when the current session doesn't yet have # the libvirt group active (e.g., right after usermod -aG libvirt). _virsh() { if [ "${SC_VIRSH_SUDO:-false}" = true ]; then sudo virsh "$@" else virsh "$@" fi } ensure_network() { local name="$1" local xml_path="$2" if _virsh net-list --all 2>/dev/null | grep -q "\\b${name}\\b"; then if ! _virsh net-info "$name" 2>/dev/null | grep -q "Active:.*yes"; then _virsh net-start "$name" >/dev/null 2>&1 fi return 0 fi _virsh net-define "$xml_path" >/dev/null 2>&1 _virsh net-autostart "$name" >/dev/null 2>&1 _virsh net-start "$name" >/dev/null 2>&1 } ensure_pool() { local name="$1" local path="$2" if _virsh pool-list --all 2>/dev/null | grep -q "\\b${name}\\b"; then if ! _virsh pool-info "$name" 2>/dev/null | grep -q "State:.*running"; then _virsh pool-start "$name" >/dev/null 2>&1 fi return 0 fi mkdir -p "$path" _virsh pool-define-as "$name" dir --target "$path" >/dev/null 2>&1 _virsh pool-autostart "$name" >/dev/null 2>&1 _virsh pool-start "$name" >/dev/null 2>&1 } pool_path() { local name="$1" _virsh pool-dumpxml "$name" 2>/dev/null \ | sed -n 's:.*\(.*\).*:\1:p' \ | head -n1 } domain_exists() { _virsh dominfo "$1" >/dev/null 2>&1 } domain_state() { _virsh domstate "$1" 2>/dev/null | tr -d ' \n' } network_active() { _virsh net-info "$1" 2>/dev/null | grep -q "Active:.*yes" } ensure_network_active() { local name="$1" _virsh net-list --all 2>/dev/null | grep -q "\\b${name}\\b" || return 1 network_active "$name" || _virsh net-start "$name" >/dev/null 2>&1 } snapshot_exists() { _virsh snapshot-info "$1" "$2" >/dev/null 2>&1 } snapshot_create() { local domain="$1" local name="$2" local desc="${3:-}" _virsh snapshot-delete "$domain" "$name" >/dev/null 2>&1 || true _virsh snapshot-create-as "$domain" "$name" --description "$desc" --atomic } snapshot_revert() { _virsh snapshot-revert "$1" "$2" --running } snapshot_delete() { _virsh snapshot-delete "$1" "$2" } snapshot_list_names() { _virsh snapshot-list "$1" --name 2>/dev/null || true } # Returns approximate qcow2 disk usage for a domain in human-readable form domain_disk_usage() { local domain="$1" local total=0 local disk for disk in $(_virsh domblklist "$domain" --details 2>/dev/null | awk '/disk/ && $4 != "-" {print $4}' || true); do [ -f "$disk" ] || continue local sz sz="$(du -sb "$disk" 2>/dev/null | awk '{print $1}' || echo 0)" total=$(( total + sz )) done if [ "$total" -gt 0 ]; then numfmt --to=iec-i --suffix=B "$total" 2>/dev/null || echo "${total}B" else echo "0B" fi }