@@ -30,6 +30,8 @@ import (
3030 "github.com/openshift/origin/test/extended/util/image"
3131)
3232
33+ const kvIPRequestsAnnot = "network.kubevirt.io/addresses"
34+
3335var _ = Describe ("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][Feature:Layer2LiveMigration] Kubevirt Virtual Machines" , func () {
3436 // disable automatic namespace creation, we need to add the required UDN label
3537 oc := exutil .NewCLIWithoutNamespace ("network-segmentation-e2e" )
@@ -303,6 +305,20 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
303305 preconfiguredMAC : "02:0A:0B:0C:0D:51" ,
304306 },
305307 ),
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+ ),
306322 )
307323 },
308324 Entry ("NetworkAttachmentDefinitions" , func (c networkAttachmentConfigParams ) {
@@ -526,6 +542,65 @@ func verifyVMMAC(virtClient *kubevirt.Client, vmName, expectedMAC string) {
526542 Should (Equal (expectedMAC ))
527543}
528544
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+
529604func waitForPodsCondition (fr * framework.Framework , pods []* corev1.Pod , conditionFn func (g Gomega , pod * corev1.Pod )) {
530605 for _ , pod := range pods {
531606 Eventually (func (g Gomega ) {
@@ -696,3 +771,7 @@ func formatAddressesAnnotation(preconfiguredIPs []string) (string, error) {
696771
697772 return string (staticIPs ), nil
698773}
774+
775+ func ipRequests (ips string ) map [string ]string {
776+ return map [string ]string {kvIPRequestsAnnot : ips }
777+ }
0 commit comments