Skip to content

Commit 970c8e8

Browse files
committed
Add cloud-init network snippet to avoid NIC rename
Introduce setup_cloud_init_network_no_rename to generate a netplan snippet that matches the VM interface by MAC (avoiding ens18 -> eth0 renames) and install it as a Proxmox snippet. The function validates IP/gateway, selects an active snippets storage, writes a YAML network config (static IP, gateway, nameservers, optional search domain), preserves existing cicustom entries, sets the VM's cicustom to include the new snippet, and updates cloud-init. Also update vm/ubuntu2604-vm.sh to call setup_cloud_init with clearer formatting and invoke the new helper when CLOUDINIT_NETWORK_MODE is set to static.
1 parent 335b394 commit 970c8e8

2 files changed

Lines changed: 134 additions & 1 deletion

File tree

misc/cloud-init.func

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,120 @@ function regenerate_cloud_init() {
582582
fi
583583
}
584584

585+
# ------------------------------------------------------------------------------
586+
# Creates a custom Cloud-Init network configuration without renaming the NIC.
587+
#
588+
# Workaround for Ubuntu 26.04 / cloud-init 26.1 / netplan 1.2:
589+
# Prevents the failing ens18 -> eth0 rename by matching the interface by MAC only.
590+
#
591+
# Parameters:
592+
# $1 - VMID
593+
# $2 - MAC address
594+
# $3 - Static IP in CIDR format
595+
# $4 - Gateway
596+
# $5 - Space-separated DNS servers
597+
# $6 - Search domain
598+
#
599+
# Optional:
600+
# CLOUDINIT_SNIPPET_STORAGE - Proxmox storage supporting snippets
601+
# ------------------------------------------------------------------------------
602+
function setup_cloud_init_network_no_rename() {
603+
local vmid="$1"
604+
local mac="$2"
605+
local static_ip="$3"
606+
local gateway="$4"
607+
local nameservers="${5:-$CLOUDINIT_DNS_SERVERS}"
608+
local search_domain="${6:-$CLOUDINIT_SEARCH_DOMAIN}"
609+
610+
local snippet_storage="${CLOUDINIT_SNIPPET_STORAGE:-}"
611+
local snippet_name="vm-${vmid}-network.yaml"
612+
local snippet_volid
613+
local snippet_path
614+
local existing_cicustom
615+
local dns
616+
617+
if ! validate_ip_cidr "$static_ip"; then
618+
_ci_msg_error "Invalid static IP format: $static_ip"
619+
return 1
620+
fi
621+
622+
if ! validate_ip "$gateway"; then
623+
_ci_msg_error "Invalid gateway format: $gateway"
624+
return 1
625+
fi
626+
627+
if [[ -z "$snippet_storage" ]]; then
628+
snippet_storage="$(
629+
pvesm status -content snippets 2>/dev/null |
630+
awk 'NR > 1 && $3 == "active" {print $1; exit}'
631+
)"
632+
fi
633+
634+
if [[ -z "$snippet_storage" ]]; then
635+
_ci_msg_error "No active Proxmox storage supporting snippets was found"
636+
return 1
637+
fi
638+
639+
snippet_volid="${snippet_storage}:snippets/${snippet_name}"
640+
snippet_path="$(pvesm path "$snippet_volid")"
641+
642+
mkdir -p "$(dirname "$snippet_path")"
643+
644+
{
645+
cat <<EOF
646+
version: 2
647+
ethernets:
648+
primary:
649+
match:
650+
macaddress: "${mac,,}"
651+
dhcp4: false
652+
addresses:
653+
- "${static_ip}"
654+
routes:
655+
- to: default
656+
via: "${gateway}"
657+
nameservers:
658+
addresses:
659+
EOF
660+
661+
for dns in $nameservers; do
662+
printf ' - "%s"\n' "$dns"
663+
done
664+
665+
if [[ -n "$search_domain" ]]; then
666+
cat <<EOF
667+
search:
668+
- "${search_domain}"
669+
EOF
670+
fi
671+
} >"$snippet_path"
672+
673+
chmod 600 "$snippet_path"
674+
675+
# Preserve existing custom user/vendor/meta configuration.
676+
existing_cicustom="$(
677+
qm config "$vmid" |
678+
sed -n 's/^cicustom: //p' |
679+
tr ',' '\n' |
680+
grep -v '^network=' |
681+
paste -sd, - || true
682+
)"
683+
684+
if [[ -n "$existing_cicustom" ]]; then
685+
existing_cicustom+=","
686+
fi
687+
688+
qm set "$vmid" \
689+
--cicustom "${existing_cicustom}network=${snippet_volid}" \
690+
>/dev/null
691+
692+
qm cloudinit update "$vmid" >/dev/null
693+
694+
export CLOUDINIT_NETWORK_SNIPPET="$snippet_volid"
695+
696+
_ci_msg_ok "Configured Cloud-Init network without interface renaming"
697+
}
698+
585699
# ------------------------------------------------------------------------------
586700
# get_vm_ip - Get VM IP address via qemu-guest-agent
587701
# ------------------------------------------------------------------------------

vm/ubuntu2604-vm.sh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,26 @@ msg_info "Resizing disk to $DISK_SIZE"
158158
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
159159

160160
if [ "$USE_CLOUD_INIT" = "yes" ] && declare -f setup_cloud_init >/dev/null 2>&1; then
161-
setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes" "${CLOUDINIT_USER:-ubuntu}" "${CLOUDINIT_NETWORK_MODE:-dhcp}" "${CLOUDINIT_IP:-}" "${CLOUDINIT_GW:-}" "${CLOUDINIT_DNS:-${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}}"
161+
setup_cloud_init \
162+
"$VMID" \
163+
"$STORAGE" \
164+
"$HN" \
165+
"yes" \
166+
"${CLOUDINIT_USER:-ubuntu}" \
167+
"${CLOUDINIT_NETWORK_MODE:-dhcp}" \
168+
"${CLOUDINIT_IP:-}" \
169+
"${CLOUDINIT_GW:-}" \
170+
"${CLOUDINIT_DNS:-${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}}"
171+
172+
if [[ "${CLOUDINIT_NETWORK_MODE:-dhcp}" == "static" ]]; then
173+
setup_cloud_init_network_no_rename \
174+
"$VMID" \
175+
"$MAC" \
176+
"$CLOUDINIT_IP" \
177+
"$CLOUDINIT_GW" \
178+
"${CLOUDINIT_DNS:-${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}}" \
179+
"${CLOUDINIT_SEARCH_DOMAIN:-local}"
180+
fi
162181
fi
163182

164183
msg_ok "Created a Ubuntu 26.04 VM ${CL}${BL}(${HN})"

0 commit comments

Comments
 (0)