Project: KubeVirt (App Definition and Development / Application Definition & Image Build)
File: vm-presets.md

Virtual Machine Presets ============================= `VirtualMachineInstancePresets` are an extension to general `VirtualMachineInstance` configuration behaving much like `PodPresets` from Kubernetes. When a `VirtualMachineInstance` is created, any applicable `VirtualMachineInstancePresets` will be applied to the existing spec for the `VirtualMachineInstance`. This allows for re-use of common settings that should apply to multiple `VirtualMachineInstances`. Implementation `VirtualMachineInstancePresets` are applied early while processing `VirtualMachineInstance` resources. This means the `VirtualMachineInstance` resource is modified before it is processed by any other component of KubeVirt. Once a `VirtualMachineInstancePreset` is successfully applied to a `VirtualMachineInstance`, the `VirtualMachineInstance` will be marked with an annotation to indicate that it was applied. If a conflict occurs while a `VirtualMachineInstancePreset` is being applied that portion of the `VirtualMachineInstancePreset` will be skipped. Usage KubeVirt uses Kubernetes `Labels` and `Selectors` to determine which `VirtualMachineInstancePresets` apply to any given `VirtualMachineInstance`, similarly to how `PodPresets` work in Kubernetes. The `VirtualMachineInstance` is marked with an Annotation upon successful completion. Any domain structure can be listed in the `spec` of a `VirtualMachineInstancePreset`. e.g. Clock, Features, Memory, CPU, or Devices such network interfaces. All elements of the `spec` section of a `VirtualMachineInstancePreset` will be applied to the `VirtualMachineInstance`. Overrides `VirtualMachineInstancePresets` use a similar conflict resolution strategy to Kubernetes `PodPresets`. If a portion of the domain spec is present in both a `VirtualMachineInstance` and a `VirtualMachineInstancePreset` and both resources have the identical information, then creation of the `VirtualMachineInstance` will continue normally. If however there is a difference between the resources, an Event will be created indicating which `DomainSpec` element of which `VirtualMachineInstancePreset` was overridden. For example: If both the `VirtualMachineInstance` and `VirtualMachineInstancePreset` define a `CPU`, but use a different number of `Cores`, KubeVirt will note the difference. If any settings from the `VirtualMachineInstancePreset` were successfully applied, the `VirtualMachineInstance` will be annotated. Because `VirtualMachineInstancePresets` are implemented within the `virt-controller` pod, log messages associated with resource conflicts will also be reflected there. Creation and Usage `VirtualMachineInstancePresets` are namespaced resources, so should be created in the same namespace as the `VirtualMachineInstances` that will use them: `kubectl create -f <preset>.yaml [--namespace <namespace>]` KubeVirt will determine which `VirtualMachineInstancePresets` apply to a Particular `VirtualMachineInstance` by matching `Labels`. For example: ```yaml kind: VirtualMachineInstancePreset metadata: name: example-preset spec: selector: matchLabels: kubevirt.io/flavor: foo

``` would match any `VirtualMachineInstance` in the same namespace with a `Label` of `kubevirt.io/flavor: foo`. For example: ```yaml kind: VirtualMachineInstance version: v1 metadata: name: myvm labels: kubevirt.io/flavor: foo ... ``` Exclusions Since `VirtualMachineInstancePresets` use `Selectors` that indicate which `VirtualMachineInstances` their settings should apply to, there needs to exist a mechanism by which `VirtualMachineInstances` can opt out of `VirtualMachineInstancePresets` altogether. This is done using an annotation: ```yaml kind: VirtualMachineInstance version: v1 metadata: name: myvm annotations: virtualmachinepresets.admission.kubevirt.io/exclude: "true" ... ``` Examples ============================= Simple `VirtualMachineInstancePreset` Example ```yaml apiVersion: kubevirt.io/v1 kind: VirtualMachineInstancePreset metadata: name: example-preset spec: selector: matchLabels: kubevirt.io/flavor: windows-10 domain: features: acpi: {} apic: {} hyperv: relaxed: {} vapic: {} spinlocks: spinlocks: 8191 apiVersion: kubevirt.io/v1 kind: VirtualMachineInstance version: v1 metadata: name: myvm labels: kubevirt.io/flavor: windows-10 spec: domain: firmware: uuid: c8f99fc8-20f5-46c4-85e5-2b841c547cef ``` Once the `VirtualMachineInstancePreset` is applied to the `VirtualMachineInstance`, the resulting resource would look like this: ```yaml apiVersion: v1 items: apiVersion: kubevirt.io/v1 kind: VirtualMachineInstance metadata: annotations: presets.virtualmachines.kubevirt.io/presets-applied: kubevirt.io/v1 virtualmachinepreset.kubevirt.io/example-preset: kubevirt.io/v1 labels: kubevirt.io/flavor: windows-10 name: myvm namespace: default selfLink: /apis/kubevirt.io/v1/namespaces/default/virtualmachineinstances/myvm spec: domain: devices: {} features: acpi: enabled: true apic: enabled: true hyperv: relaxed: enabled: true spinlocks: enabled: true spinlocks: 8191 vapic: enabled: true firmware: uuid: c8f99fc8-20f5-46c4-85e5-2b841c547cef machine: type: q35 resources: requests: memory: 8Mi status: phase: Scheduling kind: List metadata: resourceVersion: "" selfLink: "" ``` Conflict Example This is an example of a merge conflict. In this case both the `VirtualMachineInstance` and `VirtualMachineInstancePreset` request different number of CPU's. ```yaml apiVersion: kubevirt.io/v1 kind: VirtualMachineInstancePreset metadata: name: example-preset spec: selector: matchLabels: kubevirt.io/flavor: default-features domain: cpu: cores: 4 apiVersion: kubevirt.io/v1 kind: VirtualMachineInstance version: v1 metadata: name: myvm labels: kubevirt.io/flavor: default-features spec: domain: cpu: cores: 6 ``` In this case the `VirtualMachineInstance` Spec will remain unmodified. Use `kubectl get events` to show events. ```yaml apiVersion: v1 items: apiVersion: kubevirt.io/v1 kind: VirtualMachineInstance metadata: annotations: presets.virtualmachines.kubevirt.io/presets-applied: kubevirt.io/v1 clusterName: "" labels: kubevirt.io/flavor: default-features name: myvm namespace: default selfLink: /apis/kubevirt.io/v1/namespaces/default/virtualmachineinstances/myvm spec: domain: cpu: cores: 6 devices: {} features: acpi: enabled: true firmware: uuid: efaaa6e4-0002-44d6-9de1-5526b24615d1 machine: type: q35 resources: requests: memory: 8Mi status: phase: Scheduling kind: List metadata: resourceVersion: "" selfLink: "" ``` Calling `kubectl get events` would have a line like: 2m 2m 1 myvm.1515bbb8d397f258 VirtualMachineInstance Warning Conflict virtualmachine-preset-controller Unable to apply VirtualMachineInstancePreset 'example-preset': spec.cpu: &{6} != &{4}