diff --git a/go-controller/pkg/kubevirt/pod.go b/go-controller/pkg/kubevirt/pod.go index 48917c7ae0b..fc71696d148 100644 --- a/go-controller/pkg/kubevirt/pod.go +++ b/go-controller/pkg/kubevirt/pod.go @@ -355,7 +355,9 @@ func IsPodOwnedByVirtualMachine(pod *corev1.Pod) bool { // IsPodAllowedForMigration determines whether a given pod is eligible for live migration func IsPodAllowedForMigration(pod *corev1.Pod, netInfo util.NetInfo) bool { - return IsPodOwnedByVirtualMachine(pod) && netInfo.TopologyType() == ovntypes.Layer2Topology + return IsPodOwnedByVirtualMachine(pod) && + (netInfo.TopologyType() == ovntypes.Layer2Topology || + netInfo.TopologyType() == ovntypes.LocalnetTopology) } func isTargetPodReady(targetPod *corev1.Pod) bool { diff --git a/go-controller/pkg/ovn/base_network_controller_pods.go b/go-controller/pkg/ovn/base_network_controller_pods.go index 90444f1fbdf..d2881c28d5b 100644 --- a/go-controller/pkg/ovn/base_network_controller_pods.go +++ b/go-controller/pkg/ovn/base_network_controller_pods.go @@ -566,15 +566,25 @@ func (bnc *BaseNetworkController) addLogicalPortToNetwork(pod *kapi.Pod, nadName return nil, nil, nil, false, err } - // set addresses on the port - // LSP addresses in OVN are a single space-separated value + lsp.Enabled = enable + if lsp.Enabled != nil { + customFields = append(customFields, libovsdbops.LogicalSwitchPortEnabled) + } + addresses = []string{podAnnotation.MAC.String()} for _, podIfAddr := range podAnnotation.IPs { addresses[0] = addresses[0] + " " + podIfAddr.IP.String() } - lsp.Addresses = addresses - customFields = append(customFields, libovsdbops.LogicalSwitchPortAddresses) + // Skip address configuration if LSP is disabled since it will install + // l2 look up flows that harms some topologies + if lsp.Enabled == nil || *lsp.Enabled { + // set addresses on the port + // LSP addresses in OVN are a single space-separated value + + lsp.Addresses = addresses + customFields = append(customFields, libovsdbops.LogicalSwitchPortAddresses) + } // add external ids lsp.ExternalIDs = map[string]string{"namespace": pod.Namespace, "pod": "true"} @@ -602,11 +612,6 @@ func (bnc *BaseNetworkController) addLogicalPortToNetwork(pod *kapi.Pod, nadName if len(lsp.Options) != 0 { customFields = append(customFields, libovsdbops.LogicalSwitchPortOptions) } - - lsp.Enabled = enable - if lsp.Enabled != nil { - customFields = append(customFields, libovsdbops.LogicalSwitchPortEnabled) - } ops, err = libovsdbops.CreateOrUpdateLogicalSwitchPortsOnSwitchWithCustomFieldsOps(bnc.nbClient, nil, ls, customFields, lsp) if err != nil { return nil, nil, nil, false, diff --git a/go-controller/pkg/ovn/base_network_controller_secondary.go b/go-controller/pkg/ovn/base_network_controller_secondary.go index b18d963db6b..98cf3465744 100644 --- a/go-controller/pkg/ovn/base_network_controller_secondary.go +++ b/go-controller/pkg/ovn/base_network_controller_secondary.go @@ -356,7 +356,9 @@ func (bsnc *BaseSecondaryNetworkController) addLogicalPortToNetworkForNAD(pod *c } if shouldHandleLiveMigration && - kubevirtLiveMigrationStatus.IsTargetDomainReady() { + kubevirtLiveMigrationStatus.IsTargetDomainReady() && + // At localnet there is no source pod remote LSP so it should be skipped + (bsnc.TopologyType() != types.LocalnetTopology || bsnc.isPodScheduledinLocalZone(kubevirtLiveMigrationStatus.SourcePod)) { ops, err = bsnc.disableLiveMigrationSourceLSPOps(kubevirtLiveMigrationStatus, nadName, ops) if err != nil { return fmt.Errorf("failed to create LSP ops for source pod during Live-migration status: %w", err) @@ -444,7 +446,7 @@ func (bsnc *BaseSecondaryNetworkController) removePodForSecondaryNetwork(pod *co } var alreadyProcessed bool - for nadName := range podNetworks { + for nadName, podAnnotation := range podNetworks { if !bsnc.HasNAD(nadName) { continue } @@ -471,7 +473,7 @@ func (bsnc *BaseSecondaryNetworkController) removePodForSecondaryNetwork(pod *co } if kubevirt.IsPodAllowedForMigration(pod, bsnc.GetNetInfo()) { - if err = bsnc.enableSourceLSPFailedLiveMigration(pod, nadName); err != nil { + if err = bsnc.enableSourceLSPFailedLiveMigration(pod, nadName, podAnnotation.MAC, podAnnotation.IPs); err != nil { return err } } @@ -896,15 +898,34 @@ func (bsnc *BaseSecondaryNetworkController) requireDHCP(pod *corev1.Pod) bool { bsnc.TopologyType() == types.Layer2Topology } -func (bsnc *BaseSecondaryNetworkController) setPodLogicalSwitchPortEnabledField( - pod *corev1.Pod, nadName string, ops []ovsdb.Operation, enabled bool) ([]ovsdb.Operation, *nbdb.LogicalSwitchPort, error) { +func (bsnc *BaseSecondaryNetworkController) setPodLogicalSwitchPortAddressesAndEnabledField( + pod *corev1.Pod, nadName string, mac string, ips []string, enabled bool, ops []ovsdb.Operation) ([]ovsdb.Operation, *nbdb.LogicalSwitchPort, error) { lsp := &nbdb.LogicalSwitchPort{Name: bsnc.GetLogicalPortName(pod, nadName)} lsp.Enabled = ptr.To(enabled) + customFields := []libovsdbops.ModelUpdateField{ + libovsdbops.LogicalSwitchPortEnabled, + libovsdbops.LogicalSwitchPortAddresses, + } + if !enabled { + lsp.Addresses = nil + } else { + if len(mac) == 0 || len(ips) == 0 { + return nil, nil, fmt.Errorf("failed to configure addresses for lsp, missing mac and ips for pod %s", pod.Name) + } + + // Remove length + for i, ip := range ips { + ips[i] = strings.Split(ip, "/")[0] + } + + lsp.Addresses = []string{ + strings.Join(append([]string{mac}, ips...), " "), + } + } switchName, err := bsnc.getExpectedSwitchName(pod) if err != nil { return nil, nil, fmt.Errorf("failed to fetch switch name for pod %s: %w", pod.Name, err) } - customFields := []libovsdbops.ModelUpdateField{libovsdbops.LogicalSwitchPortEnabled} ops, err = libovsdbops.UpdateLogicalSwitchPortsOnSwitchWithCustomFieldsOps(bsnc.nbClient, ops, &nbdb.LogicalSwitch{Name: switchName}, customFields, lsp) if err != nil { return nil, nil, fmt.Errorf("failed updating logical switch port %+v on switch %s: %w", *lsp, switchName, err) @@ -916,11 +937,11 @@ func (bsnc *BaseSecondaryNetworkController) disableLiveMigrationSourceLSPOps( kubevirtLiveMigrationStatus *kubevirt.LiveMigrationStatus, nadName string, ops []ovsdb.Operation) ([]ovsdb.Operation, error) { // closing the sourcePod lsp to ensure traffic goes to the now ready targetPod. - ops, _, err := bsnc.setPodLogicalSwitchPortEnabledField(kubevirtLiveMigrationStatus.SourcePod, nadName, ops, false) + ops, _, err := bsnc.setPodLogicalSwitchPortAddressesAndEnabledField(kubevirtLiveMigrationStatus.SourcePod, nadName, "", nil, false, ops) return ops, err } -func (bsnc *BaseSecondaryNetworkController) enableSourceLSPFailedLiveMigration(pod *corev1.Pod, nadName string) error { +func (bsnc *BaseSecondaryNetworkController) enableSourceLSPFailedLiveMigration(pod *corev1.Pod, nadName string, mac string, ips []string) error { kubevirtLiveMigrationStatus, err := kubevirt.DiscoverLiveMigrationStatus(bsnc.watchFactory, pod) if err != nil { return fmt.Errorf("failed to discover Live-migration status after pod termination: %w", err) @@ -931,7 +952,7 @@ func (bsnc *BaseSecondaryNetworkController) enableSourceLSPFailedLiveMigration(p return nil } // make sure sourcePod lsp is enabled if migration failed after DomainReady was set. - ops, sourcePodLsp, err := bsnc.setPodLogicalSwitchPortEnabledField(kubevirtLiveMigrationStatus.SourcePod, nadName, nil, true) + ops, sourcePodLsp, err := bsnc.setPodLogicalSwitchPortAddressesAndEnabledField(kubevirtLiveMigrationStatus.SourcePod, nadName, mac, ips, true, nil) if err != nil { return fmt.Errorf("failed to set source Pod lsp to enabled after migration failed: %w", err) } diff --git a/go-controller/pkg/ovn/multihoming_test.go b/go-controller/pkg/ovn/multihoming_test.go index f04052c6519..f31ea5e949f 100644 --- a/go-controller/pkg/ovn/multihoming_test.go +++ b/go-controller/pkg/ovn/multihoming_test.go @@ -158,6 +158,9 @@ func (em *secondaryNetworkExpectationMachine) expectedLogicalSwitchesAndPortsWit lsp := newExpectedSwitchPort(lspUUID, portName, podAddr, pod, ocInfo.bnc, nad) if expectedPodLspEnabled != nil { lsp.Enabled = expectedPodLspEnabled[pod.podName] + if lsp.Enabled != nil && !*lsp.Enabled { + lsp.Addresses = nil + } } if pod.noIfaceIdVer { @@ -429,6 +432,13 @@ func enableICFeatureConfig() *config.OVNKubernetesFeatureConfig { return featConfig } +func enableNonICFeatureConfig() *config.OVNKubernetesFeatureConfig { + featConfig := minimalFeatureConfig() + featConfig.EnableInterconnect = false + featConfig.EnablePersistentIPs = true + return featConfig +} + type testConfigOpt = func(*testConfiguration) func icClusterTestConfiguration(opts ...testConfigOpt) testConfiguration { @@ -443,7 +453,9 @@ func icClusterTestConfiguration(opts ...testConfigOpt) testConfiguration { } func nonICClusterTestConfiguration(opts ...testConfigOpt) testConfiguration { - config := testConfiguration{} + config := testConfiguration{ + configToOverride: enableNonICFeatureConfig(), + } for _, opt := range opts { opt(&config) } @@ -464,8 +476,14 @@ func newMultiHomedKubevirtPod(vmName string, liveMigrationInfo liveMigrationPodI func newMultiHomedPod(testPod testPod, multiHomingConfigs ...secondaryNetInfo) *v1.Pod { pod := newPod(testPod.namespace, testPod.podName, testPod.nodeName, testPod.podIP) var secondaryNetworks []nadapi.NetworkSelectionElement + if len(pod.Annotations) == 0 { + pod.Annotations = map[string]string{} + } for _, multiHomingConf := range multiHomingConfigs { if multiHomingConf.isPrimary { + if multiHomingConf.ipamClaimReference != "" { + pod.Annotations[util.OvnUDNIPAMClaimName] = multiHomingConf.ipamClaimReference + } continue // these will be automatically plugged in } nadNamePair := strings.Split(multiHomingConf.nadName, "/") @@ -476,13 +494,14 @@ func newMultiHomedPod(testPod testPod, multiHomingConfigs ...secondaryNetInfo) * attachmentName = nadNamePair[1] } nse := nadapi.NetworkSelectionElement{ - Name: attachmentName, - Namespace: ns, + Name: attachmentName, + Namespace: ns, + IPAMClaimReference: multiHomingConf.ipamClaimReference, } secondaryNetworks = append(secondaryNetworks, nse) } serializedNetworkSelectionElements, _ := json.Marshal(secondaryNetworks) - pod.Annotations = map[string]string{nadapi.NetworkAttachmentAnnot: string(serializedNetworkSelectionElements)} + pod.Annotations[nadapi.NetworkAttachmentAnnot] = string(serializedNetworkSelectionElements) if config.OVNKubernetesFeature.EnableInterconnect { dummyOVNNetAnnotations := dummyOVNPodNetworkAnnotations(testPod.secondaryPodInfos, multiHomingConfigs) if dummyOVNNetAnnotations != "{}" { diff --git a/go-controller/pkg/ovn/ovn_test.go b/go-controller/pkg/ovn/ovn_test.go index 1cec615909e..c598a637b04 100644 --- a/go-controller/pkg/ovn/ovn_test.go +++ b/go-controller/pkg/ovn/ovn_test.go @@ -8,6 +8,7 @@ import ( "github.com/onsi/ginkgo/v2" + ipamclaimsapi "github.com/k8snetworkplumbingwg/ipamclaims/pkg/crd/ipamclaims/v1alpha1" fakeipamclaimclient "github.com/k8snetworkplumbingwg/ipamclaims/pkg/crd/ipamclaims/v1alpha1/apis/clientset/versioned/fake" mnpapi "github.com/k8snetworkplumbingwg/multi-networkpolicy/pkg/apis/k8s.cni.cncf.io/v1beta1" mnpfake "github.com/k8snetworkplumbingwg/multi-networkpolicy/pkg/client/clientset/versioned/fake" @@ -127,6 +128,7 @@ func (o *FakeOVN) start(objects ...runtime.Object) { egressServiceObjects := []runtime.Object{} apbExternalRouteObjects := []runtime.Object{} anpObjects := []runtime.Object{} + ipamClaimObjects := []runtime.Object{} v1Objects := []runtime.Object{} nads := []nettypes.NetworkAttachmentDefinition{} nadClient := fakenadclient.NewSimpleClientset() @@ -158,6 +160,8 @@ func (o *FakeOVN) start(objects ...runtime.Object) { apbExternalRouteObjects = append(apbExternalRouteObjects, object) case *anpapi.AdminNetworkPolicyList: anpObjects = append(anpObjects, object) + case *ipamclaimsapi.IPAMClaimList: + ipamClaimObjects = append(ipamClaimObjects, object) default: v1Objects = append(v1Objects, object) } @@ -172,7 +176,7 @@ func (o *FakeOVN) start(objects ...runtime.Object) { MultiNetworkPolicyClient: mnpfake.NewSimpleClientset(multiNetworkPolicyObjects...), EgressServiceClient: egressservicefake.NewSimpleClientset(egressServiceObjects...), AdminPolicyRouteClient: adminpolicybasedroutefake.NewSimpleClientset(apbExternalRouteObjects...), - IPAMClaimsClient: fakeipamclaimclient.NewSimpleClientset(), + IPAMClaimsClient: fakeipamclaimclient.NewSimpleClientset(ipamClaimObjects...), NetworkAttchDefClient: nadClient, UserDefinedNetworkClient: udnclientfake.NewSimpleClientset(), } @@ -410,6 +414,7 @@ func NewOvnController( EgressServiceClient: ovnClient.EgressServiceClient, APBRouteClient: ovnClient.AdminPolicyRouteClient, EgressQoSClient: ovnClient.EgressQoSClient, + IPAMClaimsClient: ovnClient.IPAMClaimsClient, }, wf, recorder, @@ -525,6 +530,7 @@ func (o *FakeOVN) NewSecondaryNetworkController(netattachdef *nettypes.NetworkAt Kube: kube.Kube{KClient: o.fakeClient.KubeClient}, EIPClient: o.fakeClient.EgressIPClient, EgressFirewallClient: o.fakeClient.EgressFirewallClient, + IPAMClaimsClient: o.fakeClient.IPAMClaimsClient, }, o.watcher, o.fakeRecorder, diff --git a/go-controller/pkg/ovn/secondary_layer2_network_controller_test.go b/go-controller/pkg/ovn/secondary_layer2_network_controller_test.go index 57a41a58d9f..dcd20cccf25 100644 --- a/go-controller/pkg/ovn/secondary_layer2_network_controller_test.go +++ b/go-controller/pkg/ovn/secondary_layer2_network_controller_test.go @@ -12,9 +12,12 @@ import ( "github.com/urfave/cli/v2" + ipamclaimsapi "github.com/k8snetworkplumbingwg/ipamclaims/pkg/crd/ipamclaims/v1alpha1" nadapi "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" knet "k8s.io/utils/net" "k8s.io/utils/ptr" @@ -82,7 +85,7 @@ var _ = Describe("OVN Multi-Homed pod operations for layer 2 network", func() { "reconciles a new", func(netInfo secondaryNetInfo, testConfig testConfiguration, gatewayMode config.GatewayMode) { const podIdx = 0 - podInfo := dummyL2TestPod(ns, netInfo, podIdx) + podInfo := dummyL2TestPod(ns, netInfo, podIdx, podIdx) setupConfig(netInfo, testConfig, gatewayMode) app.Action = func(ctx *cli.Context) error { pod := newMultiHomedPod(podInfo, netInfo) @@ -181,11 +184,25 @@ var _ = Describe("OVN Multi-Homed pod operations for layer 2 network", func() { DescribeTable( "reconciles a new kubevirt-related pod during its live-migration phases", func(netInfo secondaryNetInfo, testConfig testConfiguration, migrationInfo *liveMigrationInfo) { + ipamClaim := ipamclaimsapi.IPAMClaim{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: netInfo.netName + "-" + migrationInfo.vmName, + }, + Spec: ipamclaimsapi.IPAMClaimSpec{ + Network: netInfo.netName, + Interface: "net1", + }, + } + netInfo.allowPersistentIPs = true + netInfo.ipamClaimReference = ipamClaim.Name + const ( - sourcePodInfoIdx = 0 - targetPodInfoIdx = 1 + sourcePodInfoIdx = 0 + targetPodInfoIdx = 1 + secondaryNetworkIdx = 0 ) - sourcePodInfo := dummyL2TestPod(ns, netInfo, sourcePodInfoIdx) + sourcePodInfo := dummyL2TestPod(ns, netInfo, sourcePodInfoIdx, secondaryNetworkIdx) setupConfig(netInfo, testConfig, config.GatewayModeShared) app.Action = func(ctx *cli.Context) error { sourcePod := newMultiHomedKubevirtPod( @@ -199,7 +216,9 @@ var _ = Describe("OVN Multi-Homed pod operations for layer 2 network", func() { testNode, err := newNodeWithSecondaryNets(nodeName, nodeIPv4CIDR) Expect(err).NotTo(HaveOccurred()) - Expect(setupFakeOvnForLayer2Topology(fakeOvn, initialDB, netInfo, testNode, sourcePodInfo, sourcePod)).To(Succeed()) + Expect(setupFakeOvnForLayer2Topology(fakeOvn, initialDB, netInfo, testNode, sourcePodInfo, sourcePod, + &ipamclaimsapi.IPAMClaimList{Items: []ipamclaimsapi.IPAMClaim{ipamClaim}}), + ).To(Succeed()) defer fakeOvn.networkManager.Stop() // for layer2 on interconnect, it is the cluster manager that @@ -234,7 +253,7 @@ var _ = Describe("OVN Multi-Homed pod operations for layer 2 network", func() { expectationOptions..., ).expectedLogicalSwitchesAndPorts(netInfo.isPrimary)...)) - targetPodInfo := dummyL2TestPod(ns, netInfo, targetPodInfoIdx) + targetPodInfo := dummyL2TestPod(ns, netInfo, targetPodInfoIdx, secondaryNetworkIdx) targetKvPod := newMultiHomedKubevirtPod( migrationInfo.vmName, migrationInfo.targetPodInfo, @@ -470,7 +489,7 @@ func dummyPrimaryLayer2UserDefinedNetwork(subnets string) secondaryNetInfo { return secondaryNet } -func dummyL2TestPod(nsName string, info secondaryNetInfo, podIdx int) testPod { +func dummyL2TestPod(nsName string, info secondaryNetInfo, podIdx, secondaryNetIdx int) testPod { const nodeSubnet = "10.128.1.0/24" if info.isPrimary { @@ -493,8 +512,8 @@ func dummyL2TestPod(nsName string, info secondaryNetInfo, podIdx int) testPod { info.clustersubnets, "", "100.200.0.1", - fmt.Sprintf("100.200.0.%d/16", podIdx+3), - fmt.Sprintf("0a:58:64:c8:00:%0.2d", podIdx+3), + fmt.Sprintf("100.200.0.%d/16", secondaryNetIdx+3), + fmt.Sprintf("0a:58:64:c8:00:%0.2d", secondaryNetIdx+3), "primary", 0, []util.PodRoute{ @@ -517,8 +536,8 @@ func dummyL2TestPod(nsName string, info secondaryNetInfo, podIdx int) testPod { info.clustersubnets, "", "", - fmt.Sprintf("100.200.0.%d/16", podIdx+1), - fmt.Sprintf("0a:58:64:c8:00:%0.2d", podIdx+1), + fmt.Sprintf("100.200.0.%d/16", secondaryNetIdx+1), + fmt.Sprintf("0a:58:64:c8:00:%0.2d", secondaryNetIdx+1), "secondary", 0, []util.PodRoute{}, @@ -529,7 +548,7 @@ func dummyL2TestPod(nsName string, info secondaryNetInfo, podIdx int) testPod { func dummyL2TestPodAdditionalNetworkIP() string { const podIdx = 0 secNetInfo := dummyPrimaryLayer2UserDefinedNetwork("100.200.0.0/16") - return dummyL2TestPod(ns, secNetInfo, podIdx).getNetworkPortInfo(secNetInfo.netName, secNetInfo.nadName).podIP + return dummyL2TestPod(ns, secNetInfo, podIdx, podIdx).getNetworkPortInfo(secNetInfo.netName, secNetInfo.nadName).podIP } func expectedLayer2EgressEntities(netInfo util.NetInfo, gwConfig util.L3GatewayConfig, nodeName string) []libovsdbtest.TestData { @@ -685,8 +704,7 @@ func nodeCIDR() *net.IPNet { } } -func setupFakeOvnForLayer2Topology(fakeOvn *FakeOVN, initialDB libovsdbtest.TestSetup, netInfo secondaryNetInfo, testNode *v1.Node, podInfo testPod, pod *v1.Pod) error { - By(fmt.Sprintf("creating a network attachment definition for network: %s", netInfo.netName)) +func setupFakeOvnForLayer2Topology(fakeOvn *FakeOVN, initialDB libovsdbtest.TestSetup, netInfo secondaryNetInfo, testNode *v1.Node, podInfo testPod, pod *corev1.Pod, extraObjects ...runtime.Object) error { By(fmt.Sprintf("creating a network attachment definition for network: %s", netInfo.netName)) nad, err := newNetworkAttachmentDefinition( ns, @@ -714,8 +732,7 @@ func setupFakeOvnForLayer2Topology(fakeOvn *FakeOVN, initialDB libovsdbtest.Test ) } - fakeOvn.startWithDBSetup( - initialDB, + objects := []runtime.Object{ &v1.NamespaceList{ Items: []v1.Namespace{ *n, @@ -730,7 +747,11 @@ func setupFakeOvnForLayer2Topology(fakeOvn *FakeOVN, initialDB libovsdbtest.Test &nadapi.NetworkAttachmentDefinitionList{ Items: []nadapi.NetworkAttachmentDefinition{*nad}, }, - ) + } + + objects = append(objects, extraObjects...) + + fakeOvn.startWithDBSetup(initialDB, objects...) podInfo.populateLogicalSwitchCache(fakeOvn) // on IC, the test itself spits out the pod with the diff --git a/go-controller/pkg/ovn/secondary_layer3_network_controller_test.go b/go-controller/pkg/ovn/secondary_layer3_network_controller_test.go index cbebc5ee9c0..3a63953a0f3 100644 --- a/go-controller/pkg/ovn/secondary_layer3_network_controller_test.go +++ b/go-controller/pkg/ovn/secondary_layer3_network_controller_test.go @@ -36,12 +36,14 @@ import ( ) type secondaryNetInfo struct { - netName string - nadName string - clustersubnets string - hostsubnets string // not used in layer2 tests - topology string - isPrimary bool + netName string + nadName string + clustersubnets string + hostsubnets string // not used in layer2 tests + topology string + isPrimary bool + allowPersistentIPs bool + ipamClaimReference string } const ( @@ -548,10 +550,11 @@ func (sni *secondaryNetInfo) netconf() *ovncnitypes.NetConf { Name: sni.netName, Type: plugin, }, - Topology: sni.topology, - NADName: sni.nadName, - Subnets: sni.clustersubnets, - Role: role, + Topology: sni.topology, + NADName: sni.nadName, + Subnets: sni.clustersubnets, + Role: role, + AllowPersistentIPs: sni.allowPersistentIPs, } } diff --git a/test/e2e/kubevirt.go b/test/e2e/kubevirt.go index 71e9603503d..6fb084ea64e 100644 --- a/test/e2e/kubevirt.go +++ b/test/e2e/kubevirt.go @@ -326,8 +326,8 @@ var _ = Describe("Kubevirt Virtual Machines", func() { lastIperfLogLine := iperfLogLines[len(iperfLogLines)-1] return lastIperfLogLine, nil }). - WithPolling(time.Second). - WithTimeout(30*time.Second). + WithPolling(50*time.Millisecond). + WithTimeout(2*time.Second). Should( SatisfyAll( ContainSubstring(" sec "), @@ -1532,11 +1532,13 @@ runcmd: if td.topology == "localnet" { By("setting up the localnet underlay") nodes := ovsPods(clientSet) - Expect(nodes).ToNot(BeEmpty()) - defer func() { - By("tearing down the localnet underlay") - Expect(teardownUnderlay(nodes)).To(Succeed()) - }() + Expect(nodes).NotTo(BeEmpty()) + DeferCleanup(func() { + if e2eframework.TestContext.DeleteNamespace && (e2eframework.TestContext.DeleteNamespaceOnFailure || !CurrentSpecReport().Failed()) { + By("tearing down the localnet underlay") + Expect(teardownUnderlay(nodes)).To(Succeed()) + } + }) const secondaryInterfaceName = "eth1" Expect(setupUnderlay(nodes, secondaryInterfaceName, netConfig)).To(Succeed()) @@ -1704,7 +1706,7 @@ runcmd: topology: "layer2", role: "primary", }), - XEntry(nil, Label("TODO", "SDN-5490"), testData{ + Entry(nil, testData{ resource: virtualMachine, test: liveMigrate, topology: "localnet", @@ -1720,7 +1722,7 @@ runcmd: topology: "layer2", role: "primary", }), - XEntry(nil, Label("TODO", "SDN-5490"), testData{ + Entry(nil, testData{ resource: virtualMachineInstance, test: liveMigrate, topology: "localnet", @@ -1742,6 +1744,11 @@ runcmd: topology: "layer2", role: "primary", }), + Entry(nil, testData{ + resource: virtualMachineInstance, + test: liveMigrateFailed, + topology: "localnet", + }), ) }) Context("with kubevirt VM using layer2 UDPN", Ordered, func() {