diff --git a/build/components/versions.yml b/build/components/versions.yml index daf7a6a989..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.28 + 3p-kubevirt: feat/vm/disable-tap-veth-bridge 3p-containerized-data-importer: v1.60.3-v12n.18 distribution: 2.8.3 package: diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 6381ba5eae..686a306528 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 @@ -28,6 +30,8 @@ altPackages: - pkg-config - libtool - gcc-c++ +- clang +- libbpf-devel packages: - libmnl - ncurses @@ -113,6 +117,7 @@ shell: - export GOOS=linux - export GOARCH=amd64 - export CGO_ENABLED=0 + - export BPF_CLANG=clang - echo ============== Build container-disk =================== {{- $_ := set $ "ProjectName" (list .ImageName "container-disk" | join "/") }} @@ -197,10 +202,27 @@ shell: {{- include "image-build.build" (set $ "BuildCommand" `go build -ldflags="-s -w" -o /kubevirt-binaries/virt-operator ./cmd/virt-operator/`) | nindent 6 }} - echo ============== Build sidecars ========================= - {{- $_ := set $ "ProjectName" (list .ImageName "sidecars" | join "/") }} + - | + cd /kubevirt + echo "Sidecars cmd list:" + ls -la cmd/sidecars/ + echo "---" + {{- $_ := set $ "ProjectName" (list $.ImageName "sidecars" | join "/") }} - | {{- include "image-build.build" (set $ "BuildCommand" `go build -ldflags="-s -w" -o /kubevirt-binaries/sidecars ./cmd/sidecars/`) | nindent 6 }} + - echo ============== Build network-bpf-bridge-binding ======= + {{- $_ := set $ "ProjectName" (list $.ImageName "network-bpf-bridge-binding" | join "/") }} + - | + {{- include "image-build.build" (set $ "BuildCommand" `go build -ldflags="-s -w" -o /kubevirt-binaries/network-bpf-bridge-binding ./cmd/sidecars/network-bpf-bridge-binding/`) | nindent 6 }} + + - echo ============== Build bpf_bridge.o ===================== + {{- $_ := set $ "ProjectName" (list $.ImageName "bpf-bridge-obj" | join "/") }} + - mkdir -p /kubevirt-binaries/network-bpf-bridge-binding-assets + - | + {{- include "image-build.build" (set $ "BuildCommand" `clang -O2 -g -target bpf -I/usr/include -c ./cmd/sidecars/network-bpf-bridge-binding/bpf/bpf_bridge.c -o /kubevirt-binaries/network-bpf-bridge-binding-assets/bpf_bridge.o`) | nindent 6 }} + - echo "Built bpf object:" && ls -l /kubevirt-binaries/network-bpf-bridge-binding-assets/ && file /kubevirt-binaries/network-bpf-bridge-binding-assets/bpf_bridge.o || true + - echo ============== Build virtctl ========================== {{- $_ := set $ "ProjectName" (list .ImageName "virtctl" | join "/") }} - | diff --git a/images/virt-launcher/werf.inc.yaml b/images/virt-launcher/werf.inc.yaml index 89dcb3dceb..bd5afce159 100644 --- a/images/virt-launcher/werf.inc.yaml +++ b/images/virt-launcher/werf.inc.yaml @@ -77,6 +77,7 @@ altLibs: - psmisc - msulogin - strace + - iproute2 binaries: # GNU utils (required to run swtpm). - /usr/bin/certtool @@ -196,11 +197,18 @@ import: before: setup includePaths: - container-disk + - network-bpf-bridge-binding - virt-freezer - virt-launcher - virt-launcher-monitor - virt-probe - virt-tail +- image: {{ .ModuleNamePrefix }}virt-artifact + add: /kubevirt-binaries/network-bpf-bridge-binding-assets/ + to: /relocate/opt/network-bpf-bridge-binding + before: setup + includePaths: + - bpf_bridge.o - image: {{ .ModuleNamePrefix }}virt-artifact add: /kubevirt-binaries to: /relocate/etc/libvirt/hooks/qemu @@ -246,6 +254,8 @@ import: after: setup includePaths: - sbin/tc + - usr/include + - usr/lib - image: {{ .ModuleNamePrefix }}{{ .ImageName }}-cbuilder add: /bins @@ -392,6 +402,23 @@ shell: echo "Create symlink for run -> var/run " ln -s var/run run + echo "Copy system tc and runtime dirs" + mkdir -p /relocate/usr/sbin + cp -a /usr/sbin/tc /relocate/usr/sbin/tc + if [ -d /usr/lib/tc ]; then + mkdir -p /relocate/usr/lib + cp -a /usr/lib/tc /relocate/usr/lib/tc + fi + if [ -d /usr/lib64/tc ]; then + mkdir -p /relocate/usr/lib64 + cp -a /usr/lib64/tc /relocate/usr/lib64/tc + fi + + - | + echo "iproute2 runtime contents in /relocate/usr:" + find /relocate/usr \( -path "/relocate/usr/sbin/tc" -o -path "/relocate/usr/lib/tc" -o -path "/relocate/usr/lib/tc/*" -o -path "/relocate/usr/lib64/tc" -o -path "/relocate/usr/lib64/tc/*" \) | sort || true + ls -ld /relocate/usr/lib/tc /relocate/usr/lib64/tc 2>/dev/null || true + # /etc/libvirt-init will be copied back into /etc/libvirt at runtime. This is necessary because we configure libvirt to mount /etc/libvirt and set readOnlyRootFilesystem for other directories. # DO NOT REMOVE. node-labeler.sh uses /etc/libvirt. - | diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index 75669f228b..f1db0e7b9a 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -208,6 +208,8 @@ func main() { os.Exit(1) } + networkSettings := appconfig.LoadNetworkSettingsFromEnv() + // Get a config to talk to the apiserver cfg, err := config.GetConfig() if err != nil { @@ -360,7 +362,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, 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 a487cab2b2..b318f95bc7 100644 --- a/images/virtualization-artifact/pkg/common/annotations/annotations.go +++ b/images/virtualization-artifact/pkg/common/annotations/annotations.go @@ -88,6 +88,10 @@ 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" + // 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/common/network/spec.go b/images/virtualization-artifact/pkg/common/network/spec.go index 4d1976cbc9..c89dd25a1b 100644 --- a/images/virtualization-artifact/pkg/common/network/spec.go +++ b/images/virtualization-artifact/pkg/common/network/spec.go @@ -30,6 +30,16 @@ func CreateNetworkSpec(vm *v1alpha2.VirtualMachine, vmmacs []*v1alpha2.VirtualMa macPool := NewMacAddressPool(vm, vmmacs) var specs InterfaceSpecList + if len(vm.Spec.Networks) == 0 { + return InterfaceSpecList{{ + ID: 1, + Type: v1alpha2.NetworksTypeMain, + Name: "", + InterfaceName: NameDefaultInterface, + MAC: "", + }} + } + for _, net := range vm.Spec.Networks { if net.Type == v1alpha2.NetworksTypeMain { specs = append(specs, createMainInterfaceSpec(net)) 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..a3547b4ac9 --- /dev/null +++ b/images/virtualization-artifact/pkg/config/load_network_settings.go @@ -0,0 +1,36 @@ +/* +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" + 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 6eeddc1ad9..fc21abc3ea 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -28,6 +28,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/klog/v2" "k8s.io/utils/ptr" virtv1 "kubevirt.io/api/core/v1" @@ -67,6 +68,8 @@ const ( type KVVMOptions struct { EnableParavirtualization bool OsType v1alpha2.OsType + DisableTapVethBridge bool + DisableDHCP bool // These options are for local development mode DisableHypervSyNIC bool @@ -92,6 +95,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, @@ -740,8 +747,10 @@ func (b *KVVM) GetOSSettings() map[string]interface{} { } func (b *KVVM) ClearNetworkInterfaces() { + klog.Infof("kvbuilder: ClearNetworkInterfaces before ifaces=%d nets=%d", len(b.Resource.Spec.Template.Spec.Domain.Devices.Interfaces), len(b.Resource.Spec.Template.Spec.Networks)) b.Resource.Spec.Template.Spec.Networks = nil b.Resource.Spec.Template.Spec.Domain.Devices.Interfaces = nil + klog.Infof("kvbuilder: ClearNetworkInterfaces after ifaces=%d nets=%d", len(b.Resource.Spec.Template.Spec.Domain.Devices.Interfaces), len(b.Resource.Spec.Template.Spec.Networks)) } func (b *KVVM) SetNetworkInterface(name, macAddress string, acpiIndex int) { @@ -765,7 +774,13 @@ func (b *KVVM) SetNetworkInterface(name, macAddress string, acpiIndex int) { Model: devPreset.InterfaceModel, ACPIIndex: acpiIndex, } - iface.Bridge = &virtv1.InterfaceBridge{} + if name == "default" { + iface.Binding = &virtv1.PluginBinding{Name: "bpfbridge"} + klog.Infof("kvbuilder: using bpfbridge binding for default interface %q", name) + } else { + iface.Bridge = &virtv1.InterfaceBridge{} + klog.Infof("kvbuilder: using bridge binding for non-default interface %q", name) + } if macAddress != "" { iface.MacAddress = macAddress } diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go index 61edd64c33..2124f815a7 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go @@ -24,6 +24,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/klog/v2" "k8s.io/utils/ptr" virtv1 "kubevirt.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -96,6 +97,7 @@ func ApplyVirtualMachineSpec( ipAddress string, networkSpec network.InterfaceSpecList, ) error { + klog.Infof("kvbuilder: ApplyVirtualMachineSpec start vm=%s/%s networks=%d existingIfaces=%d", vm.Namespace, vm.Name, len(networkSpec), len(kvvm.Resource.Spec.Template.Spec.Domain.Devices.Interfaces)) if err := kvvm.SetRunPolicy(vm.Spec.RunPolicy); err != nil { return err } @@ -111,6 +113,16 @@ func ApplyVirtualMachineSpec( kvvm.SetUSBMigrationStrategy() kvvm.SetMetadata(vm.ObjectMeta) + if kvvm.Options().DisableTapVethBridge { + kvvm.SetKVVMIAnnotation(annotations.AnnDisableTapVethBridge, "true") + } 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) @@ -355,10 +367,24 @@ func ApplyMigrationVolumes(kvvm *KVVM, vm *v1alpha2.VirtualMachine, vdsByName ma } func setNetwork(kvvm *KVVM, networkSpec network.InterfaceSpecList) { + klog.Infof("kvbuilder: setNetwork start specLen=%d currentIfaces=%d currentNets=%d", len(networkSpec), len(kvvm.Resource.Spec.Template.Spec.Domain.Devices.Interfaces), len(kvvm.Resource.Spec.Template.Spec.Networks)) + for idx, n := range networkSpec { + klog.Infof("kvbuilder: setNetwork spec[%d] ifName=%q mac=%q id=%d type=%q", idx, n.InterfaceName, n.MAC, n.ID, n.Type) + } kvvm.ClearNetworkInterfaces() + klog.Infof("kvbuilder: after ClearNetworkInterfaces ifaces=%d nets=%d", len(kvvm.Resource.Spec.Template.Spec.Domain.Devices.Interfaces), len(kvvm.Resource.Spec.Template.Spec.Networks)) for _, n := range networkSpec { kvvm.SetNetworkInterface(n.InterfaceName, n.MAC, n.ID) } + klog.Infof("kvbuilder: setNetwork done resultingIfaces=%d resultingNets=%d", len(kvvm.Resource.Spec.Template.Spec.Domain.Devices.Interfaces), len(kvvm.Resource.Spec.Template.Spec.Networks)) + for idx, iface := range kvvm.Resource.Spec.Template.Spec.Domain.Devices.Interfaces { + bindingName := "" + if iface.Binding != nil { + bindingName = iface.Binding.Name + } + isBridge := iface.Bridge != nil + klog.Infof("kvbuilder: resulting iface[%d] name=%q bridge=%t binding=%q", idx, iface.Name, isBridge, bindingName) + } } func setNetworksAnnotation(kvvm *KVVM, networkSpec network.InterfaceSpecList) error { 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 6eef76e17f..fe6a704abd 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, 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..51c0126ab8 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,22 @@ 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, 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) (*virtv1.VirtualMachine, error), delayDuration time.Duration) *MigrationVolumesService { +func NewMigrationVolumesService(client client.Client, makeKVVMFromSpec func(ctx context.Context, s state.VirtualMachineState, disableTapVethBridge, disableDHCP bool) (*virtv1.VirtualMachine, error), delayDuration time.Duration, disableTapVethBridge, disableDHCP 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, + disableDHCP: disableDHCP, } } @@ -476,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) + 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 dbbd4db4be..fb0669679c 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go @@ -63,22 +63,28 @@ func NewSyncKvvmHandler( recorder eventrecord.EventRecorderLogger, featureGate featuregate.FeatureGate, syncVolumesService syncVolumesService, + disableTapVethBridge bool, + disableDHCP 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, + disableDHCP: disableDHCP, } } 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 + disableDHCP bool } func (h *SyncKvvmHandler) Handle(ctx context.Context, s state.VirtualMachineState) (reconcile.Result, error) { @@ -349,7 +355,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, h.disableDHCP) if err != nil { return fmt.Errorf("failed to make the internal virtual machine: %w", err) } @@ -378,7 +384,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, h.disableDHCP) if err != nil { return fmt.Errorf("update internal virtual machine: make kvvm from the virtual machine spec: %w", err) } @@ -444,7 +450,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, disableDHCP bool) (*virtv1.VirtualMachine, error) { if s.VirtualMachine().IsEmpty() { return nil, nil } @@ -452,6 +458,8 @@ func MakeKVVMFromVMSpec(ctx context.Context, s state.VirtualMachineState) (*virt kvvmName := object.NamespacedName(current) 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 1e76e42ee3..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)) + 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 21b3ba6100..3ff7b81cb0 100644 --- a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go +++ b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go @@ -51,6 +51,8 @@ func SetupController( log *log.Logger, dvcrSettings *dvcr.Settings, firmwareImage string, + disableTapVethBridge bool, + disableDHCP bool, ) error { recorder := eventrecord.NewEventRecorderLogger(mgr, ControllerName) mgrCache := mgr.GetCache() @@ -58,7 +60,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, disableDHCP) handlers := []Handler{ internal.NewMaintenanceHandler(client), @@ -76,7 +78,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, 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 e46d2362fc..1e42890ff3 100644 --- a/openapi/config-values.yaml +++ b/openapi/config-values.yaml @@ -252,6 +252,27 @@ 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. + 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/kubevirt/kubevirt.yaml b/templates/kubevirt/kubevirt.yaml index 31656db4cc..d6d8fe9ba0 100644 --- a/templates/kubevirt/kubevirt.yaml +++ b/templates/kubevirt/kubevirt.yaml @@ -39,6 +39,11 @@ spec: {{- end }} evictionStrategy: LiveMigrate vmRolloutStrategy: LiveUpdate + network: + binding: + bpfbridge: + sidecarImage: {{ include "helm_lib_module_image" (list . "virtLauncher") }} + migration: {} developerConfiguration: logVerbosity: virtLauncher: {{ $logVerbosity }} diff --git a/templates/virtualization-controller/_helpers.tpl b/templates/virtualization-controller/_helpers.tpl index 3d799bf0fd..626efadf66 100644 --- a/templates/virtualization-controller/_helpers.tpl +++ b/templates/virtualization-controller/_helpers.tpl @@ -18,6 +18,10 @@ 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: DISABLE_DHCP + value: {{ dig "network" "disableDHCP" false .Values.virtualization.internal.moduleConfig | toString | quote }} - name: POD_NAMESPACE valueFrom: fieldRef: