# 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`.

## Create a VirtualMachineInstancePreset

You can describe a `VirtualMachineInstancePreset` in a YAML file. For example, the `vmi-preset.yaml` file below describes a `VirtualMachineInstancePreset` that requests a `VirtualMachineInstance` be created with a resource request for 64M of RAM.

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstancePreset
    metadata:
      name: small-qemu
    spec:
      selector:
        matchLabels:
          kubevirt.io/size: small
      domain:
        resources:
          requests:
            memory: 64M
```

* Create a `VirtualMachineInstancePreset` based on that YAML file:

```
    kubectl create -f vmipreset.yaml
```

### Required Fields

As with most Kubernetes resources, a `VirtualMachineInstancePreset` requires `apiVersion`, `kind` and `metadata` fields.

Additionally `VirtualMachineInstancePresets` also need a `spec` section. While not technically required to satisfy syntax, it is strongly recommended to include a `Selector` in the `spec` section, otherwise a `VirtualMachineInstancePreset` will match all `VirtualMachineInstances` in a namespace.

### VirtualMachine Selector

KubeVirt uses Kubernetes `Labels` and `Selectors` to determine which `VirtualMachineInstancePresets` apply to a given `VirtualMachineInstance`, similarly to how `PodPresets` work in Kubernetes. If a setting from a `VirtualMachineInstancePreset` is applied to a `VirtualMachineInstance`, the `VirtualMachineInstance` will be marked with an Annotation upon completion.

Any domain structure can be listed in the `spec` of a `VirtualMachineInstancePreset`, e.g. Clock, Features, Memory, CPU, or Devices such as network interfaces. All elements of the `spec` section of a `VirtualMachineInstancePreset` will be applied to the `VirtualMachineInstance`.

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.

Any valid `Label` can be matched against, but it is suggested that a general rule of thumb is to use os/shortname, e.g. `kubevirt.io/os: rhel7`.

## Updating a VirtualMachineInstancePreset

If a `VirtualMachineInstancePreset` is modified, changes will *not* be applied to existing `VirtualMachineInstances`. This applies to both the `Selector` indicating which `VirtualMachineInstances` should be matched, and also the `Domain` section which lists the settings that should be applied to a `VirtualMachine`.

## 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.

In the event that there is a difference between the `Domains` of a `VirtualMachineInstance` and `VirtualMachineInstancePreset`, KubeVirt will create an `Event`. `kubectl get events` can be used to show all `Events`. For example:

```
    $ kubectl get events
    ....
    Events:
      FirstSeen                         LastSeen                        Count From                              SubobjectPath                Reason    Message
      2m          2m           1         myvmi.1515bbb8d397f258                       VirtualMachineInstance                                     Warning   Conflict                  virtualmachineinstance-preset-controller   Unable to apply VirtualMachineInstancePreset 'example-preset': spec.cpu: &{6} != &{4}
```

## 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:

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstancePreset
    metadata:
      name: example-preset
      selector:
        matchLabels:
          kubevirt.io/os: win10
      ...
```

would match any `VirtualMachineInstance` in the same namespace with a `Label` of `flavor: foo`. For example:

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    version: v1
    metadata:
      name: myvmi
      labels:
        kubevirt.io/os: win10
      ...
```

## Conflicts

When multiple `VirtualMachineInstancePresets` match a particular `VirtualMachineInstance`, if they specify the same settings within a Domain, those settings must match. If two `VirtualMachineInstancePresets` have conflicting settings (e.g. for the number of CPU cores requested), an error will occur, and the `VirtualMachineInstance` will enter the `Failed` state, and a `Warning` event will be emitted explaining which settings of which `VirtualMachineInstancePresets` were problematic.

## Matching Multiple `VirtualMachineInstances`

The main use case for `VirtualMachineInstancePresets` is to create re-usable settings that can be applied across various machines. Multiple methods are available to match the labels of a `VirtualMachineInstance` using selectors.

* matchLabels: Each `VirtualMachineInstance` can use a specific label shared by all

  instances. \* matchExpressions: Logical operators for sets can be used to match multiple

  labels.

Using matchLabels, the label used in the `VirtualMachineInstancePreset` must match one of the labels of the `VirtualMachineInstance`:

```
    selector:
      matchLabels:
        kubevirt.io/memory: large
```

would match

```
    metadata:
      labels:
        kubevirt.io/memory: large
        kubevirt.io/os: win10
```

or

```
    metadata:
      labels:
        kubevirt.io/memory: large
        kubevirt.io/os: fedora27
```

Using matchExpressions allows for matching multiple labels of `VirtualMachineInstances` without needing to explicity list a label.

```
    selector:
      matchExpressions:
        - {key: kubevirt.io/os, operator: In, values: [fedora27, fedora26]}
```

would match both:

```
    metadata:
      labels:
        kubevirt.io/os: fedora26

    metadata:
      labels:
        kubevirt.io/os: fedora27
```

The Kubernetes [documentation](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) has a detailed explanation. Examples are provided below.

## 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:

```
    kind: VirtualMachineInstance
    version: v1
    metadata:
      name: myvmi
      annotations:
        virtualmachineinstancepresets.admission.kubevirt.io/exclude: "true"
      ...
```

## Examples

### Simple `VirtualMachineInstancePreset` Example

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstancePreset
    version: v1alpha3
    metadata:
      name: example-preset
    spec:
      selector:
        matchLabels:
          kubevirt.io/os: win10
      domain:
        features:
          acpi: {}
          apic: {}
          hyperv:
            relaxed: {}
            vapic: {}
            spinlocks:
              spinlocks: 8191
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    version: v1
    metadata:
      name: myvmi
      labels:
        kubevirt.io/os: win10
    spec:
      domain:
        firmware:
          uuid: c8f99fc8-20f5-46c4-85e5-2b841c547cef
```

