Last active
August 9, 2023 14:14
-
-
Save billchurch/0f5388e8025d55b5830519937f628aaf to your computer and use it in GitHub Desktop.
A simple script that builds a template on Proxmox VE v7.x from a qcow2 image and provides some customization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
newbigip.sh | |
#!/bin/bash | |
# This script will: | |
# - Create a 2 core 4096MB BIG-IP virtual machine | |
# - Install the image specified | |
# - Customize the image by loading bootstrap files to /config and | |
# expects: | |
# startup* | |
# .startup-env | |
# to be in the current directoy | |
# - Promote virtual machine to a template for later use. | |
# | |
# This script is only useful/safe on Proxmox VE v7.x+ AND | |
# those that use ZFS as storage and NO LVM usage. This is due | |
# to the fact that there's not a lot of error checking on LVM | |
# operations to mount and umount the BIG-IP image and it will | |
# most likley blow away any existing LVM config | |
# | |
# See: https://github.com/billchurch/bigip-bootstrap for details on | |
# how I use /startup* and .startup-env files | |
# | |
# usage: | |
# newbigip.sh <big-ip qcow image file (without path)> <vmid> | |
# | |
# requires: | |
# kpartx (apt-get install kpartx) | |
# proxmox ve v7.x+ | |
# a bigip image? | |
# | |
# Bill Church - bill@f5.com | |
# | |
# Changelog: | |
# | |
# 20220615 - First Release | |
script_version=20220615 | |
prerequisites="kpartx pvesh qemu-img vgchange lvchange dmsetup" | |
logfile="/var/log/$(mktemp -u newbigip-XXXX.log)" | |
scriptname=$(basename "$0") | |
script_path="${BASH_SOURCE[0]}"; | |
script_full="${script_path}/${scriptname}" | |
pve_node=pve | |
file=$1 | |
node_id=$2 | |
cols=$(tput cols) | |
node_name=${file%.qcow2*} | |
# cpu cores | |
cores=2 | |
# ram in megabytes | |
memory=4096 | |
vm_config="--net0 model=virtio,bridge=vmbr0,tag=30 --net1 model=virtio,bridge=vmbr0,tag=10 --net2 model=virtio,bridge=vmbr0,tag=20 --net3 model=virtio,bridge=vmbr0,link_down=1 --ostype l26 --serial0 socket --cores ${cores} -sockets 1 --memory ${memory} --name ${node_name}" | |
#colors | |
_fgLtRed=$(tput bold;tput setaf 1) | |
_fgLtGrn=$(tput bold;tput setaf 2) | |
_fgLtYel=$(tput bold;tput setaf 3) | |
_fgLtBlu=$(tput bold;tput setaf 4) | |
_fgLtMag=$(tput bold;tput setaf 5) | |
_fgLtCya=$(tput bold;tput setaf 6) | |
_fgLtWhi=$(tput bold;tput setaf 7) | |
_fgLtGry=$(tput bold;tput setaf 8) | |
echo "${_fgLtWhi}" | |
clear | |
echoNotice () { echo -e -n "\n$*... "; } | |
logit() { | |
date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") | |
echo "$date - $script_full}: f$*" >> "$logfile" | |
} | |
touch "${logfile}" | |
logit "${script_full} - $script_version" | |
# checks the output of a command to get the status and report/handle failure | |
checkOutput() { | |
if [ "$result" -eq 0 ]; then | |
# success | |
echo "${_fgLtGrn}[OK]${_fgLtWhi}" | |
logit "[SUCCESS]: ${command}" | |
return | |
else | |
# failure | |
logit " [FAILED]: ${command}" | |
logit " ${output}" | |
tput bel;tput bel;tput bel;tput bel | |
echo "${_fgLtRed}[FAILED]${_fgLtWhi}" | |
echo -e "\nPrevious command failed in ${script_full} with error level: ${result}" | |
echo -e "\nCommand:\n" | |
echo " ${command}" | |
echo -e "\nSTDOUT/STDERR:\n" | |
echo "${output}" | |
rm -rf "$workingdir" | |
exit 255 | |
fi | |
} | |
# run a comand and check call checkOutput | |
runCommand() { | |
# $1 command | |
# $2 show output (0 yes, 1 no) | |
command=$1 | |
if [[ -n "$2" ]]; then | |
eval "$command" | |
output="Sent to console..." | |
result="$?" 2>&1 | |
else | |
output=$( (eval "$command") 2>&1) | |
result="$?" 2>&1 | |
fi | |
checkOutput | |
} | |
function run_help() { | |
fold -s -w "$cols" <<HELPFILE | less --RAW-CONTROL-CHARS -X -F -K -E | |
${_fgLtGrn}${scriptname} v${script_version}${_fgLtWhi} | |
--------------------- | |
Create a BIG-IP virtual machine on Proxmox v7.x+ and install a new image | |
usage: | |
${_fgLtCya}${scriptname} ${_fgLtYel}<big-ip qcow image file (without path)> ${_fgLtMag}<new_vmid>${_fgLtWhi} | |
Details | |
This script will: | |
- Create a 2 core 4096MB BIG-IP virtual machine | |
- Install the image specified | |
- Customize the image by loading bootstrap files to ${_fgLtCya}/config${_fgLtWhi} and | |
expects: | |
${_fgLtCya}startup*${_fgLtWhi} | |
${_fgLtCya}.startup-env${_fgLtWhi} | |
to be in the current directoy | |
- Promote virtual machine to a template for later use. | |
This script is only useful/safe on Proxmox VE v7.x+ AND those that use ZFS as storage and ${_fgLtRed}NO LVM usage${_fgLtWhi}. This is due to the fact that there's not a lot of error checking on LVM operations to mount and umount the BIG-IP image and it will most likley blow away any existing LVM config. | |
HELPFILE | |
echo | |
} | |
if [[ $# -lt 2 ]] ; then | |
run_help | |
exit 255 | |
fi | |
# get cli params... | |
POSITIONAL=() | |
while [[ $# -gt 0 ]] | |
do | |
key="$1" | |
case $key in | |
-h|--help) | |
run_help | |
exit 255 | |
shift | |
;; | |
*) | |
shift | |
;; | |
esac | |
done | |
set -- "${POSITIONAL[@]}" # restore positional parameters | |
for prereq in $prerequisites | |
do | |
echoNotice "Checking prerequisite \"$prereq\" installed" | |
runCommand "which $prereq" | |
done | |
echoNotice "Source image exists" | |
runCommand "test -f $file" | |
echoNotice "Checking that target node does not exist" | |
output=$( (pvesh get /nodes/$pve_node/qemu/$node_id/status/current) 2>&1) | |
result="$?" 2>&1 | |
if [ "$result" -ne 0 ]; then | |
# success | |
echo "${_fgLtGrn}[OK]${_fgLtWhi}" | |
else | |
echo "${_fgLtRed}[FAILED]${_fgLtWhi}" | |
echo -e "\nThe target node already exists, aborting!\n" | |
exit 255 | |
fi | |
echoNotice "Geting disk size of source image $file" | |
disk_size=$(qemu-img info $file | grep "virtual size"|awk '{ print $3 }') | |
echo ${_fgLtGrn}[${disk_size}G]${_fgLtWhi} | |
echoNotice "Creating guest VM $node_id" | |
runCommand "pvesh create /nodes/$pve_node/qemu --vmid $node_id $vm_config --scsi0 local-zfs:${disk_size},discard=on,ssd=on --scsihw virtio-scsi-pci --balloon 0 --boot order=scsi0" | |
echoNotice "Getting disk location" | |
disk_loc=$(pvesh get /nodes/pve/qemu/$node_id/config --output-format json-pretty | jq .scsi0 | grep -Po "vm[^,]*+") | |
echo "${_fgLtGrn}[$disk_loc]${_fgLtWhi}" | |
echo -e "\nConverting source image of $file to $node_id" | |
runCommand "/usr/bin/qemu-img convert -p -n -f qcow2 -O raw $file zeroinit:/dev/zvol/rpool/data/$disk_loc" 1 | |
echoNotice "Reading LVM data from disk image" | |
runCommand "kpartx -a /dev/zvol/rpool/data/$disk_loc" | |
echoNotice "Waiting for config volume" | |
until [ -b /dev/vg-db-vda/set.1._config ] | |
do | |
echo -n "." | |
sleep 1 | |
done | |
echo "${_fgLtGrn}[OK]${_fgLtWhi}" | |
temp_mount=$(mktemp -d -t newbigip.XXXXXXXXXX) | |
echoNotice "Mounting config volume" | |
runCommand "mount /dev/vg-db-vda/set.1._config $temp_mount" | |
echoNotice "Copying startup to config" | |
runCommand "cp startup* .startup-env $temp_mount;chmod 755 ${temp_mount}/startup* ${temp_mount}/.startup-env" | |
echoNotice "Un mounting config volume" | |
runCommand "umount $temp_mount" | |
echoNotice "Removing temp mountpoint" | |
runCommand "rmdir ${temp_mount}" | |
echo "\n${_fgLtRed}This next part is potentially destructive${_fgLtWhi}, especially if you're using LVM... In fact, if you're using LVM you shouldn't even be using this script!" | |
echo "\nPress any key to deactivate LVM..." | |
read -n1 _NUL | |
echoNotice "Deactivating LVM volumes" | |
runCommand "lvchange -an /dev/vg-db-vda/*" | |
echoNotice "Deactivating volume groups" | |
runCommand "vgchange -an vg-db-vda" | |
echo "Removing disks from lvm config" | |
for disk in $(dmsetup ls | awk '{print $1}'); do dmsetup remove $disk; done | |
echoNotice "Promoting $node_id to template" | |
runCommand "pvesh create /nodes/$pve_node/qemu/$node_id/template" | |
echo "${_fgLtGrn}Complete!${_fgLtWhi}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment