diff --git a/Taskfile.yaml b/Taskfile.yaml index e193b2b1d7..020d59f4f7 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -165,8 +165,7 @@ tasks: "ports": [ { "containerPort": 2345, "name": "dlv" } ], "readinessProbe": null, "livenessProbe": null, - "command": null, - "args": [] + "command": null }, { "name": "proxy", @@ -215,8 +214,7 @@ tasks: "ports": [ { "containerPort": 2345, "name": "dlv" } ], "readinessProbe": null, "livenessProbe": null, - "command": null, - "args": [] + "command": null }, { "name": "proxy", @@ -265,8 +263,7 @@ tasks: "ports": [ { "containerPort": 2345, "name": "dlv" } ], "readinessProbe": null, "livenessProbe": null, - "command": null, - "args": [] + "command": null }, { "name": "proxy", @@ -283,5 +280,5 @@ tasks: } } }' - kubectl -n d8-virtualization port-forward deploy/vit-api 2345:2345 + kubectl -n d8-virtualization port-forward deploy/virt-api 2345:2345 EOF diff --git a/api/client/examples/cancel-evacuation/go.mod b/api/client/examples/cancel-evacuation/go.mod index 63f821ce75..86339fe572 100644 --- a/api/client/examples/cancel-evacuation/go.mod +++ b/api/client/examples/cancel-evacuation/go.mod @@ -53,8 +53,8 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - kubevirt.io/api v1.3.1 // indirect - kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/api v1.6.2 // indirect + kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 // indirect kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/api/client/examples/cancel-evacuation/go.sum b/api/client/examples/cancel-evacuation/go.sum index d7db165b6a..cf69ab2158 100644 --- a/api/client/examples/cancel-evacuation/go.sum +++ b/api/client/examples/cancel-evacuation/go.sum @@ -372,8 +372,10 @@ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6J k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9/go.mod h1:SDJjLGhbPyayDqAqawcGmVNapBp0KodOQvhKPLVGCQU= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= diff --git a/api/client/examples/list-resources/go.mod b/api/client/examples/list-resources/go.mod index 8251bcd219..9888494628 100644 --- a/api/client/examples/list-resources/go.mod +++ b/api/client/examples/list-resources/go.mod @@ -49,8 +49,8 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - kubevirt.io/api v1.3.1 // indirect - kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/api v1.6.2 // indirect + kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 // indirect kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/api/client/examples/list-resources/go.sum b/api/client/examples/list-resources/go.sum index 3dba2c12dd..2e9bbd8060 100644 --- a/api/client/examples/list-resources/go.sum +++ b/api/client/examples/list-resources/go.sum @@ -365,8 +365,10 @@ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6J k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9/go.mod h1:SDJjLGhbPyayDqAqawcGmVNapBp0KodOQvhKPLVGCQU= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= diff --git a/api/core/v1alpha2/virtual_machine_operation.go b/api/core/v1alpha2/virtual_machine_operation.go index 01a564a9df..6f9234698e 100644 --- a/api/core/v1alpha2/virtual_machine_operation.go +++ b/api/core/v1alpha2/virtual_machine_operation.go @@ -58,12 +58,24 @@ type VirtualMachineOperationSpec struct { // * Effect on `Restart` and `Stop`: operation performs immediately. // * Effect on `Evict` and `Migrate`: enable the AutoConverge feature to force migration via CPU throttling if the `PreferSafe` or `PreferForced` policies are used for live migration. Force *bool `json:"force,omitempty"` + // Evict contains settings for Evict operation. + // +optional + Evict *VirtualMachineOperationEvictSpec `json:"evict,omitempty"` // Restore defines the restore operation. Restore *VirtualMachineOperationRestoreSpec `json:"restore,omitempty"` // Clone defines the clone operation. Clone *VirtualMachineOperationCloneSpec `json:"clone,omitempty"` } +// VirtualMachineOperationEvictSpec defines settings for Evict operation. +type VirtualMachineOperationEvictSpec struct { + // NodeSelector restricts the set of nodes the VM can migrate to. + // Passed to KubeVirt's AddedNodeSelector which complements + // any existing nodeSelector or nodeAffinity on the VM. + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` +} + // VirtualMachineOperationRestoreSpec defines the restore operation. type VirtualMachineOperationRestoreSpec struct { Mode SnapshotOperationMode `json:"mode"` diff --git a/api/core/v1alpha2/zz_generated.deepcopy.go b/api/core/v1alpha2/zz_generated.deepcopy.go index fd1ae399fa..4f0d61f57b 100644 --- a/api/core/v1alpha2/zz_generated.deepcopy.go +++ b/api/core/v1alpha2/zz_generated.deepcopy.go @@ -2621,6 +2621,29 @@ func (in *VirtualMachineOperationCloneSpec) DeepCopy() *VirtualMachineOperationC return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineOperationEvictSpec) DeepCopyInto(out *VirtualMachineOperationEvictSpec) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineOperationEvictSpec. +func (in *VirtualMachineOperationEvictSpec) DeepCopy() *VirtualMachineOperationEvictSpec { + if in == nil { + return nil + } + out := new(VirtualMachineOperationEvictSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineOperationList) DeepCopyInto(out *VirtualMachineOperationList) { *out = *in @@ -2678,6 +2701,11 @@ func (in *VirtualMachineOperationSpec) DeepCopyInto(out *VirtualMachineOperation *out = new(bool) **out = **in } + if in.Evict != nil { + in, out := &in.Evict, &out.Evict + *out = new(VirtualMachineOperationEvictSpec) + (*in).DeepCopyInto(*out) + } if in.Restore != nil { in, out := &in.Restore, &out.Restore *out = new(VirtualMachineOperationRestoreSpec) diff --git a/api/go.mod b/api/go.mod index 79b0495d1e..a4b3951825 100644 --- a/api/go.mod +++ b/api/go.mod @@ -17,7 +17,8 @@ require ( k8s.io/apiextensions-apiserver v0.33.3 k8s.io/apimachinery v0.33.3 k8s.io/client-go v0.33.3 - kubevirt.io/api v1.3.1 + k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 + kubevirt.io/api v1.6.2 sigs.k8s.io/controller-runtime v0.21.0 ) @@ -70,9 +71,8 @@ require ( k8s.io/code-generator v0.33.3 // indirect k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 // indirect kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/controller-tools v0.18.0 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect diff --git a/api/go.sum b/api/go.sum index fd5f073e7c..620d6a5a4a 100644 --- a/api/go.sum +++ b/api/go.sum @@ -570,8 +570,12 @@ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6J k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +kubevirt.io/api v1.6.2 h1:aoqZ4KsbOyDjLnuDw7H9wEgE/YTd/q5BBmYeQjJNizc= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 h1:KTb8wO1Lxj220DX7d2Rdo9xovvlyWWNo3AVm2ua+1nY= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9/go.mod h1:SDJjLGhbPyayDqAqawcGmVNapBp0KodOQvhKPLVGCQU= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= diff --git a/build/components/versions.yml b/build/components/versions.yml index bc56ce54b2..3e32c7103f 100644 --- a/build/components/versions.yml +++ b/build/components/versions.yml @@ -3,7 +3,7 @@ firmware: libvirt: v10.9.0 edk2: stable202411 core: - 3p-kubevirt: v1.3.1-v12n.24 + 3p-kubevirt: v1.6.2-virtualization 3p-containerized-data-importer: v1.60.3-v12n.12 distribution: 2.8.3 package: diff --git a/crds/embedded/virtualmachineinstances.yaml b/crds/embedded/virtualmachineinstances.yaml index b9cc1d5949..b676c9ed3a 100644 --- a/crds/embedded/virtualmachineinstances.yaml +++ b/crds/embedded/virtualmachineinstances.yaml @@ -461,7 +461,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -476,7 +476,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -642,7 +642,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -657,7 +657,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -820,7 +820,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -835,7 +835,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1001,7 +1001,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1016,7 +1016,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1127,9 +1127,12 @@ spec: of a pod. properties: name: - description: Required. + description: |- + Name is this DNS resolver option's name. + Required. type: string value: + description: Value is this DNS resolver option's value. type: string type: object type: array @@ -1447,7 +1450,11 @@ spec: cache: description: |- Cache specifies which kvm disk cache mode should be used. - Supported values are: CacheNone, CacheWriteThrough. + Supported values are: + none: Guest I/O not cached on the host, but may be kept in a disk cache. + writethrough: Guest I/O cached on the host but written through to the physical medium. Slowest but with most guarantees. + writeback: Guest I/O cached on the host. + Defaults to none if the storage supports O_DIRECT, otherwise writethrough. type: string cdrom: description: Attach a volume as a cdrom to the vmi. @@ -1567,12 +1574,24 @@ spec: description: Whether to attach a GPU device to the vmi. items: properties: + claimName: + description: |- + ClaimName needs to be provided from the list vmi.spec.resourceClaims[].name where this + device is allocated + type: string deviceName: + description: DeviceName is the name of the device provisioned + by device-plugins type: string name: description: Name of the GPU device as exposed by a device plugin type: string + requestName: + description: |- + RequestName needs to be provided from resourceClaim.spec.devices.requests[].name where this + device is requested + type: string tag: description: If specified, the virtual network interface address and its tag will be provided to the guest @@ -1601,7 +1620,6 @@ spec: type: object type: object required: - - deviceName - name type: object type: array @@ -1610,19 +1628,28 @@ spec: description: Whether to attach a host device to the vmi. items: properties: + claimName: + description: |- + ClaimName needs to be provided from the list vmi.spec.resourceClaims[].name where this + device is allocated + type: string deviceName: - description: DeviceName is the resource name of the - host device exposed by a device plugin + description: DeviceName is the name of the device provisioned + by device-plugins type: string name: type: string + requestName: + description: |- + RequestName needs to be provided from resourceClaim.spec.devices.requests[].name where this + device is requested + type: string tag: description: If specified, the virtual network interface address and its tag will be provided to the guest via config drive type: string required: - - deviceName - name type: object type: array @@ -1743,9 +1770,8 @@ spec: model: description: |- Interface model. - One of: e1000, e1000e, ne2k_pci, pcnet, rtl8139, virtio. + One of: e1000, e1000e, igb, ne2k_pci, pcnet, rtl8139, virtio. Defaults to virtio. - TODO:(ihar) switch to enums once opengen-api supports them. See: https://github.com/kubernetes/kube-openapi/issues/51 type: string name: description: |- @@ -1805,7 +1831,11 @@ spec: state: description: |- State represents the requested operational state of the interface. - The (only) value supported is 'absent', expressing a request to remove the interface. + The supported values are: + 'absent', expressing a request to remove the interface. + 'down', expressing a request to set the link down. + 'up', expressing a request to set the link up. + Empty value functions as 'up'. type: string tag: description: If specified, the virtual network interface @@ -1831,6 +1861,19 @@ spec: depends on additional factors of the VirtualMachineInstance, like the number of guest CPUs. type: boolean + panicDevices: + description: PanicDevices provides additional crash information + when a guest crashes. + items: + properties: + model: + description: |- + Model specifies what type of panic device is provided. + The panic model used when this attribute is missing depends on the hypervisor and guest arch. + One of: isa, hyperv, pvpanic. + type: string + type: object + type: array rng: description: Whether to have random number generator from host @@ -1853,6 +1896,11 @@ spec: tpm: description: Whether to emulate a TPM device. properties: + enabled: + description: |- + Enabled allows a user to explicitly disable the vTPM even when one is enabled by a preference referenced by the VirtualMachine + Defaults to True + type: boolean persistent: description: |- Persistent indicates the state of the TPM device should be kept accross reboots @@ -1865,10 +1913,30 @@ spec: This is helpful for old machines like CentOS6 or RHEL6 which do not understand virtio_non_transitional (virtio 1.0). type: boolean + video: + description: Video describes the video device configuration + for the vmi. + properties: + type: + description: |- + Type specifies the video device type (e.g., virtio, vga, bochs, ramfb). + If not specified, the default is architecture-dependent (VGA for BIOS-based VMs, Bochs for EFI-based VMs on AMD64; virtio for Arm and s390x). + type: string + type: object watchdog: description: Watchdog describes a watchdog device which can be added to the vmi. properties: + diag288: + description: diag288 watchdog device (specific to s390x + architecture). + properties: + action: + description: |- + The action to take. Valid values are poweroff, reset, shutdown. + Defaults to reset. + type: string + type: object i6300esb: description: i6300esb watchdog device. properties: @@ -2138,6 +2206,11 @@ spec: acpi: description: Information that can be set in the ACPI table properties: + msdmNameRef: + description: |- + Similar to SlicNameRef, another ACPI entry that is used in more recent Windows versions. + The above points to the spec of MSDM too. + type: string slicNameRef: description: |- SlicNameRef should match the volume name of a secret object. The data in the secret should @@ -2221,11 +2294,20 @@ spec: Defaults to a random generated uid. type: string type: object + ioThreads: + description: IOThreads specifies the IOThreads options. + properties: + supplementalPoolThreadCount: + description: SupplementalPoolThreadCount specifies how many + iothreads are allocated for the supplementalPool policy. + format: int32 + type: integer + type: object ioThreadsPolicy: description: |- Controls whether or not disks will share IOThreads. Omitting IOThreadsPolicy disables use of IOThreads. - One of: shared, auto + One of: shared, auto, supplementalPool type: string launchSecurity: description: Launch Security setting of the vmi. @@ -2340,7 +2422,7 @@ spec: - "None": No action will be taken, according to the specified 'RunStrategy' the VirtualMachine will be restarted or shutdown. - "LiveMigrate": the VirtualMachineInstance will be migrated instead of being shutdown. - "LiveMigrateIfPossible": the same as "LiveMigrate" but only if the VirtualMachine is Live-Migratable, otherwise it will behave as "None". - - "External": the VirtualMachineInstance will be protected by a PDB and 'vmi.Status.EvacuationNodeName' will be set on eviction. This is mainly useful for cluster-api-provider-kubevirt (capk) which needs a way for VMI's to be blocked from eviction, yet signal capk that eviction has been called on the VMI so the capk controller can handle tearing the VMI down. Details can be found in the commit description https://github.com/kubevirt/kubevirt/commit/c1d77face705c8b126696bac9a3ee3825f27f1fa. + - "External": the VirtualMachineInstance will be protected and 'vmi.Status.EvacuationNodeName' will be set on eviction. This is mainly useful for cluster-api-provider-kubevirt (capk) which needs a way for VMI's to be blocked from eviction, yet signal capk that eviction has been called on the VMI so the capk controller can handle tearing the VMI down. Details can be found in the commit description https://github.com/kubevirt/kubevirt/commit/c1d77face705c8b126696bac9a3ee3825f27f1fa. type: string hostname: description: |- @@ -2453,7 +2535,6 @@ spec: description: |- TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook properties: host: description: 'Optional: Host name to connect to, defaults @@ -2652,7 +2733,6 @@ spec: description: |- TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook properties: host: description: 'Optional: Host name to connect to, defaults @@ -2682,6 +2762,65 @@ spec: format: int32 type: integer type: object + resourceClaims: + description: |- + ResourceClaims define which ResourceClaims must be allocated + and reserved before the VMI, hence virt-launcher pod is allowed to start. The resources + will be made available to the domain which consumes them + by name. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate in kubernetes + https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/ + This field should only be configured if one of the feature-gates GPUsWithDRA or HostDevicesWithDRA is enabled. + This feature is in alpha. + items: + description: |- + PodResourceClaim references exactly one ResourceClaim, either directly + or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim + for the pod. + + It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. + Containers that need access to the ResourceClaim reference it with this name. + properties: + name: + description: |- + Name uniquely identifies this resource claim inside the pod. + This must be a DNS_LABEL. + type: string + resourceClaimName: + description: |- + ResourceClaimName is the name of a ResourceClaim object in the same + namespace as this pod. + + Exactly one of ResourceClaimName and ResourceClaimTemplateName must + be set. + type: string + resourceClaimTemplateName: + description: |- + ResourceClaimTemplateName is the name of a ResourceClaimTemplate + object in the same namespace as this pod. + + The template will be used to create a new ResourceClaim, which will + be bound to this pod. When this pod is deleted, the ResourceClaim + will also be deleted. The pod name and resource name, along with a + generated component, will be used to form a unique name for the + ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + + This field is immutable and no changes will be made to the + corresponding ResourceClaim by the control plane after creating the + ResourceClaim. + + Exactly one of ResourceClaimName and ResourceClaimTemplateName must + be set. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map schedulerName: description: |- If specified, the VMI will be dispatched by specified scheduler. @@ -2809,7 +2948,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -2849,7 +2987,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -2867,7 +3004,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -2879,7 +3015,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -2952,10 +3087,13 @@ spec: that contains config drive networkdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -2964,10 +3102,13 @@ spec: contains config drive userdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -2999,10 +3140,13 @@ spec: that contains NoCloud networkdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3011,10 +3155,13 @@ spec: contains NoCloud userdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3033,10 +3180,13 @@ spec: More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string optional: description: Specify whether the ConfigMap or it's keys @@ -3076,6 +3226,8 @@ spec: description: Path defines the path to disk file in the container type: string hotpluggable: + description: Hotpluggable indicates whether the volume can + be hotplugged and hotunplugged. type: boolean required: - image @@ -3090,9 +3242,8 @@ spec: be hotplugged and hotunplugged. type: boolean name: - description: |- - Name of both the DataVolume and the PVC in the same namespace. - After PVC population the DataVolume is garbage collected by default. + description: Name of both the DataVolume and the PVC in + the same namespace. type: string required: - name @@ -3340,10 +3491,13 @@ spec: be attached as disk of CDROM type. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3353,10 +3507,13 @@ spec: be attached as disk of CDROM type. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3436,6 +3593,97 @@ spec: format: int32 type: integer type: object + deviceStatus: + description: |- + DeviceStatus reflects the state of devices requested in spec.domain.devices. This is an optional field available + only when DRA feature gate is enabled + This field will only be populated if one of the feature-gates GPUsWithDRA or HostDevicesWithDRA is enabled. + This feature is in alpha. + properties: + gpuStatuses: + description: GPUStatuses reflects the state of GPUs requested + in spec.domain.devices.gpus + items: + properties: + deviceResourceClaimStatus: + description: DeviceResourceClaimStatus reflects the DRA + related information for the device + properties: + attributes: + description: |- + Attributes are properties of the device that could be used by kubevirt and other copmonents to learn more + about the device, like pciAddress or mdevUUID + properties: + mDevUUID: + description: MDevUUID is the mediated device uuid + of the allocated device + type: string + pciAddress: + description: PCIAddress is the PCIe bus address + of the allocated device + type: string + type: object + name: + description: Name is the name of actual device on the + host provisioned by the driver as reflected in resourceclaim.status + type: string + resourceClaimName: + description: ResourceClaimName is the name of the resource + claims object used to provision this resource + type: string + type: object + name: + description: Name of the device as specified in spec.domain.devices.gpus.name + or spec.domain.devices.hostDevices.name + type: string + required: + - name + type: object + type: array + x-kubernetes-list-type: atomic + hostDeviceStatuses: + description: |- + HostDeviceStatuses reflects the state of GPUs requested in spec.domain.devices.hostDevices + DRA + items: + properties: + deviceResourceClaimStatus: + description: DeviceResourceClaimStatus reflects the DRA + related information for the device + properties: + attributes: + description: |- + Attributes are properties of the device that could be used by kubevirt and other copmonents to learn more + about the device, like pciAddress or mdevUUID + properties: + mDevUUID: + description: MDevUUID is the mediated device uuid + of the allocated device + type: string + pciAddress: + description: PCIAddress is the PCIe bus address + of the allocated device + type: string + type: object + name: + description: Name is the name of actual device on the + host provisioned by the driver as reflected in resourceclaim.status + type: string + resourceClaimName: + description: ResourceClaimName is the name of the resource + claims object used to provision this resource + type: string + type: object + name: + description: Name of the device as specified in spec.domain.devices.gpus.name + or spec.domain.devices.hostDevices.name + type: string + required: + - name + type: object + type: array + x-kubernetes-list-type: atomic + type: object evacuationNodeName: description: |- EvacuationNodeName is used to track the eviction process of a VMI. It stores the name of the node that we want @@ -3443,8 +3691,9 @@ spec: type: string fsFreezeStatus: description: |- - FSFreezeStatus is the state of the fs of the guest - it can be either frozen or thawed + FSFreezeStatus indicates whether a freeze operation was requested for the guest filesystem. + It will be set to "frozen" if the request was made, or unset otherwise. + This does not reflect the actual state of the guest filesystem. type: string guestOSInfo: description: Guest OS Information @@ -3496,6 +3745,10 @@ spec: items: type: string type: array + linkState: + description: 'LinkState Reports the current operational link + state''. values: up, down.' + type: string mac: description: Hardware address of a Virtual Machine interface type: string @@ -3503,6 +3756,10 @@ spec: description: Name of the interface, corresponds to name of the network assigned to the interface type: string + podInterfaceName: + description: PodInterfaceName represents the name of the pod + network interface + type: string queueCount: description: Specifies how many queues are allocated by MultiQueue format: int32 @@ -3731,6 +3988,13 @@ spec: If set to true, migrations will still start in pre-copy, but switch to post-copy when CompletionTimeoutPerGiB triggers. Defaults to false type: boolean + allowWorkloadDisruption: + description: |- + AllowWorkloadDisruption indicates that the migration shouldn't be + canceled after acceptableCompletionTime is exceeded. Instead, if + permitted, migration will be switched to post-copy or the VMI will be + paused to allow the migration to complete + type: boolean bandwidthPerMigration: anyOf: - type: integer @@ -3743,8 +4007,8 @@ spec: completionTimeoutPerGiB: description: |- CompletionTimeoutPerGiB is the maximum number of seconds per GiB a migration is allowed to take. - If a live-migration takes longer to migrate than this value multiplied by the size of the VMI, - the migration will be cancelled, unless AllowPostCopy is true. Defaults to 800 + If the timeout is reached, the migration will be either paused, switched + to post-copy or cancelled depending on other settings. Defaults to 150 format: int64 type: integer disableTLS: @@ -3794,6 +4058,9 @@ spec: indicates the migration will be unsafe to the guest. Defaults to false type: boolean type: object + migrationNetworkType: + description: The type of migration network, either 'pod' or 'migration' + type: string migrationPolicyName: description: Name of the migration policy. If string is empty, no policy is matched @@ -3809,8 +4076,57 @@ spec: sourceNode: description: The source node that the VMI originated on type: string + sourcePersistentStatePVCName: + description: If the VMI being migrated uses persistent features + (backend-storage), its source PVC name is saved here + type: string sourcePod: type: string + sourceState: + description: SourceState contains migration state managed by the + source virt handler + properties: + domainName: + description: The name of the domain on the source libvirt + domain + type: string + domainNamespace: + description: Namespace used in the name of the source libvirt + domain. Can be used to find and modify paths in the domain + type: string + migrationUID: + description: The Source VirtualMachineInstanceMigration object + associated with this migration + type: string + node: + description: The source node that the VMI originated on + type: string + nodeSelectors: + additionalProperties: + type: string + description: Node selectors needed by the target to start + the receiving pod. + type: object + persistentStatePVCName: + description: If the VMI being migrated uses persistent features + (backend-storage), its source PVC name is saved here + type: string + pod: + description: The source pod that the VMI is originated on + type: string + selinuxContext: + description: SELinuxContext is the actual SELinux context + of the pod + type: string + syncAddress: + description: The ip address/fqdn:port combination to use to + synchronize the VMI with the target. + type: string + virtualMachineInstanceUID: + description: VirtualMachineInstanceUID is the UID of the target + virtual machine instance + type: string + type: object startTimestamp: description: The time the migration action began format: date-time @@ -3853,9 +4169,87 @@ spec: If the VMI requires dedicated CPUs, this field will hold the numa topology on the target node type: string + targetPersistentStatePVCName: + description: If the VMI being migrated uses persistent features + (backend-storage), its target PVC name is saved here + type: string targetPod: description: The target pod that the VMI is moving to type: string + targetState: + description: TargetState contains migration state managed by the + target virt handler + properties: + attachmentPodUID: + description: The UID of the target attachment pod for hotplug + volumes + type: string + cpuSet: + description: |- + If the VMI requires dedicated CPUs, this field will + hold the dedicated CPU set on the target node + items: + type: integer + type: array + x-kubernetes-list-type: atomic + directMigrationNodePorts: + additionalProperties: + type: integer + description: The list of ports opened for live migration on + the destination node + type: object + domainDetected: + description: The Target Node has seen the Domain Start Event + type: boolean + domainName: + description: The name of the domain on the source libvirt + domain + type: string + domainNamespace: + description: Namespace used in the name of the source libvirt + domain. Can be used to find and modify paths in the domain + type: string + domainReadyTimestamp: + description: The timestamp at which the target node detects + the domain is active + format: date-time + type: string + migrationUID: + description: The Source VirtualMachineInstanceMigration object + associated with this migration + type: string + node: + description: The source node that the VMI originated on + type: string + nodeAddress: + description: The address of the target node to use for the + migration + type: string + nodeTopology: + description: |- + If the VMI requires dedicated CPUs, this field will + hold the numa topology on the target node + type: string + persistentStatePVCName: + description: If the VMI being migrated uses persistent features + (backend-storage), its source PVC name is saved here + type: string + pod: + description: The source pod that the VMI is originated on + type: string + selinuxContext: + description: SELinuxContext is the actual SELinux context + of the pod + type: string + syncAddress: + description: The ip address/fqdn:port combination to use to + synchronize the VMI with the target. + type: string + virtualMachineInstanceUID: + description: VirtualMachineInstanceUID is the UID of the target + virtual machine instance + type: string + type: object type: object migrationTransport: description: This represents the migration transport diff --git a/crds/embedded/virtualmachines.yaml b/crds/embedded/virtualmachines.yaml index 72d9f865f6..a0bfe284f4 100644 --- a/crds/embedded/virtualmachines.yaml +++ b/crds/embedded/virtualmachines.yaml @@ -319,7 +319,7 @@ spec: set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -812,6 +812,7 @@ spec: description: |- Running controls whether the associatied VirtualMachineInstance is created or not Mutually exclusive with RunStrategy + Deprecated: VirtualMachineInstance field "Running" is now deprecated, please use RunStrategy instead. type: boolean template: description: Template is the direct specification of VirtualMachineInstance @@ -1219,7 +1220,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1234,7 +1235,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1402,7 +1403,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1417,7 +1418,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1583,7 +1584,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1598,7 +1599,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1766,7 +1767,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1781,7 +1782,7 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1894,9 +1895,13 @@ spec: options of a pod. properties: name: - description: Required. + description: |- + Name is this DNS resolver option's name. + Required. type: string value: + description: Value is this DNS resolver option's + value. type: string type: object type: array @@ -2217,7 +2222,11 @@ spec: cache: description: |- Cache specifies which kvm disk cache mode should be used. - Supported values are: CacheNone, CacheWriteThrough. + Supported values are: + none: Guest I/O not cached on the host, but may be kept in a disk cache. + writethrough: Guest I/O cached on the host but written through to the physical medium. Slowest but with most guarantees. + writeback: Guest I/O cached on the host. + Defaults to none if the storage supports O_DIRECT, otherwise writethrough. type: string cdrom: description: Attach a volume as a cdrom to the @@ -2344,12 +2353,24 @@ spec: vmi. items: properties: + claimName: + description: |- + ClaimName needs to be provided from the list vmi.spec.resourceClaims[].name where this + device is allocated + type: string deviceName: + description: DeviceName is the name of the device + provisioned by device-plugins type: string name: description: Name of the GPU device as exposed by a device plugin type: string + requestName: + description: |- + RequestName needs to be provided from resourceClaim.spec.devices.requests[].name where this + device is requested + type: string tag: description: If specified, the virtual network interface address and its tag will be provided @@ -2388,19 +2409,28 @@ spec: vmi. items: properties: + claimName: + description: |- + ClaimName needs to be provided from the list vmi.spec.resourceClaims[].name where this + device is allocated + type: string deviceName: - description: DeviceName is the resource name - of the host device exposed by a device plugin + description: DeviceName is the name of the device + provisioned by device-plugins type: string name: type: string + requestName: + description: |- + RequestName needs to be provided from resourceClaim.spec.devices.requests[].name where this + device is requested + type: string tag: description: If specified, the virtual network interface address and its tag will be provided to the guest via config drive type: string required: - - deviceName - name type: object type: array @@ -2523,9 +2553,8 @@ spec: model: description: |- Interface model. - One of: e1000, e1000e, ne2k_pci, pcnet, rtl8139, virtio. + One of: e1000, e1000e, igb, ne2k_pci, pcnet, rtl8139, virtio. Defaults to virtio. - TODO:(ihar) switch to enums once opengen-api supports them. See: https://github.com/kubernetes/kube-openapi/issues/51 type: string name: description: |- @@ -2587,7 +2616,11 @@ spec: state: description: |- State represents the requested operational state of the interface. - The (only) value supported is 'absent', expressing a request to remove the interface. + The supported values are: + 'absent', expressing a request to remove the interface. + 'down', expressing a request to set the link down. + 'up', expressing a request to set the link up. + Empty value functions as 'up'. type: string tag: description: If specified, the virtual network @@ -2614,6 +2647,19 @@ spec: of the VirtualMachineInstance, like the number of guest CPUs. type: boolean + panicDevices: + description: PanicDevices provides additional crash + information when a guest crashes. + items: + properties: + model: + description: |- + Model specifies what type of panic device is provided. + The panic model used when this attribute is missing depends on the hypervisor and guest arch. + One of: isa, hyperv, pvpanic. + type: string + type: object + type: array rng: description: Whether to have random number generator from host @@ -2637,6 +2683,11 @@ spec: tpm: description: Whether to emulate a TPM device. properties: + enabled: + description: |- + Enabled allows a user to explicitly disable the vTPM even when one is enabled by a preference referenced by the VirtualMachine + Defaults to True + type: boolean persistent: description: |- Persistent indicates the state of the TPM device should be kept accross reboots @@ -2649,10 +2700,30 @@ spec: This is helpful for old machines like CentOS6 or RHEL6 which do not understand virtio_non_transitional (virtio 1.0). type: boolean + video: + description: Video describes the video device configuration + for the vmi. + properties: + type: + description: |- + Type specifies the video device type (e.g., virtio, vga, bochs, ramfb). + If not specified, the default is architecture-dependent (VGA for BIOS-based VMs, Bochs for EFI-based VMs on AMD64; virtio for Arm and s390x). + type: string + type: object watchdog: description: Watchdog describes a watchdog device which can be added to the vmi. properties: + diag288: + description: diag288 watchdog device (specific + to s390x architecture). + properties: + action: + description: |- + The action to take. Valid values are poweroff, reset, shutdown. + Defaults to reset. + type: string + type: object i6300esb: description: i6300esb watchdog device. properties: @@ -2923,6 +2994,11 @@ spec: description: Information that can be set in the ACPI table properties: + msdmNameRef: + description: |- + Similar to SlicNameRef, another ACPI entry that is used in more recent Windows versions. + The above points to the spec of MSDM too. + type: string slicNameRef: description: |- SlicNameRef should match the volume name of a secret object. The data in the secret should @@ -3009,11 +3085,21 @@ spec: Defaults to a random generated uid. type: string type: object + ioThreads: + description: IOThreads specifies the IOThreads options. + properties: + supplementalPoolThreadCount: + description: SupplementalPoolThreadCount specifies + how many iothreads are allocated for the supplementalPool + policy. + format: int32 + type: integer + type: object ioThreadsPolicy: description: |- Controls whether or not disks will share IOThreads. Omitting IOThreadsPolicy disables use of IOThreads. - One of: shared, auto + One of: shared, auto, supplementalPool type: string launchSecurity: description: Launch Security setting of the vmi. @@ -3129,7 +3215,7 @@ spec: - "None": No action will be taken, according to the specified 'RunStrategy' the VirtualMachine will be restarted or shutdown. - "LiveMigrate": the VirtualMachineInstance will be migrated instead of being shutdown. - "LiveMigrateIfPossible": the same as "LiveMigrate" but only if the VirtualMachine is Live-Migratable, otherwise it will behave as "None". - - "External": the VirtualMachineInstance will be protected by a PDB and 'vmi.Status.EvacuationNodeName' will be set on eviction. This is mainly useful for cluster-api-provider-kubevirt (capk) which needs a way for VMI's to be blocked from eviction, yet signal capk that eviction has been called on the VMI so the capk controller can handle tearing the VMI down. Details can be found in the commit description https://github.com/kubevirt/kubevirt/commit/c1d77face705c8b126696bac9a3ee3825f27f1fa. + - "External": the VirtualMachineInstance will be protected and 'vmi.Status.EvacuationNodeName' will be set on eviction. This is mainly useful for cluster-api-provider-kubevirt (capk) which needs a way for VMI's to be blocked from eviction, yet signal capk that eviction has been called on the VMI so the capk controller can handle tearing the VMI down. Details can be found in the commit description https://github.com/kubevirt/kubevirt/commit/c1d77face705c8b126696bac9a3ee3825f27f1fa. type: string hostname: description: |- @@ -3242,7 +3328,6 @@ spec: description: |- TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook properties: host: description: 'Optional: Host name to connect to, defaults @@ -3441,7 +3526,6 @@ spec: description: |- TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook properties: host: description: 'Optional: Host name to connect to, defaults @@ -3471,6 +3555,65 @@ spec: format: int32 type: integer type: object + resourceClaims: + description: |- + ResourceClaims define which ResourceClaims must be allocated + and reserved before the VMI, hence virt-launcher pod is allowed to start. The resources + will be made available to the domain which consumes them + by name. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate in kubernetes + https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/ + This field should only be configured if one of the feature-gates GPUsWithDRA or HostDevicesWithDRA is enabled. + This feature is in alpha. + items: + description: |- + PodResourceClaim references exactly one ResourceClaim, either directly + or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim + for the pod. + + It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. + Containers that need access to the ResourceClaim reference it with this name. + properties: + name: + description: |- + Name uniquely identifies this resource claim inside the pod. + This must be a DNS_LABEL. + type: string + resourceClaimName: + description: |- + ResourceClaimName is the name of a ResourceClaim object in the same + namespace as this pod. + + Exactly one of ResourceClaimName and ResourceClaimTemplateName must + be set. + type: string + resourceClaimTemplateName: + description: |- + ResourceClaimTemplateName is the name of a ResourceClaimTemplate + object in the same namespace as this pod. + + The template will be used to create a new ResourceClaim, which will + be bound to this pod. When this pod is deleted, the ResourceClaim + will also be deleted. The pod name and resource name, along with a + generated component, will be used to form a unique name for the + ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + + This field is immutable and no changes will be made to the + corresponding ResourceClaim by the control plane after creating the + ResourceClaim. + + Exactly one of ResourceClaimName and ResourceClaimTemplateName must + be set. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map schedulerName: description: |- If specified, the VMI will be dispatched by specified scheduler. @@ -3600,7 +3743,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -3640,7 +3782,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -3658,7 +3799,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -3670,7 +3810,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -3743,10 +3882,13 @@ spec: secret that contains config drive networkdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3755,10 +3897,13 @@ spec: secret that contains config drive userdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3790,10 +3935,13 @@ spec: secret that contains NoCloud networkdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3802,10 +3950,13 @@ spec: secret that contains NoCloud userdata. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -3824,10 +3975,13 @@ spec: More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string optional: description: Specify whether the ConfigMap or it's @@ -3882,9 +4036,8 @@ spec: volume can be hotplugged and hotunplugged. type: boolean name: - description: |- - Name of both the DataVolume and the PVC in the same namespace. - After PVC population the DataVolume is garbage collected by default. + description: Name of both the DataVolume and the + PVC in the same namespace. type: string required: - name @@ -4137,10 +4290,13 @@ spec: that should be attached as disk of CDROM type. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -4150,10 +4306,13 @@ spec: that should be attached as disk of CDROM type. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -4219,6 +4378,35 @@ spec: updated through an Update() before ObservedGeneration in Status. format: int64 type: integer + instancetypeRef: + description: InstancetypeRef captures the state of any referenced + instance type from the VirtualMachine + nullable: true + properties: + controllerRevisionRef: + description: |- + ControllerRef specifies the ControllerRevision storing a copy of the object captured + when it is first seen by the VirtualMachine controller + properties: + name: + description: Name of the ControllerRevision + type: string + type: object + inferFromVolume: + description: InferFromVolume lists the name of a volume that should + be used to infer or discover the resource + type: string + inferFromVolumeFailurePolicy: + description: InferFromVolumeFailurePolicy controls what should + happen on failure when inferring the resource + type: string + kind: + description: Kind specifies the kind of resource + type: string + name: + description: Name is the name of resource + type: string + type: object memoryDumpRequest: description: |- MemoryDumpRequest tracks memory dump request phase and info of getting a memory @@ -4262,6 +4450,35 @@ spec: vmi when started. format: int64 type: integer + preferenceRef: + description: PreferenceRef captures the state of any referenced preference + from the VirtualMachine + nullable: true + properties: + controllerRevisionRef: + description: |- + ControllerRef specifies the ControllerRevision storing a copy of the object captured + when it is first seen by the VirtualMachine controller + properties: + name: + description: Name of the ControllerRevision + type: string + type: object + inferFromVolume: + description: InferFromVolume lists the name of a volume that should + be used to infer or discover the resource + type: string + inferFromVolumeFailurePolicy: + description: InferFromVolumeFailurePolicy controls what should + happen on failure when inferring the resource + type: string + kind: + description: Kind specifies the kind of resource + type: string + name: + description: Name is the name of resource + type: string + type: object printableStatus: default: Stopped description: PrintableStatus is a human readable, high-level representation @@ -4378,7 +4595,11 @@ spec: cache: description: |- Cache specifies which kvm disk cache mode should be used. - Supported values are: CacheNone, CacheWriteThrough. + Supported values are: + none: Guest I/O not cached on the host, but may be kept in a disk cache. + writethrough: Guest I/O cached on the host but written through to the physical medium. Slowest but with most guarantees. + writeback: Guest I/O cached on the host. + Defaults to none if the storage supports O_DIRECT, otherwise writethrough. type: string cdrom: description: Attach a volume as a cdrom to the vmi. @@ -4531,9 +4752,8 @@ spec: volume can be hotplugged and hotunplugged. type: boolean name: - description: |- - Name of both the DataVolume and the PVC in the same namespace. - After PVC population the DataVolume is garbage collected by default. + description: Name of both the DataVolume and the + PVC in the same namespace. type: string required: - name @@ -4615,6 +4835,134 @@ spec: - name type: object type: array + volumeUpdateState: + description: |- + VolumeUpdateState contains the information about the volumes set + updates related to the volumeUpdateStrategy + properties: + volumeMigrationState: + description: VolumeMigrationState tracks the information related + to the volume migration + properties: + migratedVolumes: + description: MigratedVolumes lists the source and destination + volumes during the volume migration + items: + description: StorageMigratedVolumeInfo tracks the information + about the source and destination volumes during the volume + migration + properties: + destinationPVCInfo: + description: DestinationPVCInfo contains the information + about the destination PVC + properties: + accessModes: + description: |- + AccessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Capacity represents the capacity set + on the corresponding PVC status + type: object + claimName: + description: ClaimName is the name of the PVC + type: string + filesystemOverhead: + description: Percentage of filesystem's size to + be reserved when resizing the PVC + pattern: ^(0(?:\.\d{1,3})?|1)$ + type: string + preallocated: + description: Preallocated indicates if the PVC's + storage is preallocated or not + type: boolean + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests represents the resources requested + by the corresponding PVC spec + type: object + volumeMode: + description: |- + VolumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + type: object + sourcePVCInfo: + description: SourcePVCInfo contains the information + about the source PVC + properties: + accessModes: + description: |- + AccessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Capacity represents the capacity set + on the corresponding PVC status + type: object + claimName: + description: ClaimName is the name of the PVC + type: string + filesystemOverhead: + description: Percentage of filesystem's size to + be reserved when resizing the PVC + pattern: ^(0(?:\.\d{1,3})?|1)$ + type: string + preallocated: + description: Preallocated indicates if the PVC's + storage is preallocated or not + type: boolean + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests represents the resources requested + by the corresponding PVC spec + type: object + volumeMode: + description: |- + VolumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + type: object + volumeName: + description: VolumeName is the name of the volume that + is being migrated + type: string + required: + - volumeName + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object type: object required: - spec diff --git a/crds/virtualmachineoperations.yaml b/crds/virtualmachineoperations.yaml index e1d77838ac..68568949d9 100644 --- a/crds/virtualmachineoperations.yaml +++ b/crds/virtualmachineoperations.yaml @@ -151,6 +151,18 @@ spec: && size(self.customization.namePrefix) > 0) || (has(self.customization.nameSuffix) && size(self.customization.nameSuffix) > 0))) || (has(self.nameReplacement) && size(self.nameReplacement) > 0) + evict: + description: Evict contains settings for Evict operation. + properties: + nodeSelector: + additionalProperties: + type: string + description: |- + NodeSelector restricts the set of nodes the VM can migrate to. + Passed to KubeVirt's AddedNodeSelector which complements + any existing nodeSelector or nodeAffinity on the VM. + type: object + type: object force: description: |- Force execution of an operation. diff --git a/images/hooks/go.mod b/images/hooks/go.mod index bb211a4a08..3aa044a027 100644 --- a/images/hooks/go.mod +++ b/images/hooks/go.mod @@ -105,7 +105,7 @@ require ( k8s.io/component-base v0.33.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect - kubevirt.io/api v1.3.1 // indirect + kubevirt.io/api v1.6.2 // indirect kubevirt.io/containerized-data-importer-api v1.60.3 // indirect kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/controller-runtime v0.21.0 // indirect diff --git a/images/hooks/go.sum b/images/hooks/go.sum index 4433af27eb..663744542f 100644 --- a/images/hooks/go.sum +++ b/images/hooks/go.sum @@ -623,8 +623,8 @@ k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= -kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +kubevirt.io/api v1.6.2 h1:aoqZ4KsbOyDjLnuDw7H9wEgE/YTd/q5BBmYeQjJNizc= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= kubevirt.io/containerized-data-importer-api v1.60.3 h1:kQEXi7scpzUa0RPf3/3MKk1Kmem0ZlqqiuK3kDF5L2I= kubevirt.io/containerized-data-importer-api v1.60.3/go.mod h1:8mwrkZIdy8j/LmCyKt2wFXbiMavLUIqDaegaIF67CZs= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= diff --git a/images/virt-api/debug/dlv.Dockerfile b/images/virt-api/debug/dlv.Dockerfile index bca504a4d3..fe10ced68b 100644 --- a/images/virt-api/debug/dlv.Dockerfile +++ b/images/virt-api/debug/dlv.Dockerfile @@ -1,10 +1,10 @@ -FROM golang:1.22.7 AS builder +FROM golang:1.23 AS builder RUN go install github.com/go-delve/delve/cmd/dlv@latest -ARG BRANCH="1.3.1-virtualization" -ENV VERSION="1.3.1" -ENV GOVERSION="1.22.7" +ARG BRANCH="1.6.2-virtualization" +ENV VERSION="1.6.2" +ENV GOVERSION="1.23.0" # Copy the git commits for rebuilding the image if the branch changes ADD "https://api.github.com/repos/deckhouse/3p-kubevirt/commits/$BRANCH" /.git-commit-hash.tmp @@ -14,7 +14,7 @@ WORKDIR /kubevirt RUN go mod edit -go=$GOVERSION && \ go mod download -RUN go mod vendor +RUN go work vendor ENV GO111MODULE=on ENV GOOS=linux diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 33742cfd40..a764afec8a 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -9,6 +9,7 @@ image: {{ .ModuleNamePrefix }}{{ .ImageName }}-src-artifact final: false fromImage: builder/src +fromCacheVersion: "new-version0001" # TODO: remove this secrets: - id: SOURCE_REPO value: {{ $.SOURCE_REPO }} @@ -83,7 +84,7 @@ shell: cd /kubevirt go mod download - go mod vendor + go work vendor for p in patches/*.patch ; do echo -n "Apply ${p} ... " diff --git a/images/virt-controller/debug/dlv.Dockerfile b/images/virt-controller/debug/dlv.Dockerfile index ab4f9606db..fec4948301 100644 --- a/images/virt-controller/debug/dlv.Dockerfile +++ b/images/virt-controller/debug/dlv.Dockerfile @@ -1,10 +1,10 @@ -FROM golang:1.22.7 AS builder +FROM golang:1.23 AS builder RUN go install github.com/go-delve/delve/cmd/dlv@latest -ARG BRANCH="1.3.1-virtualization" -ENV VERSION="1.3.1" -ENV GOVERSION="1.22.7" +ARG BRANCH="v1.6.1-virtualization" +ENV VERSION="1.6.1" +ENV GOVERSION="1.23.0" # Copy the git commits for rebuilding the image if the branch changes ADD "https://api.github.com/repos/deckhouse/3p-kubevirt/commits/$BRANCH" /.git-commit-hash.tmp @@ -14,7 +14,7 @@ WORKDIR /kubevirt RUN go mod edit -go=$GOVERSION && \ go mod download -RUN go mod vendor +RUN go work vendor ENV GO111MODULE=on ENV GOOS=linux diff --git a/images/virt-handler/debug/dlv.Dockerfile b/images/virt-handler/debug/dlv.Dockerfile index 874864081d..9ec7804cf0 100644 --- a/images/virt-handler/debug/dlv.Dockerfile +++ b/images/virt-handler/debug/dlv.Dockerfile @@ -3,6 +3,7 @@ RUN groupadd --gid 1001 nonroot-user && useradd nonroot-user --uid 1001 --gid 10 FROM basealt AS builder +# TODO add pin repository url RUN apt-get update RUN apt-get install -y \ @@ -17,9 +18,9 @@ RUN apt-get install -y \ RUN go install github.com/go-delve/delve/cmd/dlv@latest -ARG BRANCH="1.3.1-virtualization" -ENV VERSION="1.3.1" -ENV GOVERSION="1.22.7" +ARG BRANCH="1.6.2-virtualization" +ENV VERSION="1.6.2" +ENV GOVERSION="1.23.0" RUN mkdir /kubevirt-config-files && echo "v$VERSION-dirty" > /kubevirt-config-files/.version @@ -31,7 +32,12 @@ WORKDIR /kubevirt RUN go mod edit -go=$GOVERSION && \ go mod download -RUN go mod vendor +RUN go work vendor + +RUN for p in patches/*.patch; do \ + echo -n "Apply ${p} ... " && \ + git apply --ignore-space-change --ignore-whitespace "${p}" && echo OK || (echo FAIL && exit 1); \ + done ENV GO111MODULE=on ENV GOOS=linux @@ -47,9 +53,7 @@ FROM basealt RUN apt-get update && apt-get install --yes \ acl \ procps \ - nftables \ - qemu-img==9.0.2-alt3 \ - xorriso==1.5.6-alt1 && \ + nftables && \ apt-get clean && \ rm --recursive --force /var/lib/apt/lists/ftp.altlinux.org* /var/cache/apt/*.bin @@ -58,7 +62,6 @@ RUN echo "qemu:x:107:107::/home/qemu:/bin/bash" >> /etc/passwd && \ mkdir -p /home/qemu && \ chown -R 107:107 /home/qemu -COPY --from=builder /kubevirt/cmd/virt-handler/virt_launcher.cil /virt_launcher.cil COPY --from=builder /kubevirt-config-files/.version /.version COPY --from=builder /kubevirt/cmd/virt-handler/nsswitch.conf /etc/nsswitch.conf diff --git a/images/virt-handler/werf.inc.yaml b/images/virt-handler/werf.inc.yaml index 4888e05684..3db87a474a 100644 --- a/images/virt-handler/werf.inc.yaml +++ b/images/virt-handler/werf.inc.yaml @@ -25,10 +25,6 @@ import: - virt-chroot - virt-handler - container-disk -- image: {{ .ModuleNamePrefix }}virt-artifact - add: /kubevirt/cmd/{{ $.ImageName }}/virt_launcher.cil - to: /virt_launcher.cil - after: install - image: {{ .ModuleNamePrefix }}virt-artifact add: /kubevirt-config-files/.version to: /.version diff --git a/images/virtualization-artifact/go.mod b/images/virtualization-artifact/go.mod index 3ade7764fa..93dfc2d73b 100644 --- a/images/virtualization-artifact/go.mod +++ b/images/virtualization-artifact/go.mod @@ -32,7 +32,7 @@ require ( k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 - kubevirt.io/api v1.3.1 + kubevirt.io/api v1.6.2 kubevirt.io/containerized-data-importer-api v1.60.3 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.4.0 @@ -165,4 +165,4 @@ replace ( ) // Kubevirt API replaces -replace kubevirt.io/api => github.com/deckhouse/3p-kubevirt/staging/src/kubevirt.io/api v1.3.1-v12n.18 +replace kubevirt.io/api => github.com/deckhouse/3p-kubevirt/staging/src/kubevirt.io/api v1.6.2-v12n.4 diff --git a/images/virtualization-artifact/go.sum b/images/virtualization-artifact/go.sum index 39d45d303a..faff166184 100644 --- a/images/virtualization-artifact/go.sum +++ b/images/virtualization-artifact/go.sum @@ -45,8 +45,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckhouse/3p-kubevirt/staging/src/kubevirt.io/api v1.3.1-v12n.18 h1:9pstD3PiPmby/Chh24ickwUNbAcqbceOPp253/jSr8k= -github.com/deckhouse/3p-kubevirt/staging/src/kubevirt.io/api v1.3.1-v12n.18/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +github.com/deckhouse/3p-kubevirt/staging/src/kubevirt.io/api v1.6.2-v12n.4 h1:Ka+yNQHJwywVQ8+L6fiwWrWSofe2aNLTVjtuk2YSB7E= +github.com/deckhouse/3p-kubevirt/staging/src/kubevirt.io/api v1.6.2-v12n.4/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= github.com/deckhouse/deckhouse/pkg/log v0.0.0-20250226105106-176cd3afcdd5 h1:PsN1E0oxC/+4zdA977txrqUCuObFL3HAuu5Xnud8m8c= github.com/deckhouse/deckhouse/pkg/log v0.0.0-20250226105106-176cd3afcdd5/go.mod h1:Mk5HRzkc5pIcDIZ2JJ6DPuuqnwhXVkb3you8M8Mg+4w= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= diff --git a/images/virtualization-artifact/pkg/controller/vmop/migration/internal/service/migration.go b/images/virtualization-artifact/pkg/controller/vmop/migration/internal/service/migration.go index 138a7da43d..37dc6d2019 100644 --- a/images/virtualization-artifact/pkg/controller/vmop/migration/internal/service/migration.go +++ b/images/virtualization-artifact/pkg/controller/vmop/migration/internal/service/migration.go @@ -51,6 +51,12 @@ func (s MigrationService) IsApplicableForRunPolicy(runPolicy v1alpha2.RunPolicy) } func (s MigrationService) CreateMigration(ctx context.Context, vmop *v1alpha2.VirtualMachineOperation) error { + spec := virtv1.VirtualMachineInstanceMigrationSpec{ + VMIName: vmop.Spec.VirtualMachine, + } + if vmop.Spec.Evict != nil && len(vmop.Spec.Evict.NodeSelector) > 0 { + spec.AddedNodeSelector = vmop.Spec.Evict.NodeSelector + } return client.IgnoreAlreadyExists(s.client.Create(ctx, &virtv1.VirtualMachineInstanceMigration{ TypeMeta: metav1.TypeMeta{ APIVersion: virtv1.SchemeGroupVersion.String(), @@ -70,9 +76,7 @@ func (s MigrationService) CreateMigration(ctx context.Context, vmop *v1alpha2.Vi }, }, }, - Spec: virtv1.VirtualMachineInstanceMigrationSpec{ - VMIName: vmop.Spec.VirtualMachine, - }, + Spec: spec, })) } diff --git a/images/virtualization-artifact/pkg/livemigration/migration_configuration.go b/images/virtualization-artifact/pkg/livemigration/migration_configuration.go index 21910bc868..0fe5d9851a 100644 --- a/images/virtualization-artifact/pkg/livemigration/migration_configuration.go +++ b/images/virtualization-artifact/pkg/livemigration/migration_configuration.go @@ -38,6 +38,7 @@ const ( MigrationCompletionTimeoutPerGiB int64 = 800 DefaultUnsafeMigrationOverride bool = false MigrationAllowPostCopy bool = false + MigrationAllowWorkloadDisruption bool = false ) func NewMigrationConfiguration(allowAutoConverge bool, kvconfig virtv1.KubeVirt) *virtv1.MigrationConfiguration { @@ -63,6 +64,7 @@ func NewMigrationConfiguration(allowAutoConverge bool, kvconfig virtv1.KubeVirt) completionTimeoutPerGiB := MigrationCompletionTimeoutPerGiB defaultUnsafeMigrationOverride := DefaultUnsafeMigrationOverride allowPostCopy := MigrationAllowPostCopy + allowWorkloadDisruption := MigrationAllowWorkloadDisruption return &virtv1.MigrationConfiguration{ ParallelMigrationsPerCluster: ¶llelMigrationsPerCluster, @@ -74,6 +76,7 @@ func NewMigrationConfiguration(allowAutoConverge bool, kvconfig virtv1.KubeVirt) UnsafeMigrationOverride: &defaultUnsafeMigrationOverride, AllowAutoConverge: &allowAutoConverge, AllowPostCopy: &allowPostCopy, + AllowWorkloadDisruption: &allowWorkloadDisruption, DisableTLS: nil, Network: nil, MatchSELinuxLevelOnMigration: nil, diff --git a/images/vm-route-forge/go.mod b/images/vm-route-forge/go.mod index 57bbcc5dcc..1748f07e51 100644 --- a/images/vm-route-forge/go.mod +++ b/images/vm-route-forge/go.mod @@ -67,7 +67,6 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 // indirect github.com/openshift/custom-resource-status v1.1.2 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect @@ -123,8 +122,8 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - kubevirt.io/api v1.3.1 // indirect - kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/api v1.6.2 // indirect + kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 // indirect kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/images/vm-route-forge/go.sum b/images/vm-route-forge/go.sum index 65cc2e5874..3c63121653 100644 --- a/images/vm-route-forge/go.sum +++ b/images/vm-route-forge/go.sum @@ -300,8 +300,6 @@ github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxj github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= -github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 h1:t/CahSnpqY46sQR01SoS+Jt0jtjgmhgE6lFmRnO4q70= -github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= @@ -677,10 +675,10 @@ k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= -kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= -kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= -kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/api v1.6.2 h1:aoqZ4KsbOyDjLnuDw7H9wEgE/YTd/q5BBmYeQjJNizc= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 h1:KTb8wO1Lxj220DX7d2Rdo9xovvlyWWNo3AVm2ua+1nY= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9/go.mod h1:SDJjLGhbPyayDqAqawcGmVNapBp0KodOQvhKPLVGCQU= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= diff --git a/src/cli/go.mod b/src/cli/go.mod index bd767e6226..d859fe42de 100644 --- a/src/cli/go.mod +++ b/src/cli/go.mod @@ -66,8 +66,8 @@ require ( k8s.io/api v0.33.3 // indirect k8s.io/apiextensions-apiserver v0.33.3 // indirect k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect - kubevirt.io/api v1.3.1 // indirect - kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/api v1.6.2 // indirect + kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 // indirect kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect sigs.k8s.io/controller-runtime v0.21.0 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect diff --git a/src/cli/go.sum b/src/cli/go.sum index 2c8e3bc9b0..8bb70c9518 100644 --- a/src/cli/go.sum +++ b/src/cli/go.sum @@ -589,8 +589,12 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +kubevirt.io/api v1.6.2 h1:aoqZ4KsbOyDjLnuDw7H9wEgE/YTd/q5BBmYeQjJNizc= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9 h1:KTb8wO1Lxj220DX7d2Rdo9xovvlyWWNo3AVm2ua+1nY= +kubevirt.io/containerized-data-importer-api v1.60.3-0.20241105012228-50fbed985de9/go.mod h1:SDJjLGhbPyayDqAqawcGmVNapBp0KodOQvhKPLVGCQU= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= diff --git a/src/cli/internal/cmd/lifecycle/lifecycle.go b/src/cli/internal/cmd/lifecycle/lifecycle.go index f699c66292..1d8a70385e 100644 --- a/src/cli/internal/cmd/lifecycle/lifecycle.go +++ b/src/cli/internal/cmd/lifecycle/lifecycle.go @@ -41,6 +41,7 @@ const ( Start Command = "start" Restart Command = "restart" Evict Command = "evict" + Migrate Command = "migrate" ) type Manager interface { @@ -48,6 +49,7 @@ type Manager interface { Start(ctx context.Context, name, namespace string) (msg string, err error) Restart(ctx context.Context, name, namespace string) (msg string, err error) Evict(ctx context.Context, name, namespace string) (msg string, err error) + Migrate(ctx context.Context, name, namespace string, nodeSelector map[string]string) (msg string, err error) } func NewLifecycle(cmd Command) *Lifecycle { @@ -76,6 +78,7 @@ type Options struct { WaitComplete bool CreateOnly bool Timeout time.Duration + NodeSelector map[string]string } func (l *Lifecycle) Run(cmd *cobra.Command, args []string) error { @@ -106,6 +109,9 @@ func (l *Lifecycle) Run(cmd *cobra.Command, args []string) error { case Evict: cmd.Printf("Evicting virtual machine %q\n", key.String()) msg, err = mgr.Evict(ctx, name, namespace) + case Migrate: + cmd.Printf("Migrating virtual machine %q\n", key.String()) + msg, err = mgr.Migrate(ctx, name, namespace, l.opts.NodeSelector) default: return fmt.Errorf("invalid command %q", l.cmd) } @@ -126,10 +132,17 @@ func (l *Lifecycle) Usage() string { {{ProgramName}} {{operation}} --%s=1m myvm # Configure wait vm phase (default: wait=%v) {{ProgramName}} {{operation}} --%s myvm`, opts.Timeout, timeoutFlag, opts.WaitComplete, waitFlag), "{{operation}}", string(l.cmd)) - if l.cmd != Start && l.cmd != Evict { + if l.cmd != Start && l.cmd != Evict && l.cmd != Migrate { usage += fmt.Sprintf(` # Configure shutdown policy (default: force=%v) {{ProgramName}} %s --%s myvm`, opts.Force, l.cmd, forceFlag) + } + if l.cmd == Migrate { + usage += ` + # Migrate to specific node + {{ProgramName}} migrate myvm --node-selector="kubernetes.io/hostname=node-01" + # Migrate to nodes with specific labels + {{ProgramName}} migrate myvm --node-selector="zone=us-west,type=high-memory"` } return usage } @@ -159,6 +172,7 @@ const ( waitFlag, waitFlagShort = "wait", "w" createOnlyFlag, createOnlyFlagShort = "create-only", "c" timeoutFlag, timeoutFlagShort = "timeout", "t" + nodeSelectorFlag = "node-selector" ) func AddCommandlineArgs(flagset *pflag.FlagSet, opts *Options) { @@ -171,3 +185,8 @@ func AddCommandlineArgs(flagset *pflag.FlagSet, opts *Options) { flagset.DurationVarP(&opts.Timeout, timeoutFlag, timeoutFlagShort, opts.Timeout, fmt.Sprintf("--%s, -%s: Set this flag to change the timeout.", timeoutFlag, timeoutFlagShort)) } + +func AddMigrateArgs(flagset *pflag.FlagSet, opts *Options) { + flagset.StringToStringVar(&opts.NodeSelector, nodeSelectorFlag, nil, + fmt.Sprintf("--%s: Node selector to restrict target nodes (e.g., zone=us-west,type=high-memory).", nodeSelectorFlag)) +} diff --git a/src/cli/internal/cmd/lifecycle/migrate.go b/src/cli/internal/cmd/lifecycle/migrate.go new file mode 100644 index 0000000000..019c42e241 --- /dev/null +++ b/src/cli/internal/cmd/lifecycle/migrate.go @@ -0,0 +1,38 @@ +/* +Copyright 2024 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package lifecycle + +import ( + "github.com/spf13/cobra" + + "github.com/deckhouse/virtualization/src/cli/internal/templates" +) + +func NewMigrateCommand() *cobra.Command { + lifecycle := NewLifecycle(Migrate) + cmd := &cobra.Command{ + Use: "migrate (VirtualMachine)", + Short: "Migrate a virtual machine to target nodes.", + Example: lifecycle.Usage(), + Args: templates.ExactArgs("migrate", 1), + RunE: lifecycle.Run, + } + AddCommandlineArgs(cmd.Flags(), &lifecycle.opts) + AddMigrateArgs(cmd.Flags(), &lifecycle.opts) + cmd.SetUsageTemplate(templates.UsageTemplate()) + return cmd +} diff --git a/src/cli/internal/cmd/lifecycle/vmop/vmop.go b/src/cli/internal/cmd/lifecycle/vmop/vmop.go index 4ab33d4db5..6e6a09e963 100644 --- a/src/cli/internal/cmd/lifecycle/vmop/vmop.go +++ b/src/cli/internal/cmd/lifecycle/vmop/vmop.go @@ -93,6 +93,16 @@ func (v VirtualMachineOperation) Evict(ctx context.Context, vmName, vmNamespace return v.do(ctx, vmop, v.options.createOnly, v.options.waitComplete) } +func (v VirtualMachineOperation) Migrate(ctx context.Context, vmName, vmNamespace string, nodeSelector map[string]string) (msg string, err error) { + vmop := v.newVMOP(vmName, vmNamespace, v1alpha2.VMOPTypeEvict, v.options.force) + if len(nodeSelector) > 0 { + vmop.Spec.Evict = &v1alpha2.VirtualMachineOperationEvictSpec{ + NodeSelector: nodeSelector, + } + } + return v.do(ctx, vmop, v.options.createOnly, v.options.waitComplete) +} + func (v VirtualMachineOperation) do(ctx context.Context, vmop *v1alpha2.VirtualMachineOperation, createOnly, waitCompleted bool) (msg string, err error) { if createOnly { vmop, err = v.create(ctx, vmop) diff --git a/src/cli/pkg/command/virtualization.go b/src/cli/pkg/command/virtualization.go index 403c0047c2..115c31467a 100644 --- a/src/cli/pkg/command/virtualization.go +++ b/src/cli/pkg/command/virtualization.go @@ -92,6 +92,7 @@ func NewCommand(programName string) *cobra.Command { lifecycle.NewStopCommand(), lifecycle.NewRestartCommand(), lifecycle.NewEvictCommand(), + lifecycle.NewMigrateCommand(), optionsCmd, ) diff --git a/templates/kubevirt/kubevirt.yaml b/templates/kubevirt/kubevirt.yaml index 14a62637a7..2475cfc994 100644 --- a/templates/kubevirt/kubevirt.yaml +++ b/templates/kubevirt/kubevirt.yaml @@ -52,16 +52,12 @@ spec: virtOperator: {{ $logVerbosity }} featureGates: - HotplugVolumes - - GPU - Snapshot - ExpandDisks - Root - - VMLiveUpdateFeatures - CPUManager - Sidecar - VolumeSnapshotDataSource - - VolumeMigration - - VolumesUpdateStrategy virtualMachineOptions: disableSerialConsoleLog: {} customizeComponents: diff --git a/templates/kubevirt/virt-operator/rbac-for-us.yaml b/templates/kubevirt/virt-operator/rbac-for-us.yaml index d52cec41b0..91a6311478 100644 --- a/templates/kubevirt/virt-operator/rbac-for-us.yaml +++ b/templates/kubevirt/virt-operator/rbac-for-us.yaml @@ -26,6 +26,8 @@ rules: - kubevirt-virt-api-certs - kubevirt-controller-certs - kubevirt-exportproxy-certs + - kubevirt-synchronization-controller-certs + - kubevirt-synchronization-controller-server-certs resources: - secrets verbs: @@ -834,6 +836,9 @@ rules: - virtualmachineinstances/userlist - virtualmachineinstances/sev/fetchcertchain - virtualmachineinstances/sev/querylaunchmeasurement + - virtualmachineinstances/usbredir + - virtualmachines/objectgraph + - virtualmachineinstances/objectgraph verbs: - get - apiGroups: @@ -846,6 +851,7 @@ rules: - virtualmachineinstances/freeze - virtualmachineinstances/unfreeze - virtualmachineinstances/softreboot + - virtualmachineinstances/reset - virtualmachineinstances/sev/setupsession - virtualmachineinstances/sev/injectlaunchsecret verbs: @@ -1214,6 +1220,15 @@ rules: - subjectaccessreviews verbs: - create +- apiGroups: + - resource.k8s.io + resources: + - resourceclaims + - resourceslices + verbs: + - get + - list + - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding diff --git a/test/e2e/go.mod b/test/e2e/go.mod index b727c9ceab..5ddb0f733b 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -16,7 +16,7 @@ require ( k8s.io/cli-runtime v0.33.3 k8s.io/client-go v0.33.3 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 - kubevirt.io/api v1.3.1 + kubevirt.io/api v1.6.2 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.4.0 ) diff --git a/test/e2e/go.sum b/test/e2e/go.sum index f72cde1b6d..66999d0350 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -582,6 +582,8 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kubevirt.io/api v1.3.1 h1:MoTNo/zvDlZ44c2ocXLPln8XTaQOeUodiYbEKrTCqv4= kubevirt.io/api v1.3.1/go.mod h1:tCn7VAZktEvymk490iPSMPCmKM9UjbbfH2OsFR/IOLU= +kubevirt.io/api v1.6.2 h1:aoqZ4KsbOyDjLnuDw7H9wEgE/YTd/q5BBmYeQjJNizc= +kubevirt.io/api v1.6.2/go.mod h1:p66fEy/g79x7VpgUwrkUgOoG2lYs5LQq37WM6JXMwj4= kubevirt.io/containerized-data-importer-api v1.60.3 h1:kQEXi7scpzUa0RPf3/3MKk1Kmem0ZlqqiuK3kDF5L2I= kubevirt.io/containerized-data-importer-api v1.60.3/go.mod h1:8mwrkZIdy8j/LmCyKt2wFXbiMavLUIqDaegaIF67CZs= kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc=