#!/bin/sh # shellcheck disable=SC1090 # shellcheck disable=SC2038 # shellcheck disable=SC2154 # Deploy script for OpenBSD Amsterdam # CONF_FILE "_vms.conf" needs to have the following variables: ## Server config for -install.conf #SERVER="server1" #DOMAIN="example.com" ## IP / MAC config #IP_PREFIX="192.168.0" #IP_START=100 #IPV6_PREFIX="fe1:dead:beef" #IPV6_START=1000 #MAC_PREFIX="fe:1e:bb:4d:3c" ## .conf locations #VMS="/root/vms" #ETC="/etc" #IMAGES="/var/vmm" #HTDOCS="/var/www/htdocs" ## vm.conf #VMDUSERS="vmdusers" #UPLINK="uplink_vlan42" #BRIDGE="bridge42" ## dhcpd.conf #ROUTER="192.168.0.1" #DNS="192.186.0.1" #SUBNET="192.168.0.1" #NETMASK="255.255.255.0" #RANGE="192.168.1.10 192.168.1.10" set -e umask 022 main () { CONF_FILE="$PWD/_vms.conf" [ -f "$CONF_FILE" ] && . "$CONF_FILE" date=$(date "+%Y-%m-%d %H:%M:%S") echo "New config files created for $SERVER @ $date" echo "VM definition files in: $VMS" fs=$( list_files "$VMS" ) if test -n "$fs" then echo "$fs" echo "$fs" | render_vm_conf > "${ETC}/vm.conf" echo "$fs" | render_dhcpd_conf > "${ETC}/dhcpd.conf" echo "$fs" | render_install_conf echo "$fs" | create_images echo "$fs" | create_users fi } list_files() { # Find all the VM config files. # Takes the directory with vm*.txt files find "$1" -type f -name "vm*.txt" -maxdepth 1 | sort -V | xargs grep -l "message" } find_vm() { # Find the number of the VM (VM#). # Takes the directory with vm*.txt files and instance # Checks if instance exists otherwise returns the vm filename if _vm=$(cd "$1" && find . -type f -name "vm*.txt" -maxdepth 1 | xargs grep -l "$2") then echo "$_vm" | sed 's/^\.\/vm//;s/\.txt$//' else echo "$2" | sed 's/^vm//' fi } fetch_mac() { # Fetch the MAC address for the VM. # Takes the MAC_PREFIX and VM# # print the MAC address echo "${1}:${2}" } fetch_switch() { # Fetch the uplink for the VM. # Takes the UPLINK and switch. # print the switch if test -z "$2" then echo $1 else echo $2 fi } fetch_ip() { # Fetch the IP address for the VM. # Takes the IP_PREFIX, IP_START, VM# and ip. # add IP_START and VM# and print the IP address # print the IP address if test -z "$4" then _prefix=$1 _host=$(($2 + $3)) echo "${_prefix}.${_host}" else echo "$4" fi } fetch_ipv6() { # Fetch the IPv6 address of the VM. # Takes the IPV6_PREFIX, IPV6_START, IP_START, VM# and ipv6. # add IPV6_START and VM#, IP_START and VM# and print the IPv6 address # print the IPv6 address if test -z "$5" then _prefix=$1 _subnet=$(($2 + $4)) _host=$(($3 + $4)) echo "${_prefix}:${_subnet}::${_host}" else echo "$5" fi } generate_passwd() { # Generate a random password for the -install.conf file. # Doesn't take variables #tr -cd '[:alnum:]' < /dev/urandom | fold -w 20 | head -n 1 jot -rcs '' 20 33 126 } check_instance() { # Check if the instance name exists, otherwise return filename as VM. # Takes vm*.txt and instance # prints either filename or instance variable if test -z "$2" then echo "$1" | sed "s@^$VMS@@;s@^/@@;s/\\.txt$//" else echo "$2" fi } check_owner() { # Check if the owner name exists, otherwise returns username. # Takes username and owner # prints either owner or username if test -z "$2" then echo "$1" else echo "$2" fi } clear_variables() { # Clears all variables in vm*.txt. # Doesn't take variables unset instance unset date unset payment unset donated unset owner unset name unset email unset message unset hostname unset ip unset ipv6 unset username unset note } render_vm_conf() { # Generate vm.comf # Takes defaults from of _vms.conf and iterate over the vm*.txt files. # When the owner exists add "owner". # When the VM image doesn't exist add "boot". # fetch_mac() to get the correct MAC address of the VM. printf "#\\n# File generated on %s\\n#\\n" "$date" printf "socket owner :%s\\n\\n" "$VMDUSERS" printf "switch \"%s\" {\\n" "$UPLINK" printf "\\tinterface %s\\n" "$BRIDGE" printf "}\\n\\n" if ! test -z "$UPLINK2" then printf "switch \"%s\" {\\n" "$UPLINK2" printf "\\tinterface %s\\n" "$BRIDGE2" printf "}\\n\\n" fi while read -r f do . "$f" _instance=$(check_instance "$f" "$instance") _owner=$(check_owner "$username" "$owner") printf "vm \"%s\" {\\n" "$_instance" printf "\\tdisable\\n" printf "\\towner %s\\n" "$_owner" if ! test -f "${IMAGES}/${_instance}.img" then printf "\\tboot \"%s/bsd.rd\"\\n" "$IMAGES" fi printf "\\tdisk \"%s/%s.img\"\\n" "$IMAGES" "$_instance" printf "\\tinterface tap {\\n" #printf "\\t\\tswitch \"uplink_vlan921\"\\n" printf "\\t\\tswitch \"$(fetch_switch "$UPLINK" "$switch")\"\\n" printf "\\t\\tlladdr %s\\n" "$(fetch_mac "$MAC_PREFIX" "$(find_vm "$VMS" "$_instance")")" printf "\\t}\\n" printf "}\\n" clear_variables done } render_dhcpd_conf() { # Generate dhcpd.comf # Takes defaults from of _vms.conf and iterate over the vm*.txt files. # When the VM image doesn't exist add "auto_install". # When the VM image does exist add "auto_upgrade". # fetch_mac() to get the correct MAC address of the VM. # fetch_ip() to get the correct IP address of the VM. printf "#\\n# File generated on %s\\n#\\n" "$date" printf "option domain-name \"%s\";\\n" "$DOMAIN" printf "option domain-name-servers %s;\\n\\n" "$DNS" printf "subnet %s netmask %s {\\n" "$SUBNET" "$NETMASK" printf "\\toption routers %s;\\n" "$ROUTER" printf "\\tserver-name \"%s.%s\";\\n" "$SERVER" "$DOMAIN" #printf "\\trange %s;\\n\\n" "$RANGE" while read -r f do . "$f" _instance=$(check_instance "$f" "$instance") printf "\\thost %s {\\n" "$_instance" printf "\\t\\thardware ethernet %s;\\n" "$(fetch_mac "$MAC_PREFIX" "$(find_vm "$VMS" "$_instance")")" printf "\\t\\tfixed-address %s;\\n" "$(fetch_ip "$IP_PREFIX" "$IP_START" "$(find_vm "$VMS" "$_instance")" "$ip")" if ! test -f "${IMAGES}/${_instance}.img" then printf "\\t\\tfilename \"auto_install\";\\n" else printf "\\t\\tfilename \"auto_upgrade\";\\n" fi printf "\\t\\toption host-name \"%s\";\\n" "$hostname" printf "\\t}\\n" clear_variables done printf "}\\n" } render_install_conf() { # Generate -install.comf # Takes defaults from of _vms.conf and iterate over the vm*.txt files. # When the VM image doesn't exist create the -install.conf file. # When the VM image does exist remove the -install.conf file. # fetch_ipv6() to get the correct IPv6 address of the VM. # fetch_mac() to get the correct MAC address of the VM. while read -r f do . "$f" _instance=$(check_instance "$f" "$instance") _pass="$(generate_passwd)" _ipv6=$(fetch_ipv6 "$IPV6_PREFIX" "$IPV6_START" "$IP_START" "$(find_vm "$VMS" "$_instance")" "$ipv6") _ipv6_gateway=$(echo "$_ipv6" | sed -e 's/::[0-9]*$/::1/g') _mac=$(fetch_mac "$MAC_PREFIX" "$(find_vm "$VMS" "$_instance")") if ! test -f "${IMAGES}/${_instance}.img" then cat <<-EOF > "${HTDOCS}/${_mac}-install.conf" # # File generated on $date # System hostname = $hostname Password for root = $_pass Which speed should com0 = 115200 Network interfaces = vio0 IPv4 address for vio0 = dhcp IPv6 address for vio0 = $_ipv6 IPv6 default router = $_ipv6_gateway Setup a user = $username Password for user = $_pass Public ssh key for user = $message $_pass Which disk is the root disk = sd0 What timezone are you in = Europe/Amsterdam Location of sets = http Server = openbsd.amsterdam Set name(s) = -x* +xb* +xf* +site* Continue anyway = yes Continue without verification = yes EOF echo "Install file created: ${HTDOCS}/${_mac}-install.conf" else if test -f "${HTDOCS}/${_mac}-install.conf" then rm -rf "${HTDOCS}/${_mac}-install.conf" fi fi clear_variables done } create_images() { while read -r f do . "$f" _instance=$(check_instance "$f" "$instance") if ! test -f "${IMAGES}/${_instance}.img" then vmctl create "${IMAGES}/${_instance}.img" -s 50G > /dev/null echo "Image file created: ${IMAGES}/${_instance}.img" fi clear_variables done } create_users() { while read -r f do . "$f" _owner=$(check_owner "$username" "$owner") if test -n "$_owner" then if ! grep -e "^${_owner}:" /etc/passwd > /dev/null then useradd -m -G "$VMDUSERS" "$_owner" echo "$message" > "/home/${_owner}/.ssh/authorized_keys" echo "User created: $_owner" fi fi clear_variables done } main "$@"