Files
Myasnikov Daniil 0f3d2fa3a6 fix(vm-instance): emit empty disk object so KubeVirt accepts disks without bus
When a disk entry has no bus set (the schema default), the previous
template rendered `disk:` with no value — YAML parses that as
`disk: null` and KubeVirt's virtualmachines-mutator webhook denies the
request with: "spec.template.spec.domain.devices.disks.disk in body
must be of type object: null".

Restructure the disk loop so the disk/cdrom value is always a valid
object: `disk: {}` when bus is empty, `disk: {bus: <x>}` when set.
Mirrors how `cloudinitdisk` already does it in the same template.

Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
2026-05-13 14:48:50 +05:00

130 lines
4.8 KiB
YAML

{{- if and .Values.instanceType (not (lookup "instancetype.kubevirt.io/v1beta1" "VirtualMachineClusterInstancetype" "" .Values.instanceType)) }}
{{- fail (printf "Specified instanceType does not exist in the cluster: %s" .Values.instanceType) }}
{{- end }}
{{- if and .Values.instanceProfile (not (lookup "instancetype.kubevirt.io/v1beta1" "VirtualMachineClusterPreference" "" .Values.instanceProfile)) }}
{{- fail (printf "Specified instanceProfile does not exist in the cluster: %s" .Values.instanceProfile) }}
{{- end }}
{{- if and (not .Values.instanceType) (not (and .Values.resources .Values.resources.cpu .Values.resources.sockets .Values.resources.memory)) }}
{{- fail "Either instanceType or resources (cpu, sockets, memory) must be specified" }}
{{- end }}
{{- $networks := .Values.networks | default .Values.subnets }}
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: {{ include "virtual-machine.fullname" . }}
labels:
{{- include "virtual-machine.labels" . | nindent 4 }}
spec:
{{- if hasKey .Values "runStrategy" }}
runStrategy: {{ .Values.runStrategy }}
{{- else }}
runStrategy: {{ ternary "Always" "Halted" (.Values.running | default true) }}
{{- end }}
{{- with .Values.instanceType }}
instancetype:
kind: VirtualMachineClusterInstancetype
name: {{ . }}
{{- end }}
{{- with .Values.instanceProfile }}
preference:
kind: VirtualMachineClusterPreference
name: {{ . }}
{{- end }}
template:
metadata:
annotations:
kubevirt.io/allow-pod-bridge-network-live-migration: "true"
{{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }}
{{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }}
{{- if $ovnIP }}
ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }}
ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }}
{{- end }}
labels:
{{- include "virtual-machine.labels" . | nindent 8 }}
spec:
domain:
{{- $domainRes := include "virtual-machine.domainResources" . | fromJson -}}
{{- with $domainRes.cpu }}
cpu: {{- . | toYaml | nindent 10 }}
{{- end }}
{{- with $domainRes.resources }}
resources: {{- . | toYaml | nindent 10 }}
{{- end }}
firmware:
uuid: {{ include "virtual-machine.stableUuid" . }}
devices:
{{- if .Values.gpus }}
gpus:
{{- range $i, $gpu := .Values.gpus }}
- name: gpu{{ add $i 1 }}
deviceName: {{ $gpu.name }}
{{- end }}
{{- end }}
disks:
{{- range $i, $disk := .Values.disks }}
- name: disk-{{ $disk.name }}
{{- $dv := lookup "cdi.kubevirt.io/v1beta1" "DataVolume" $.Release.Namespace (printf "vm-disk-%s" $disk.name) }}
{{- if $dv }}
{{- $isOptical := and (hasKey $dv.metadata.annotations "vm-disk.cozystack.io/optical") (eq (index $dv.metadata.annotations "vm-disk.cozystack.io/optical") "true") }}
{{- $deviceKey := ternary "cdrom" "disk" $isOptical }}
{{- if $disk.bus }}
{{ $deviceKey }}:
bus: {{ $disk.bus }}
{{- else }}
{{ $deviceKey }}: {}
{{- end }}
bootOrder: {{ add $i 1 }}
{{- else }}
{{- fail (printf "Specified disk not exists in cluster: %s" .name) }}
{{- end }}
{{- end }}
{{- if or .Values.cloudInit .Values.sshKeys }}
- name: cloudinitdisk
disk: {}
{{- end }}
interfaces:
- name: default
bridge: {}
{{- range $i, $net := $networks }}
- name: {{ $net.name }}
bridge: {}
{{- end }}
machine:
type: ""
{{- with .Values.sshKeys }}
accessCredentials:
- sshPublicKey:
source:
secret:
secretName: {{ include "virtual-machine.fullname" $ }}-ssh-keys
propagationMethod:
# keys will be injected into metadata part of cloud-init disk
noCloud: {}
{{- end }}
terminationGracePeriodSeconds: 30
{{- include "virtual-machine.nodeAffinity" . | nindent 6 }}
volumes:
{{- range .Values.disks }}
- name: disk-{{ .name }}
dataVolume:
name: vm-disk-{{ .name }}
{{- end }}
{{- if or .Values.cloudInit .Values.sshKeys }}
- name: cloudinitdisk
cloudInitNoCloud:
secretRef:
name: {{ include "virtual-machine.fullname" . }}-cloud-init
{{- end }}
networks:
- name: default
pod: {}
{{- range $i, $net := $networks }}
- name: {{ $net.name }}
multus:
networkName: {{ $.Release.Namespace }}/{{ $net.name }}
{{- end }}