@@ -30,6 +30,8 @@ import (
30
30
"github.com/openshift/origin/test/extended/util/image"
31
31
)
32
32
33
+ const kvIPRequestsAnnot = "network.kubevirt.io/addresses"
34
+
33
35
var _ = Describe ("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][Feature:Layer2LiveMigration] Kubevirt Virtual Machines" , func () {
34
36
// disable automatic namespace creation, we need to add the required UDN label
35
37
oc := exutil .NewCLIWithoutNamespace ("network-segmentation-e2e" )
@@ -303,6 +305,20 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
303
305
preconfiguredMAC : "02:0A:0B:0C:0D:51" ,
304
306
},
305
307
),
308
+ Entry (
309
+ "[OCPFeatureGate:PreconfiguredUDNAddresses] when the VM with preconfigured IP address is created when the address is already taken" ,
310
+ networkAttachmentConfigParams {
311
+ name : nadName ,
312
+ topology : "layer2" ,
313
+ role : "primary" ,
314
+ allowPersistentIPs : true ,
315
+ },
316
+ kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
317
+ duplicateVM ,
318
+ workloadNetworkConfig {
319
+ preconfiguredIPs : []string {"203.203.0.100" , "2014:100:200::100" },
320
+ },
321
+ ),
306
322
)
307
323
},
308
324
Entry ("NetworkAttachmentDefinitions" , func (c networkAttachmentConfigParams ) {
@@ -526,6 +542,65 @@ func verifyVMMAC(virtClient *kubevirt.Client, vmName, expectedMAC string) {
526
542
Should (Equal (expectedMAC ))
527
543
}
528
544
545
+ func duplicateVM (cli * kubevirt.Client , vmNamespace , vmName string ) {
546
+ GinkgoHelper ()
547
+ duplicateVMName := vmName + "-duplicate"
548
+ By (fmt .Sprintf ("Duplicating VM %s/%s to %s/%s" , vmNamespace , vmName , vmNamespace , duplicateVMName ))
549
+
550
+ vmiSpecJSON , err := cli .GetJSONPath ("vmi" , vmName , "{.spec}" )
551
+ Expect (err ).NotTo (HaveOccurred ())
552
+ var vmiSpec map [string ]interface {}
553
+ Expect (json .Unmarshal ([]byte (vmiSpecJSON ), & vmiSpec )).To (Succeed ())
554
+
555
+ originalVMIRawAnnotations , err := cli .GetJSONPath ("vmi" , vmName , "{.metadata.annotations}" )
556
+ Expect (err ).NotTo (HaveOccurred ())
557
+
558
+ originalVMIAnnotations := map [string ]string {}
559
+ Expect (json .Unmarshal ([]byte (originalVMIRawAnnotations ), & originalVMIAnnotations )).To (Succeed ())
560
+
561
+ var vmiCreationOptions []kubevirt.Option
562
+ var vmiExpectations []func ()
563
+ if requestedIPs , hasIPRequests := originalVMIAnnotations [kvIPRequestsAnnot ]; hasIPRequests {
564
+ vmiCreationOptions = append (
565
+ vmiCreationOptions ,
566
+ kubevirt .WithAnnotations (ipRequests (requestedIPs )),
567
+ )
568
+ vmiExpectations = append (vmiExpectations , func () {
569
+ waitForVMPodEventWithMessage (
570
+ cli ,
571
+ vmNamespace ,
572
+ duplicateVMName ,
573
+ "IP is already allocated" ,
574
+ 2 * time .Minute ,
575
+ )
576
+ })
577
+ }
578
+ Expect (cli .CreateVMIFromSpec (vmNamespace , duplicateVMName , vmiSpec , vmiCreationOptions ... )).To (Succeed ())
579
+ for _ , expectation := range vmiExpectations {
580
+ expectation ()
581
+ }
582
+ }
583
+
584
+ func waitForVMPodEventWithMessage (vmClient * kubevirt.Client , vmNamespace , vmName , expectedEventMessage string , timeout time.Duration ) {
585
+ GinkgoHelper ()
586
+ By (fmt .Sprintf ("Waiting for event containing %q on VM %s/%s virt-launcher pod" , expectedEventMessage , vmNamespace , vmName ))
587
+
588
+ Eventually (func (g Gomega ) []string {
589
+ const vmLabelKey = "vm.kubevirt.io/name"
590
+ podNames , err := vmClient .GetPodsByLabel (vmLabelKey , vmName )
591
+ g .Expect (err ).NotTo (HaveOccurred (), "Failed to get pods by label %s=%s" , vmLabelKey , vmName )
592
+ g .Expect (podNames ).To (HaveLen (1 ), "Expected exactly one virt-launcher pod for VM %s/%s, but found %d pods: %v" , vmNamespace , vmName , len (podNames ), podNames )
593
+
594
+ virtLauncherPodName := podNames [0 ]
595
+ eventMessages , err := vmClient .GetEventsForPod (virtLauncherPodName )
596
+ g .Expect (err ).NotTo (HaveOccurred (), "Failed to get events for pod %s" , virtLauncherPodName )
597
+
598
+ return eventMessages
599
+ }).WithPolling (time .Second ).WithTimeout (timeout ).Should (
600
+ ContainElement (ContainSubstring (expectedEventMessage )),
601
+ fmt .Sprintf ("Expected to find an event containing %q" , expectedEventMessage ))
602
+ }
603
+
529
604
func waitForPodsCondition (fr * framework.Framework , pods []* corev1.Pod , conditionFn func (g Gomega , pod * corev1.Pod )) {
530
605
for _ , pod := range pods {
531
606
Eventually (func (g Gomega ) {
@@ -696,3 +771,7 @@ func formatAddressesAnnotation(preconfiguredIPs []string) (string, error) {
696
771
697
772
return string (staticIPs ), nil
698
773
}
774
+
775
+ func ipRequests (ips string ) map [string ]string {
776
+ return map [string ]string {kvIPRequestsAnnot : ips }
777
+ }
0 commit comments