Once the `VirtualMachineInstancePreset` is applied to the `VirtualMachineInstance`, the resulting resource would look like this:

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      annotations:
        presets.virtualmachineinstances.kubevirt.io/presets-applied: kubevirt.io/v1alpha3
        virtualmachineinstancepreset.kubevirt.io/example-preset: kubevirt.io/v1alpha3
      labels:
        kubevirt.io/os: win10
        kubevirt.io/nodeName: master
      name: myvmi
      namespace: default
    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
```

### Conflict Example

This is an example of a merge conflict. In this case both the `VirtualMachineInstance` and `VirtualMachineInstancePreset` request different number of CPU's.

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstancePreset
    version: v1alpha3
    metadata:
      name: example-preset
    spec:
      selector:
        matchLabels:
          kubevirt.io/flavor: default-features
      domain:
        cpu:
          cores: 4
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    version: v1
    metadata:
      name: myvmi
      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.

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      annotations:
        presets.virtualmachineinstances.kubevirt.io/presets-applied: kubevirt.io/v1alpha3
      generation: 0
      labels:
        kubevirt.io/flavor: default-features
      name: myvmi
      namespace: default
    spec:
      domain:
        cpu:
          cores: 6
        devices: {}
        machine:
          type: ""
        resources: {}
    status: {}
```

Calling `kubectl get events` would have a line like:

```
2m 2m 1 myvmi.1515bbb8d397f258 VirtualMachineInstance Warning Conflict virtualmachineinstance-preset-controller Unable to apply VirtualMachineInstancePreset example-preset: spec.cpu: &{6} != &{4}
```

### Matching Multiple VirtualMachineInstances Using MatchLabels

These `VirtualMachineInstances` have multiple labels, one that is unique and one that is shared.

Note: This example breaks from the convention of using os-shortname as a `Label` for demonstration purposes.

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstancePreset
    metadata:
      name: twelve-cores
    spec:
      selector:
        matchLabels:
          kubevirt.io/cpu: dodecacore
      domain:
        cpu:
          cores: 12
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      name: windows-10
      labels:
        kubevirt.io/os: win10
        kubevirt.io/cpu: dodecacore
    spec:
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      name: windows-7
      labels:
        kubevirt.io/os: win7
        kubevirt.io/cpu: dodecacore
    spec:
      terminationGracePeriodSeconds: 0
```

Adding this `VirtualMachineInstancePreset` and these `VirtualMachineInstances` will result in:

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      annotations:
        presets.virtualmachineinstances.kubevirt.io/presets-applied: kubevirt.io/v1alpha3
        virtualmachineinstancepreset.kubevirt.io/twelve-cores: kubevirt.io/v1alpha3
      labels:
        kubevirt.io/cpu: dodecacore
        kubevirt.io/os: win10
      name: windows-10
    spec:
      domain:
        cpu:
          cores: 12
        devices: {}
        resources:
          requests:
            memory: 4Gi
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      annotations:
        presets.virtualmachineinstances.kubevirt.io/presets-applied: kubevirt.io/v1alpha3
        virtualmachineinstancepreset.kubevirt.io/twelve-cores: kubevirt.io/v1alpha3
      labels:
        kubevirt.io/cpu: dodecacore
        kubevirt.io/os: win7
      name: windows-7
    spec:
      domain:
        cpu:
          cores: 12
        devices: {}
        resources:
          requests:
            memory: 4Gi
      terminationGracePeriodSeconds: 0
```

### Matching Multiple VirtualMachineInstances Using MatchExpressions

This `VirtualMachineInstancePreset` has a matchExpression that will match two labels: `kubevirt.io/os: win10` and `kubevirt.io/os: win7`.

```
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstancePreset
    metadata:
      name: windows-vmis
    spec:
      selector:
        matchExpressions:
          - {key: kubevirt.io/os, operator: In, values: [win10, win7]}
      domain:
        resources:
          requests:
            memory: 128M
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      name: smallvmi
      labels:
        kubevirt.io/os: win10
    spec:
      terminationGracePeriodSeconds: 60
    ---
    apiVersion: kubevirt.io/v1alpha3
    kind: VirtualMachineInstance
    metadata:
      name: largevmi
      labels:
        kubevirt.io/os: win7
    spec:
      terminationGracePeriodSeconds: 120
```

Applying the preset to both VM's will result in:

```
    apiVersion: v1
    items:
    - apiVersion: kubevirt.io/v1alpha3
      kind: VirtualMachineInstance
      metadata:
        annotations:
          presets.virtualmachineinstances.kubevirt.io/presets-applied: kubevirt.io/v1alpha3
          virtualmachineinstancepreset.kubevirt.io/windows-vmis: kubevirt.io/v1alpha3
        labels:
          kubevirt.io/os: win7
        name: largevmi
      spec:
        domain:
          resources:
            requests:
              memory: 128M
        terminationGracePeriodSeconds: 120
    - apiVersion: kubevirt.io/v1alpha3
      kind: VirtualMachineInstance
      metadata:
        annotations:
          presets.virtualmachineinstances.kubevirt.io/presets-applied: kubevirt.io/v1alpha3
          virtualmachineinstancepreset.kubevirt.io/windows-vmis: kubevirt.io/v1alpha3
        labels:
          kubevirt.io/os: win10
        name: smallvmi
      spec:
        domain:
          resources:
            requests:
              memory: 128M
        terminationGracePeriodSeconds: 60
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kubevirtlegacy.gitbook.io/user-guide/docs/virtual_machines/presets.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
