Last active
March 28, 2024 00:53
-
-
Save MrLenin/240b0ffd793858030525c89cc5291937 to your computer and use it in GitHub Desktop.
Basic proxmox hookscript and cloud-init bootcmd to insert interface ip addresses into hosts file template
This file contains hidden or 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
Can be useful for vm guests with dhcp assigned addresses, but can likely be extended to do almost | |
anything cloud-init can be used to do. | |
regenerate-cloud-init-data.pl is a hookscript that is attached to your vm template so that it | |
is present in the config for all VMs cloned from it. It is not likely suitable for environments | |
with multiple nodes as-is. | |
It is run prior to the starting of the VM and regenetates the vm-<id>-userconfig.yaml file from a | |
template containing the bootcmd and any other cloud-config data you wish to use. It also appends | |
configuration data to set the hostname (the VM name) and fqdn (configured in the script) of the VM. | |
The bootcmd could be made a bunch simpler if you don't care about readability or formatting of | |
the final hosts file, or even more complex if you do or require more selective naming abilities. | |
I do care a little about readability and formatting, but I'm lazy so I just chopped the file in 3. | |
I included the chopped up debian template for reference, other distros may or may not have their own | |
template file. |
This file contains hidden or 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
#!/usr/bin/perl | |
use strict; | |
use warnings; | |
use File::Copy; | |
use PVE::APIClient::LWP; | |
use PVE::AccessControl; | |
use PVE::INotify; | |
################################################################################ | |
# change these | |
# filesystem path which contains the snippets directory | |
my $cloudinit = "/var/cloudinit/"; | |
# the volume which contains the snippets directory | |
my $volumeid = "cloudinit"; | |
# domain suffix used for fqdn | |
my $domainsuffix = ".fractalrealities.net"; | |
################################################################################ | |
print "GUEST HOOK: " . join(' ', @ARGV). "\n"; | |
my $vmid = shift; | |
my $phase = shift; | |
my $tmpl = $cloudinit . "userconfig.yaml.tmpl"; | |
my $genfile = $cloudinit . "snippets/vm-" . $vmid . "-userconfig.yaml"; | |
################################################################################ | |
sub get_local_cert_fingerprint { | |
my ($node) = @_; | |
my $cert_path = "/etc/pve/nodes/$node/pve-ssl.pem"; | |
my $custom_cert_path = "/etc/pve/nodes/$node/pveproxy-ssl.pem"; | |
$cert_path = $custom_cert_path if -f $custom_cert_path; | |
my $bio = Net::SSLeay::BIO_new_file($cert_path, 'r'); | |
my $cert = Net::SSLeay::PEM_read_bio_X509($bio); | |
Net::SSLeay::BIO_free($bio); | |
my $fp = Net::SSLeay::X509_get_fingerprint($cert, 'sha256'); | |
die "got empty fingerprint" if !defined($fp) || ($fp eq ''); | |
return $fp; | |
} | |
################################################################################ | |
# get hostname for this node | |
my $hostname = PVE::INotify::read_file("hostname"); | |
# obtain ticket and csrf token for the root user | |
my $ticket = PVE::AccessControl::assemble_ticket('root@pam'); | |
my $csrftoken = PVE::AccessControl::assemble_csrf_prevention_token('root@pam'); | |
# get cert fingerprint for this node | |
my $local_fingerprint = get_local_cert_fingerprint($hostname); | |
if ($phase eq 'pre-start') { | |
print "$vmid is starting, doing preparations.\n"; | |
# open an API connection to proxmox using our ticket/token/fingerprint | |
my $conn = PVE::APIClient::LWP->new( | |
ticket => $ticket, | |
csrftoken => $csrftoken, | |
host => $hostname, | |
cached_fingerprints => { | |
$local_fingerprint => 1, | |
}); | |
# read config data for vm | |
my $api_path = "/nodes/$hostname/qemu/${vmid}/config"; | |
my $vm_config = $conn->get($api_path); | |
# overwrite the existing user-data with our template | |
copy($tmpl, $genfile) or die "Copy failed: $!"; | |
# open the config and append our instance-specific data | |
open(my $fh, '>>', $genfile) or die "Could not open file '$genfile' $!"; | |
say $fh "fqdn: " . lc($vm_config->{name}) . lc($domainsuffix); | |
close $fh; | |
print "$vmid preparations complete.\n"; | |
} | |
exit(0); |
This file contains hidden or 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
#cloud-config | |
manage_etc_hosts: true | |
password: $5$TUPT4znQ$lOYy4APH6ejrPoXsftkCUoxmRL43YtUmu93iyx6aJ1A | |
ssh_authorized_keys: | |
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGHWf9A33GIRfj/37IPhYnFn7bhdbo9dVhfKhP702VmV ibutsu | |
chpasswd: | |
expire: False | |
users: | |
- default | |
package_upgrade: true | |
bootcmd: | |
- [ sh, -c, echo "Generating hosts file template..." ] | |
- | | |
#!/bin/sh | |
(sleep 5; | |
TMPL="/etc/cloud/templates/hosts.debian.tmpl" | |
TMP="/run/hoststmp" | |
LOCALIPS=$(hostname -I) | |
for ip in ${LOCALIPS:-"127.0.1.1"} | |
do | |
echo "Discovered $ip" | |
if [ "$ip" != "${ip#*[0-9].[0-9]}" ]; then | |
echo "Adding IPv4 address $ip" | |
echo "$ip {{fqdn}} {{hostname}}" >> "$TMP.ipv4" | |
continue | |
elif [ "$ip" != "${ip#*:[0-9a-fA-F]}" ]; then | |
echo "Adding IPv6 address $ip" | |
echo "$ip {{fqdn}} {{hostname}}" >> "$TMP.ipv6" | |
continue | |
else | |
echo "Unrecognized IP format '$ip'" | |
continue | |
fi | |
done | |
if [ -f "$TMP.ipv6" ] | |
then | |
{ cat "$TMPL.begin"; cat "$TMP.ipv4"; cat "$TMPL.mid"; cat "$TMP.ipv6"; cat "$TMPL.end"; } > $TMPL | |
rm -f "$TMP.ipv4" "$TMP.ipv6" | |
else | |
{ cat "$TMPL.begin"; cat "$TMP.ipv4"; cat "$TMPL.mid"; cat "$TMPL.end"; } > $TMPL | |
rm -f "$TMP.ipv4" | |
fi) | |
- [ sh, -c, echo "Done." ] |
This file contains hidden or 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
#/bin/sh | |
CLOUDINITPATH="/var/cloudinit/" | |
CLOUDINITVOL="cloudinit" | |
if [ -z "$1" ] | |
then | |
read -p "Enter the source VM ID: " VMIDSRC | |
else | |
VMIDSRC="$1" | |
fi | |
if [ -z "$2" ] | |
then | |
read -p "Enter the destination VM ID: " VMIDDEST | |
else | |
VMIDDEST="$2" | |
fi | |
if [ -z "$3" ] | |
then | |
read -p "Enter the destination VM name: " VMNAMEDEST | |
else | |
VMNAMEDEST="$3" | |
fi | |
CLONECMD=('qm' 'clone' "$VMIDSRC" "$VMIDDEST" '--name' "$VMNAMEDEST") | |
REGENCMD=("${CLOUDINITPATH}snippets/regenerate-cloud-init-data.pl" "$VMIDDEST" 'pre-start') | |
CICSTCMD=('qm' 'set' "$VMIDDEST" '--cicustom' "user=$CLOUDINITVOL:snippets/vm-$VMIDDEST-userconfig.yaml") | |
"${CLONECMD[@]}" | |
"${REGENCMD[@]}" > /dev/null | |
"${CICSTCMD[@]}" |
This file contains hidden or 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
#/bin/sh | |
CLOUDINITPATH="/var/cloudinit/" | |
if [ -z "$1" ] | |
then | |
read -p "Enter the VM ID: " VMID | |
else | |
VMID="$1" | |
fi | |
USERCFG="${CLOUDINITPATH}snippets/vm-$VMID-userconfig.yaml" | |
STATUSCMD=('qm' 'status' "$VMID") | |
STOPCMD=('qm' 'stop' "$VMID") | |
DESTROYCMD=('qm' 'destroy' "$VMID" '--purge' "${2:-'false'}") | |
STATUS=$("${STATUSCMD[@]}") | |
if [ "$STATUS" != "status: stopped" ] | |
then | |
"${STOPCMD[@]}" | |
fi | |
"${DESTROYCMD[@]}" | |
if [ -f "$USERCFG" ] | |
then | |
rm -f "$USERCFG" | |
fi |
This file contains hidden or 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
## template:jinja | |
# Your system has configured 'manage_etc_hosts' as True. | |
# As a result, if you wish for changes to this file to persist | |
# then you will need to either | |
# a.) make changes to the master file in /etc/cloud/templates/hosts.debian.tmpl | |
# b.) change or remove the value of 'manage_etc_hosts' in | |
# /etc/cloud/cloud.cfg or cloud-config from user-data | |
# |
This file contains hidden or 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
127.0.0.1 localhost | |
# The following lines are desirable for IPv6 capable hosts |
This file contains hidden or 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
::1 ip6-localhost ip6-loopback | |
fe00::0 ip6-localnet | |
ff00::0 ip6-mcastprefix | |
ff02::1 ip6-allnodes | |
ff02::2 ip6-allrouters | |
ff02::3 ip6-allhosts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment