@@ -12,6 +12,8 @@ import (
12
12
. "github.com/onsi/gomega"
13
13
. "github.com/onsi/gomega/gstruct"
14
14
15
+ "gopkg.in/yaml.v2"
16
+
15
17
corev1 "k8s.io/api/core/v1"
16
18
v1 "k8s.io/api/core/v1"
17
19
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -300,6 +302,30 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
300
302
kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
301
303
migrateVM ,
302
304
),
305
+ Entry (
306
+ "[OCPFeatureGate:PreconfiguredUDNAddresses] when the VM with preconfigured IP address is created when the address is already taken" ,
307
+ networkAttachmentConfigParams {
308
+ name : nadName ,
309
+ topology : "layer2" ,
310
+ role : "primary" ,
311
+ allowPersistentIPs : true ,
312
+ preconfiguredIP : "203.203.0.100" ,
313
+ },
314
+ kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
315
+ duplicateVM ,
316
+ ),
317
+ Entry (
318
+ "[OCPFeatureGate:PreconfiguredUDNAddresses] when the VM with preconfigured MAC address is created when the address is already taken" ,
319
+ networkAttachmentConfigParams {
320
+ name : nadName ,
321
+ topology : "layer2" ,
322
+ role : "primary" ,
323
+ allowPersistentIPs : true ,
324
+ preconfiguredMAC : "02:0A:0B:0C:0D:100" ,
325
+ },
326
+ kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
327
+ duplicateVM ,
328
+ ),
303
329
)
304
330
},
305
331
Entry ("NetworkAttachmentDefinitions" , func (c networkAttachmentConfigParams ) networkAttachmentConfig {
@@ -525,6 +551,62 @@ func verifyVMMAC(virtClient *kubevirt.Client, vmName, expectedMAC string) {
525
551
Should (Equal (expectedMAC ))
526
552
}
527
553
554
+ func createVMIFromSpec (cli * kubevirt.Client , vmNamespace , vmName string , vmiSpec map [string ]interface {}) error {
555
+ GinkgoHelper ()
556
+
557
+ newVMI := map [string ]interface {}{
558
+ "apiVersion" : "kubevirt.io/v1" ,
559
+ "kind" : "VirtualMachineInstance" ,
560
+ "metadata" : map [string ]interface {}{
561
+ "name" : vmName ,
562
+ "namespace" : vmNamespace ,
563
+ },
564
+ "spec" : vmiSpec ,
565
+ }
566
+
567
+ newVMIYAML , err := yaml .Marshal (newVMI )
568
+ if err != nil {
569
+ return err
570
+ }
571
+
572
+ return cli .Apply (string (newVMIYAML ))
573
+ }
574
+
575
+ func duplicateVM (cli * kubevirt.Client , vmNamespace , vmName string ) {
576
+ GinkgoHelper ()
577
+ duplicateVMName := vmName + "-duplicate"
578
+ By (fmt .Sprintf ("Duplicating VM %s/%s to %s/%s" , vmNamespace , vmName , vmNamespace , duplicateVMName ))
579
+
580
+ vmiSpecJSON , err := cli .GetJSONPath ("vmi" , vmName , "{.spec}" )
581
+ Expect (err ).NotTo (HaveOccurred ())
582
+ var vmiSpec map [string ]interface {}
583
+ Expect (json .Unmarshal ([]byte (vmiSpecJSON ), & vmiSpec )).To (Succeed ())
584
+
585
+ Expect (createVMIFromSpec (cli , vmNamespace , duplicateVMName , vmiSpec )).To (Succeed ())
586
+ waitForVMPodEventWithMessage (cli , vmNamespace , duplicateVMName , "address conflict detected" , 2 * time .Minute )
587
+ }
588
+
589
+ func waitForVMPodEventWithMessage (vmClient * kubevirt.Client , vmNamespace , vmName , expectedEventMessage string , timeout time.Duration ) {
590
+ GinkgoHelper ()
591
+ By (fmt .Sprintf ("Waiting for event containing %q on VM %s/%s virt-launcher pod" , expectedEventMessage , vmNamespace , vmName ))
592
+
593
+ Eventually (func (g Gomega ) []string {
594
+ const vmLabelKey = "vm.kubevirt.io/name"
595
+ podNames , err := vmClient .GetPodsByLabel (vmLabelKey , vmName )
596
+ if err != nil || len (podNames ) != 1 {
597
+ return []string {}
598
+ }
599
+
600
+ virtLauncherPodName := podNames [0 ]
601
+ eventMessages , err := vmClient .GetEventsForPod (virtLauncherPodName )
602
+ g .Expect (err ).NotTo (HaveOccurred (), "Failed to get events for pod" )
603
+
604
+ return eventMessages
605
+ }).WithPolling (time .Second ).WithTimeout (timeout ).Should (
606
+ ContainElement (ContainSubstring (expectedEventMessage )),
607
+ fmt .Sprintf ("Expected to find an event containing %q" , expectedEventMessage ))
608
+ }
609
+
528
610
func waitForPodsCondition (fr * framework.Framework , pods []* corev1.Pod , conditionFn func (g Gomega , pod * corev1.Pod )) {
529
611
for _ , pod := range pods {
530
612
Eventually (func (g Gomega ) {
0 commit comments