From 261ce4278f6a2ff566c62033fd6f71073e40158a Mon Sep 17 00:00:00 2001 From: Denis Seleznev Date: Tue, 8 Apr 2025 02:28:41 +0200 Subject: [PATCH] Add a setting to VMs that allows users to trigger cloud-init full reconfiguration. Changing `cloudInitSeed` will trigger cloud-init reinitialization, including ssh keys update and static network config refresh. Signed-off-by: Denis Seleznev --- packages/apps/virtual-machine/README.md | 1 + .../virtual-machine/templates/_helpers.tpl | 20 +++++++++++++++++++ .../apps/virtual-machine/templates/vm.yaml | 2 ++ .../apps/virtual-machine/values.schema.json | 5 +++++ packages/apps/virtual-machine/values.yaml | 9 +++++++++ packages/apps/vm-instance/README.md | 1 + .../apps/vm-instance/templates/_helpers.tpl | 20 +++++++++++++++++++ packages/apps/vm-instance/templates/vm.yaml | 2 ++ packages/apps/vm-instance/values.schema.json | 5 +++++ packages/apps/vm-instance/values.yaml | 9 +++++++++ 10 files changed, 74 insertions(+) diff --git a/packages/apps/virtual-machine/README.md b/packages/apps/virtual-machine/README.md index 29b22401..fc049f9c 100644 --- a/packages/apps/virtual-machine/README.md +++ b/packages/apps/virtual-machine/README.md @@ -52,6 +52,7 @@ virtctl ssh @ | `sshKeys` | List of SSH public keys for authentication. Can be a single key or a list of keys. | `[]` | | `cloudInit` | cloud-init user data config. See cloud-init documentation for more details. | `#cloud-config ` | +| `cloudInitSeed` | A seed string to generate an SMBIOS UUID for the VM. | `""` | ## U Series diff --git a/packages/apps/virtual-machine/templates/_helpers.tpl b/packages/apps/virtual-machine/templates/_helpers.tpl index 671b8934..f3ade695 100644 --- a/packages/apps/virtual-machine/templates/_helpers.tpl +++ b/packages/apps/virtual-machine/templates/_helpers.tpl @@ -49,3 +49,23 @@ Selector labels app.kubernetes.io/name: {{ include "virtual-machine.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} + +{{/* +Generate a stable UUID for cloud-init re-initialization upon upgrade. +*/}} +{{- define "virtual-machine.stableUuid" -}} +{{- $source := printf "%s-%s-%s" .Release.Namespace (include "virtual-machine.fullname" .) .Values.cloudInitSeed }} +{{- $hash := sha256sum $source }} +{{- $uuid := printf "%s-%s-4%s-9%s-%s" (substr 0 8 $hash) (substr 8 12 $hash) (substr 13 16 $hash) (substr 17 20 $hash) (substr 20 32 $hash) }} +{{- if eq .Values.cloudInitSeed "" }} + {{- /* Try to save previous uuid to not trigger full cloud-init again if user decided to remove the seed. */}} + {{- $vmResource := lookup "kubevirt.io/v1" "VirtualMachine" .Release.Namespace (include "virtual-machine.fullname" .) -}} + {{- if $vmResource }} + {{- $existingUuid := $vmResource | dig "spec" "template" "spec" "domain" "firmware" "uuid" "" }} + {{- if $existingUuid }} + {{- $uuid = $existingUuid }} + {{- end }} + {{- end }} +{{- end }} +{{- $uuid }} +{{- end }} diff --git a/packages/apps/virtual-machine/templates/vm.yaml b/packages/apps/virtual-machine/templates/vm.yaml index d952483e..853a7891 100644 --- a/packages/apps/virtual-machine/templates/vm.yaml +++ b/packages/apps/virtual-machine/templates/vm.yaml @@ -68,6 +68,8 @@ spec: requests: memory: {{ .Values.resources.memory | quote }} {{- end }} + firmware: + uuid: {{ include "virtual-machine.stableUuid" . }} devices: disks: - disk: diff --git a/packages/apps/virtual-machine/values.schema.json b/packages/apps/virtual-machine/values.schema.json index 02b60675..070c18b8 100644 --- a/packages/apps/virtual-machine/values.schema.json +++ b/packages/apps/virtual-machine/values.schema.json @@ -191,6 +191,11 @@ "type": "string", "description": "cloud-init user data config. See cloud-init documentation for more details.", "default": "#cloud-config\n" + }, + "cloudInitSeed": { + "type": "string", + "description": "A seed string to generate an SMBIOS UUID for the VM.", + "default": "" } } } diff --git a/packages/apps/virtual-machine/values.yaml b/packages/apps/virtual-machine/values.yaml index 0d651378..146cc167 100644 --- a/packages/apps/virtual-machine/values.yaml +++ b/packages/apps/virtual-machine/values.yaml @@ -51,3 +51,12 @@ sshKeys: [] ## cloudInit: | #cloud-config + +## @param cloudInitSeed A seed string to generate an SMBIOS UUID for the VM. +cloudInitSeed: "" +## Change it to any new value to force a full cloud-init reconfiguration. Change it when you want to apply +## to an existing VM settings that are usually written only once, like new SSH keys or new network configuration. +## An empty value does nothing (and the existing UUID is not reverted). Please note that changing this value +## does not trigger a VM restart. You must perform the restart separately. +## Example: +## cloudInitSeed: "upd1" diff --git a/packages/apps/vm-instance/README.md b/packages/apps/vm-instance/README.md index 53d9f614..6a361dcb 100644 --- a/packages/apps/vm-instance/README.md +++ b/packages/apps/vm-instance/README.md @@ -50,6 +50,7 @@ virtctl ssh @ | `sshKeys` | List of SSH public keys for authentication. Can be a single key or a list of keys. | `[]` | | `cloudInit` | cloud-init user data config. See cloud-init documentation for more details. | `#cloud-config ` | +| `cloudInitSeed` | A seed string to generate an SMBIOS UUID for the VM. | `""` | ## U Series diff --git a/packages/apps/vm-instance/templates/_helpers.tpl b/packages/apps/vm-instance/templates/_helpers.tpl index 671b8934..f3ade695 100644 --- a/packages/apps/vm-instance/templates/_helpers.tpl +++ b/packages/apps/vm-instance/templates/_helpers.tpl @@ -49,3 +49,23 @@ Selector labels app.kubernetes.io/name: {{ include "virtual-machine.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} + +{{/* +Generate a stable UUID for cloud-init re-initialization upon upgrade. +*/}} +{{- define "virtual-machine.stableUuid" -}} +{{- $source := printf "%s-%s-%s" .Release.Namespace (include "virtual-machine.fullname" .) .Values.cloudInitSeed }} +{{- $hash := sha256sum $source }} +{{- $uuid := printf "%s-%s-4%s-9%s-%s" (substr 0 8 $hash) (substr 8 12 $hash) (substr 13 16 $hash) (substr 17 20 $hash) (substr 20 32 $hash) }} +{{- if eq .Values.cloudInitSeed "" }} + {{- /* Try to save previous uuid to not trigger full cloud-init again if user decided to remove the seed. */}} + {{- $vmResource := lookup "kubevirt.io/v1" "VirtualMachine" .Release.Namespace (include "virtual-machine.fullname" .) -}} + {{- if $vmResource }} + {{- $existingUuid := $vmResource | dig "spec" "template" "spec" "domain" "firmware" "uuid" "" }} + {{- if $existingUuid }} + {{- $uuid = $existingUuid }} + {{- end }} + {{- end }} +{{- end }} +{{- $uuid }} +{{- end }} diff --git a/packages/apps/vm-instance/templates/vm.yaml b/packages/apps/vm-instance/templates/vm.yaml index 843ae221..a82b0b03 100644 --- a/packages/apps/vm-instance/templates/vm.yaml +++ b/packages/apps/vm-instance/templates/vm.yaml @@ -40,6 +40,8 @@ spec: requests: memory: {{ .Values.resources.memory | quote }} {{- end }} + firmware: + uuid: {{ include "virtual-machine.stableUuid" . }} devices: disks: {{- range $i, $disk := .Values.disks }} diff --git a/packages/apps/vm-instance/values.schema.json b/packages/apps/vm-instance/values.schema.json index 40560861..f0cc083d 100644 --- a/packages/apps/vm-instance/values.schema.json +++ b/packages/apps/vm-instance/values.schema.json @@ -172,6 +172,11 @@ "type": "string", "description": "cloud-init user data config. See cloud-init documentation for more details.", "default": "#cloud-config\n" + }, + "cloudInitSeed": { + "type": "string", + "description": "A seed string to generate an SMBIOS UUID for the VM.", + "default": "" } } } diff --git a/packages/apps/vm-instance/values.yaml b/packages/apps/vm-instance/values.yaml index 418ba7e8..dff83abf 100644 --- a/packages/apps/vm-instance/values.yaml +++ b/packages/apps/vm-instance/values.yaml @@ -49,3 +49,12 @@ sshKeys: [] ## cloudInit: | #cloud-config + +## @param cloudInitSeed A seed string to generate an SMBIOS UUID for the VM. +cloudInitSeed: "" +## Change it to any new value to force a full cloud-init reconfiguration. Change it when you want to apply +## to an existing VM settings that are usually written only once, like new SSH keys or new network configuration. +## An empty value does nothing (and the existing UUID is not reverted). Please note that changing this value +## does not trigger a VM restart. You must perform the restart separately. +## Example: +## cloudInitSeed: "upd1"