@@ -12,6 +12,8 @@ import (
1212 . "github.com/onsi/gomega"
1313 . "github.com/onsi/gomega/gstruct"
1414
15+ "gopkg.in/yaml.v2"
16+
1517 corev1 "k8s.io/api/core/v1"
1618 v1 "k8s.io/api/core/v1"
1719 apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -300,6 +302,30 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
300302 kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
301303 migrateVM ,
302304 ),
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+ ),
303329 )
304330 },
305331 Entry ("NetworkAttachmentDefinitions" , func (c networkAttachmentConfigParams ) networkAttachmentConfig {
@@ -525,6 +551,62 @@ func verifyVMMAC(virtClient *kubevirt.Client, vmName, expectedMAC string) {
525551 Should (Equal (expectedMAC ))
526552}
527553
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+
528610func waitForPodsCondition (fr * framework.Framework , pods []* corev1.Pod , conditionFn func (g Gomega , pod * corev1.Pod )) {
529611 for _ , pod := range pods {
530612 Eventually (func (g Gomega ) {
0 commit comments