From 83b9bddbbf7715743d490c14ebf8308b1f5ea6f3 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Tue, 14 Apr 2026 15:23:15 +0300 Subject: [PATCH 1/3] feat(vm): add disable-tap-veth-bridge setting Signed-off-by: Dmitry Lopatin --- .../cmd/virtualization-controller/main.go | 4 ++- .../pkg/common/annotations/annotations.go | 2 ++ .../pkg/config/load_network_settings.go | 31 +++++++++++++++++++ .../pkg/controller/kvbuilder/kvvm.go | 5 +++ .../pkg/controller/kvbuilder/kvvm_utils.go | 5 +++ .../controller/vm/internal/migrating_test.go | 2 +- .../vm/internal/service/migration_volumes.go | 22 +++++++------ .../pkg/controller/vm/internal/sync_kvvm.go | 30 ++++++++++-------- .../controller/vm/internal/sync_kvvm_test.go | 2 +- .../pkg/controller/vm/vm_controller.go | 5 +-- openapi/config-values.yaml | 13 ++++++++ .../virtualization-controller/_helpers.tpl | 2 ++ 12 files changed, 95 insertions(+), 28 deletions(-) create mode 100644 images/virtualization-artifact/pkg/config/load_network_settings.go diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index 45bbc5efcc..cb76caa4a5 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -207,6 +207,8 @@ func main() { os.Exit(1) } + networkSettings := appconfig.LoadNetworkSettingsFromEnv() + // Get a config to talk to the apiserver cfg, err := config.GetConfig() if err != nil { @@ -347,7 +349,7 @@ func main() { } vmLogger := logger.NewControllerLogger(vm.ControllerName, logLevel, logOutput, logDebugVerbosity, logDebugControllerList) - if err = vm.SetupController(ctx, mgr, virtClient, vmLogger, dvcrSettings, firmwareImage); err != nil { + if err = vm.SetupController(ctx, mgr, virtClient, vmLogger, dvcrSettings, firmwareImage, networkSettings.DisableTapVethBridge); err != nil { log.Error(err.Error()) os.Exit(1) } diff --git a/images/virtualization-artifact/pkg/common/annotations/annotations.go b/images/virtualization-artifact/pkg/common/annotations/annotations.go index 00e93d6805..44e1564d84 100644 --- a/images/virtualization-artifact/pkg/common/annotations/annotations.go +++ b/images/virtualization-artifact/pkg/common/annotations/annotations.go @@ -88,6 +88,8 @@ const ( // AnnVMRestartRequested is an annotation on KVVM that represents a request to restart a virtual machine. AnnVMRestartRequested = AnnAPIGroupV + "/vm-restart-requested" + // AnnDisableTapVethBridge disables tap-veth-bridge wiring for the VMI network setup in KubeVirt. + AnnDisableTapVethBridge = AnnAPIGroupV + "/disable-tap-veth-bridge" // AnnVMOPWorkloadUpdate is an annotation on vmop that represents a vmop created by workload-updater controller. AnnVMOPWorkloadUpdate = AnnAPIGroupV + "/workload-update" diff --git a/images/virtualization-artifact/pkg/config/load_network_settings.go b/images/virtualization-artifact/pkg/config/load_network_settings.go new file mode 100644 index 0000000000..762ad89e66 --- /dev/null +++ b/images/virtualization-artifact/pkg/config/load_network_settings.go @@ -0,0 +1,31 @@ +/* +Copyright 2026 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 config + +import "os" + +const DisableTapVethBridgeVar = "DISABLE_TAP_VETH_BRIDGE" + +type NetworkSettings struct { + DisableTapVethBridge bool +} + +func LoadNetworkSettingsFromEnv() NetworkSettings { + return NetworkSettings{ + DisableTapVethBridge: os.Getenv(DisableTapVethBridgeVar) == "true", + } +} diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index 1a55e10b9b..9fadb91aa1 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -67,6 +67,7 @@ const ( type KVVMOptions struct { EnableParavirtualization bool OsType v1alpha2.OsType + DisableTapVethBridge bool // These options are for local development mode DisableHypervSyNIC bool @@ -92,6 +93,10 @@ func DefaultOptions(current *v1alpha2.VirtualMachine) KVVMOptions { } } +func (b *KVVM) Options() KVVMOptions { + return b.opts +} + func NewEmptyKVVM(name types.NamespacedName, opts KVVMOptions) *KVVM { return &KVVM{ opts: opts, diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go index 61edd64c33..2771238341 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go @@ -111,6 +111,11 @@ func ApplyVirtualMachineSpec( kvvm.SetUSBMigrationStrategy() kvvm.SetMetadata(vm.ObjectMeta) + if kvvm.Options().DisableTapVethBridge { + kvvm.SetKVVMIAnnotation(annotations.AnnDisableTapVethBridge, "true") + } else { + kvvm.RemoveKVVMIAnnotation(annotations.AnnDisableTapVethBridge) + } setNetwork(kvvm, networkSpec) kvvm.SetTablet("default-0") kvvm.SetNodeSelector(vm.Spec.NodeSelector, class.Spec.NodeSelector.MatchLabels) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go b/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go index ecf10128e0..5c8dec6348 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go @@ -92,7 +92,7 @@ var _ = Describe("MigratingHandler", func() { } reconcile := func() { - h := NewMigratingHandler(vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second)) + h := NewMigratingHandler(vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second, false)) _, err := h.Handle(ctx, vmState) Expect(err).NotTo(HaveOccurred()) err = resource.Update(context.Background()) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go b/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go index 2fc332e9ae..71fe47854e 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go @@ -47,18 +47,20 @@ import ( ) type MigrationVolumesService struct { - client client.Client - makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState) (*virtv1.VirtualMachine, error) - delay map[types.UID]time.Time - delayDuration time.Duration + client client.Client + makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool) (*virtv1.VirtualMachine, error) + delay map[types.UID]time.Time + delayDuration time.Duration + disableTapVethBridge bool } -func NewMigrationVolumesService(client client.Client, makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState) (*virtv1.VirtualMachine, error), delayDuration time.Duration) *MigrationVolumesService { +func NewMigrationVolumesService(client client.Client, makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool) (*virtv1.VirtualMachine, error), delayDuration time.Duration, disableTapVethBridge bool) *MigrationVolumesService { return &MigrationVolumesService{ - client: client, - makeKVVMFromSpec: makeKVVMFromSpec, - delay: make(map[types.UID]time.Time), - delayDuration: delayDuration, + client: client, + makeKVVMFromSpec: makeKVVMFromSpec, + delay: make(map[types.UID]time.Time), + delayDuration: delayDuration, + disableTapVethBridge: disableTapVethBridge, } } @@ -476,7 +478,7 @@ func (s MigrationVolumesService) fillContainerDiskImagePullPolicies(kvvm *virtv1 } func (s MigrationVolumesService) makeKVVMFromVirtualMachineSpec(ctx context.Context, vmState state.VirtualMachineState) (*virtv1.VirtualMachine, *virtv1.VirtualMachine, error) { - kvvm, err := s.makeKVVMFromSpec(ctx, vmState) + kvvm, err := s.makeKVVMFromSpec(ctx, vmState, s.disableTapVethBridge) if err != nil { return nil, nil, err } diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go index 56e7250a2d..6fa8658df8 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go @@ -62,22 +62,25 @@ func NewSyncKvvmHandler( recorder eventrecord.EventRecorderLogger, featureGate featuregate.FeatureGate, syncVolumesService syncVolumesService, + disableTapVethBridge bool, ) *SyncKvvmHandler { return &SyncKvvmHandler{ - dvcrSettings: dvcrSettings, - client: client, - recorder: recorder, - featureGate: featureGate, - syncVolumesService: syncVolumesService, + dvcrSettings: dvcrSettings, + client: client, + recorder: recorder, + featureGate: featureGate, + syncVolumesService: syncVolumesService, + disableTapVethBridge: disableTapVethBridge, } } type SyncKvvmHandler struct { - client client.Client - recorder eventrecord.EventRecorderLogger - dvcrSettings *dvcr.Settings - featureGate featuregate.FeatureGate - syncVolumesService syncVolumesService + client client.Client + recorder eventrecord.EventRecorderLogger + dvcrSettings *dvcr.Settings + featureGate featuregate.FeatureGate + syncVolumesService syncVolumesService + disableTapVethBridge bool } func (h *SyncKvvmHandler) Handle(ctx context.Context, s state.VirtualMachineState) (reconcile.Result, error) { @@ -343,7 +346,7 @@ func (h *SyncKvvmHandler) createKVVM(ctx context.Context, s state.VirtualMachine if s.VirtualMachine().IsEmpty() { return fmt.Errorf("the virtual machine is empty, please report a bug") } - kvvm, err := MakeKVVMFromVMSpec(ctx, s) + kvvm, err := MakeKVVMFromVMSpec(ctx, s, h.disableTapVethBridge) if err != nil { return fmt.Errorf("failed to make the internal virtual machine: %w", err) } @@ -372,7 +375,7 @@ func (h *SyncKvvmHandler) updateKVVM(ctx context.Context, s state.VirtualMachine return fmt.Errorf("the virtual machine is empty, please report a bug") } - newKVVM, err := MakeKVVMFromVMSpec(ctx, s) + newKVVM, err := MakeKVVMFromVMSpec(ctx, s, h.disableTapVethBridge) if err != nil { return fmt.Errorf("update internal virtual machine: make kvvm from the virtual machine spec: %w", err) } @@ -438,7 +441,7 @@ func saveKVVMDomainMemoryForPatching(prevKVVM, newKVVM *virtv1.VirtualMachine) * return nil } -func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState) (*virtv1.VirtualMachine, error) { +func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool) (*virtv1.VirtualMachine, error) { if s.VirtualMachine().IsEmpty() { return nil, nil } @@ -446,6 +449,7 @@ func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState) (*virt kvvmName := object.NamespacedName(current) kvvmOpts := kvbuilder.DefaultOptions(current) + kvvmOpts.DisableTapVethBridge = disableTapVethBridge kvvm, err := s.KVVM(ctx) if err != nil { diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go index 1e76e42ee3..5073ede77a 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go @@ -138,7 +138,7 @@ var _ = Describe("SyncKvvmHandler", func() { } reconcile := func() { - h := NewSyncKvvmHandler(nil, fakeClient, recorder, featuregates.Default(), vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second)) + h := NewSyncKvvmHandler(nil, fakeClient, recorder, featuregates.Default(), vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second, false), false) _, err := h.Handle(ctx, vmState) Expect(err).NotTo(HaveOccurred()) err = resource.Update(context.Background()) diff --git a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go index 21b3ba6100..44f9fd8b11 100644 --- a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go +++ b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go @@ -51,6 +51,7 @@ func SetupController( log *log.Logger, dvcrSettings *dvcr.Settings, firmwareImage string, + disableTapVethBridge bool, ) error { recorder := eventrecord.NewEventRecorderLogger(mgr, ControllerName) mgrCache := mgr.GetCache() @@ -58,7 +59,7 @@ func SetupController( blockDeviceService := service.NewBlockDeviceService(client) vmClassService := service.NewVirtualMachineClassService(client) - migrateVolumesService := vmservice.NewMigrationVolumesService(client, internal.MakeKVVMFromVMSpec, 10*time.Second) + migrateVolumesService := vmservice.NewMigrationVolumesService(client, internal.MakeKVVMFromVMSpec, 10*time.Second, disableTapVethBridge) handlers := []Handler{ internal.NewMaintenanceHandler(client), @@ -76,7 +77,7 @@ func SetupController( internal.NewPodHandler(client), internal.NewSizePolicyHandler(), internal.NewNetworkInterfaceHandler(featuregates.Default()), - internal.NewSyncKvvmHandler(dvcrSettings, client, recorder, featuregates.Default(), migrateVolumesService), + internal.NewSyncKvvmHandler(dvcrSettings, client, recorder, featuregates.Default(), migrateVolumesService, disableTapVethBridge), internal.NewSyncPowerStateHandler(client, recorder), internal.NewSyncMetadataHandler(client), internal.NewLifeCycleHandler(client, recorder), diff --git a/openapi/config-values.yaml b/openapi/config-values.yaml index e46d2362fc..3ded848587 100644 --- a/openapi/config-values.yaml +++ b/openapi/config-values.yaml @@ -252,6 +252,19 @@ properties: type: string minLength: 1 x-examples: ["sc-1", "sc-2"] + network: + type: object + description: | + Virtual machine networking settings. + properties: + disableTapVethBridge: + type: boolean + default: false + description: | + Disable tap-veth-bridge wiring for KubeVirt bridge interfaces. + + When enabled, the virtualization controller adds the `virtualization.deckhouse.io/disable-tap-veth-bridge=true` annotation to the KubeVirt VirtualMachineInstance template. + The KubeVirt network setup then skips creating the tap-veth-bridge wiring and bridge DHCP configurator for such VMIs. logLevel: type: string description: | diff --git a/templates/virtualization-controller/_helpers.tpl b/templates/virtualization-controller/_helpers.tpl index 3d799bf0fd..220c3a020c 100644 --- a/templates/virtualization-controller/_helpers.tpl +++ b/templates/virtualization-controller/_helpers.tpl @@ -18,6 +18,8 @@ true value: "1" - name: DISABLE_HYPERV_SYNIC value: "1" +- name: DISABLE_TAP_VETH_BRIDGE + value: {{ dig "network" "disableTapVethBridge" false .Values.virtualization.internal.moduleConfig | toString | quote }} - name: POD_NAMESPACE valueFrom: fieldRef: From 18a546bd0058958381b96c40830b79edfa7a4157 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Tue, 14 Apr 2026 15:23:15 +0300 Subject: [PATCH 2/3] feat(vm): add disable-tap-veth-bridge setting Signed-off-by: Dmitry Lopatin --- build/components/versions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/components/versions.yml b/build/components/versions.yml index 02d20930a8..d25bd9b984 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.6.2-v12n.24 + 3p-kubevirt: feat/vm/disable-tap-veth-bridge 3p-containerized-data-importer: v1.60.3-v12n.18 distribution: 2.8.3 package: From ba5c9bb9186ebf7f205f13c0256182b132ed4dad Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Thu, 16 Apr 2026 22:30:14 +0300 Subject: [PATCH 3/3] feat(vm): add disable DHCP VM setting Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 ++ .../cmd/virtualization-controller/main.go | 2 +- .../pkg/common/annotations/annotations.go | 2 ++ .../pkg/config/load_network_settings.go | 3 +++ .../pkg/controller/kvbuilder/kvvm.go | 1 + .../pkg/controller/kvbuilder/kvvm_utils.go | 5 +++++ .../pkg/controller/vm/internal/migrating_test.go | 2 +- .../vm/internal/service/migration_volumes.go | 8 +++++--- .../pkg/controller/vm/internal/sync_kvvm.go | 10 +++++++--- .../pkg/controller/vm/internal/sync_kvvm_test.go | 2 +- .../pkg/controller/vm/vm_controller.go | 5 +++-- openapi/config-values.yaml | 8 ++++++++ templates/virtualization-controller/_helpers.tpl | 2 ++ 13 files changed, 41 insertions(+), 11 deletions(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index f30560fba6..d50cf2dde8 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -13,8 +13,10 @@ secrets: - id: SOURCE_REPO value: {{ $.SOURCE_REPO }} shell: + installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | + echo "$date" echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index cb76caa4a5..23d4d542fe 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -349,7 +349,7 @@ func main() { } vmLogger := logger.NewControllerLogger(vm.ControllerName, logLevel, logOutput, logDebugVerbosity, logDebugControllerList) - if err = vm.SetupController(ctx, mgr, virtClient, vmLogger, dvcrSettings, firmwareImage, networkSettings.DisableTapVethBridge); err != nil { + if err = vm.SetupController(ctx, mgr, virtClient, vmLogger, dvcrSettings, firmwareImage, networkSettings.DisableTapVethBridge, networkSettings.DisableDHCP); err != nil { log.Error(err.Error()) os.Exit(1) } diff --git a/images/virtualization-artifact/pkg/common/annotations/annotations.go b/images/virtualization-artifact/pkg/common/annotations/annotations.go index 44e1564d84..bc3d5175ef 100644 --- a/images/virtualization-artifact/pkg/common/annotations/annotations.go +++ b/images/virtualization-artifact/pkg/common/annotations/annotations.go @@ -90,6 +90,8 @@ const ( AnnVMRestartRequested = AnnAPIGroupV + "/vm-restart-requested" // AnnDisableTapVethBridge disables tap-veth-bridge wiring for the VMI network setup in KubeVirt. AnnDisableTapVethBridge = AnnAPIGroupV + "/disable-tap-veth-bridge" + // AnnDisableDHCP disables bridge DHCP configurator for the VMI network setup in KubeVirt. + AnnDisableDHCP = AnnAPIGroupV + "/disable-dhcp" // AnnVMOPWorkloadUpdate is an annotation on vmop that represents a vmop created by workload-updater controller. AnnVMOPWorkloadUpdate = AnnAPIGroupV + "/workload-update" diff --git a/images/virtualization-artifact/pkg/config/load_network_settings.go b/images/virtualization-artifact/pkg/config/load_network_settings.go index 762ad89e66..1bf35cbd94 100644 --- a/images/virtualization-artifact/pkg/config/load_network_settings.go +++ b/images/virtualization-artifact/pkg/config/load_network_settings.go @@ -19,13 +19,16 @@ package config import "os" const DisableTapVethBridgeVar = "DISABLE_TAP_VETH_BRIDGE" +const DisableDHCPVar = "DISABLE_DHCP" type NetworkSettings struct { DisableTapVethBridge bool + DisableDHCP bool } func LoadNetworkSettingsFromEnv() NetworkSettings { return NetworkSettings{ DisableTapVethBridge: os.Getenv(DisableTapVethBridgeVar) == "true", + DisableDHCP: os.Getenv(DisableDHCPVar) == "true", } } diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index 9fadb91aa1..ddc3077c4e 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -68,6 +68,7 @@ type KVVMOptions struct { EnableParavirtualization bool OsType v1alpha2.OsType DisableTapVethBridge bool + DisableDHCP bool // These options are for local development mode DisableHypervSyNIC bool diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go index 2771238341..20bac3ee64 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go @@ -116,6 +116,11 @@ func ApplyVirtualMachineSpec( } else { kvvm.RemoveKVVMIAnnotation(annotations.AnnDisableTapVethBridge) } + if kvvm.Options().DisableDHCP { + kvvm.SetKVVMIAnnotation(annotations.AnnDisableDHCP, "true") + } else { + kvvm.RemoveKVVMIAnnotation(annotations.AnnDisableDHCP) + } setNetwork(kvvm, networkSpec) kvvm.SetTablet("default-0") kvvm.SetNodeSelector(vm.Spec.NodeSelector, class.Spec.NodeSelector.MatchLabels) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go b/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go index 5c8dec6348..1d1684a405 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/migrating_test.go @@ -92,7 +92,7 @@ var _ = Describe("MigratingHandler", func() { } reconcile := func() { - h := NewMigratingHandler(vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second, false)) + h := NewMigratingHandler(vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second, false, false)) _, err := h.Handle(ctx, vmState) Expect(err).NotTo(HaveOccurred()) err = resource.Update(context.Background()) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go b/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go index 71fe47854e..1a73a395de 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/service/migration_volumes.go @@ -48,19 +48,21 @@ import ( type MigrationVolumesService struct { client client.Client - makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool) (*virtv1.VirtualMachine, error) + makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool, disableDHCP bool) (*virtv1.VirtualMachine, error) delay map[types.UID]time.Time delayDuration time.Duration disableTapVethBridge bool + disableDHCP bool } -func NewMigrationVolumesService(client client.Client, makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool) (*virtv1.VirtualMachine, error), delayDuration time.Duration, disableTapVethBridge bool) *MigrationVolumesService { +func NewMigrationVolumesService(client client.Client, makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool, disableDHCP bool) (*virtv1.VirtualMachine, error), delayDuration time.Duration, disableTapVethBridge bool, disableDHCP bool) *MigrationVolumesService { return &MigrationVolumesService{ client: client, makeKVVMFromSpec: makeKVVMFromSpec, delay: make(map[types.UID]time.Time), delayDuration: delayDuration, disableTapVethBridge: disableTapVethBridge, + disableDHCP: disableDHCP, } } @@ -478,7 +480,7 @@ func (s MigrationVolumesService) fillContainerDiskImagePullPolicies(kvvm *virtv1 } func (s MigrationVolumesService) makeKVVMFromVirtualMachineSpec(ctx context.Context, vmState state.VirtualMachineState) (*virtv1.VirtualMachine, *virtv1.VirtualMachine, error) { - kvvm, err := s.makeKVVMFromSpec(ctx, vmState, s.disableTapVethBridge) + kvvm, err := s.makeKVVMFromSpec(ctx, vmState, s.disableTapVethBridge, s.disableDHCP) if err != nil { return nil, nil, err } diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go index 6fa8658df8..adbd3fdc91 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go @@ -63,6 +63,7 @@ func NewSyncKvvmHandler( featureGate featuregate.FeatureGate, syncVolumesService syncVolumesService, disableTapVethBridge bool, + disableDHCP bool, ) *SyncKvvmHandler { return &SyncKvvmHandler{ dvcrSettings: dvcrSettings, @@ -71,6 +72,7 @@ func NewSyncKvvmHandler( featureGate: featureGate, syncVolumesService: syncVolumesService, disableTapVethBridge: disableTapVethBridge, + disableDHCP: disableDHCP, } } @@ -81,6 +83,7 @@ type SyncKvvmHandler struct { featureGate featuregate.FeatureGate syncVolumesService syncVolumesService disableTapVethBridge bool + disableDHCP bool } func (h *SyncKvvmHandler) Handle(ctx context.Context, s state.VirtualMachineState) (reconcile.Result, error) { @@ -346,7 +349,7 @@ func (h *SyncKvvmHandler) createKVVM(ctx context.Context, s state.VirtualMachine if s.VirtualMachine().IsEmpty() { return fmt.Errorf("the virtual machine is empty, please report a bug") } - kvvm, err := MakeKVVMFromVMSpec(ctx, s, h.disableTapVethBridge) + kvvm, err := MakeKVVMFromVMSpec(ctx, s, h.disableTapVethBridge, h.disableDHCP) if err != nil { return fmt.Errorf("failed to make the internal virtual machine: %w", err) } @@ -375,7 +378,7 @@ func (h *SyncKvvmHandler) updateKVVM(ctx context.Context, s state.VirtualMachine return fmt.Errorf("the virtual machine is empty, please report a bug") } - newKVVM, err := MakeKVVMFromVMSpec(ctx, s, h.disableTapVethBridge) + newKVVM, err := MakeKVVMFromVMSpec(ctx, s, h.disableTapVethBridge, h.disableDHCP) if err != nil { return fmt.Errorf("update internal virtual machine: make kvvm from the virtual machine spec: %w", err) } @@ -441,7 +444,7 @@ func saveKVVMDomainMemoryForPatching(prevKVVM, newKVVM *virtv1.VirtualMachine) * return nil } -func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool) (*virtv1.VirtualMachine, error) { +func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge bool, disableDHCP bool) (*virtv1.VirtualMachine, error) { if s.VirtualMachine().IsEmpty() { return nil, nil } @@ -450,6 +453,7 @@ func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState, disabl kvvmOpts := kvbuilder.DefaultOptions(current) kvvmOpts.DisableTapVethBridge = disableTapVethBridge + kvvmOpts.DisableDHCP = disableDHCP kvvm, err := s.KVVM(ctx) if err != nil { diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go index 5073ede77a..a288a73dc2 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm_test.go @@ -138,7 +138,7 @@ var _ = Describe("SyncKvvmHandler", func() { } reconcile := func() { - h := NewSyncKvvmHandler(nil, fakeClient, recorder, featuregates.Default(), vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second, false), false) + h := NewSyncKvvmHandler(nil, fakeClient, recorder, featuregates.Default(), vmservice.NewMigrationVolumesService(fakeClient, MakeKVVMFromVMSpec, 10*time.Second, false, false), false, false) _, err := h.Handle(ctx, vmState) Expect(err).NotTo(HaveOccurred()) err = resource.Update(context.Background()) diff --git a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go index 44f9fd8b11..3ff7b81cb0 100644 --- a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go +++ b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go @@ -52,6 +52,7 @@ func SetupController( dvcrSettings *dvcr.Settings, firmwareImage string, disableTapVethBridge bool, + disableDHCP bool, ) error { recorder := eventrecord.NewEventRecorderLogger(mgr, ControllerName) mgrCache := mgr.GetCache() @@ -59,7 +60,7 @@ func SetupController( blockDeviceService := service.NewBlockDeviceService(client) vmClassService := service.NewVirtualMachineClassService(client) - migrateVolumesService := vmservice.NewMigrationVolumesService(client, internal.MakeKVVMFromVMSpec, 10*time.Second, disableTapVethBridge) + migrateVolumesService := vmservice.NewMigrationVolumesService(client, internal.MakeKVVMFromVMSpec, 10*time.Second, disableTapVethBridge, disableDHCP) handlers := []Handler{ internal.NewMaintenanceHandler(client), @@ -77,7 +78,7 @@ func SetupController( internal.NewPodHandler(client), internal.NewSizePolicyHandler(), internal.NewNetworkInterfaceHandler(featuregates.Default()), - internal.NewSyncKvvmHandler(dvcrSettings, client, recorder, featuregates.Default(), migrateVolumesService, disableTapVethBridge), + internal.NewSyncKvvmHandler(dvcrSettings, client, recorder, featuregates.Default(), migrateVolumesService, disableTapVethBridge, disableDHCP), internal.NewSyncPowerStateHandler(client, recorder), internal.NewSyncMetadataHandler(client), internal.NewLifeCycleHandler(client, recorder), diff --git a/openapi/config-values.yaml b/openapi/config-values.yaml index 3ded848587..1e42890ff3 100644 --- a/openapi/config-values.yaml +++ b/openapi/config-values.yaml @@ -265,6 +265,14 @@ properties: When enabled, the virtualization controller adds the `virtualization.deckhouse.io/disable-tap-veth-bridge=true` annotation to the KubeVirt VirtualMachineInstance template. The KubeVirt network setup then skips creating the tap-veth-bridge wiring and bridge DHCP configurator for such VMIs. + disableDHCP: + type: boolean + default: false + description: | + Disable bridge DHCP configurator for KubeVirt bridge interfaces. + + When enabled, the virtualization controller adds the `virtualization.deckhouse.io/disable-dhcp=true` annotation to the KubeVirt VirtualMachineInstance template. + The KubeVirt network setup then skips creating the bridge DHCP configurator for such VMIs. logLevel: type: string description: | diff --git a/templates/virtualization-controller/_helpers.tpl b/templates/virtualization-controller/_helpers.tpl index 220c3a020c..626efadf66 100644 --- a/templates/virtualization-controller/_helpers.tpl +++ b/templates/virtualization-controller/_helpers.tpl @@ -20,6 +20,8 @@ true value: "1" - name: DISABLE_TAP_VETH_BRIDGE value: {{ dig "network" "disableTapVethBridge" false .Values.virtualization.internal.moduleConfig | toString | quote }} +- name: DISABLE_DHCP + value: {{ dig "network" "disableDHCP" false .Values.virtualization.internal.moduleConfig | toString | quote }} - name: POD_NAMESPACE valueFrom: fieldRef: