@@ -70,8 +70,12 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
70
70
DescribeTableSubtree ("created using" ,
71
71
func (createNetworkFn func (netConfig networkAttachmentConfigParams ) networkAttachmentConfig ) {
72
72
73
- DescribeTable ("[Suite:openshift/network/virtualization] should keep ip" , func (netConfig networkAttachmentConfigParams , vmResource string , opCmd func (cli * kubevirt.Client , vmNamespace , vmName string )) {
73
+ DescribeTable ("[Suite:openshift/network/virtualization] should keep ip" , func (netConfig networkAttachmentConfigParams , vmResource string , opCmd func (cli * kubevirt.Client , vmNamespace , vmName string ), wlConfig ... workloadNetworkConfig ) {
74
74
var err error
75
+ var workloadConfig workloadNetworkConfig
76
+ if len (wlConfig ) > 0 {
77
+ workloadConfig = wlConfig [0 ]
78
+ }
75
79
l := map [string ]string {
76
80
"e2e-framework" : f .BaseName ,
77
81
}
@@ -128,6 +132,14 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
128
132
vmCreationParams .NetworkName = nadName
129
133
}
130
134
135
+ if len (workloadConfig .preconfiguredIPs ) > 0 {
136
+ var err error
137
+ vmCreationParams .PreconfiguredIP , err = formatAddressesAnnotation (workloadConfig .preconfiguredIPs )
138
+ Expect (err ).NotTo (HaveOccurred ())
139
+ }
140
+ if workloadConfig .preconfiguredMAC != "" {
141
+ vmCreationParams .PreconfiguredMAC = workloadConfig .preconfiguredMAC
142
+ }
131
143
Expect (virtClient .CreateVM (vmResource , vmCreationParams )).To (Succeed ())
132
144
waitForVMReadiness (virtClient , vmCreationParams .VMNamespace , vmCreationParams .VMName )
133
145
@@ -151,6 +163,17 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
151
163
}
152
164
Expect (initialAddresses ).To (HaveLen (expectedNumberOfAddresses ))
153
165
166
+ if len (workloadConfig .preconfiguredIPs ) > 0 {
167
+ By ("Verifying VM received the preconfigured IP address(es)" )
168
+ for _ , expectedIP := range workloadConfig .preconfiguredIPs {
169
+ expectedIP = strings .TrimSpace (expectedIP )
170
+ Expect (initialAddresses ).To (ContainElement (expectedIP ), fmt .Sprintf ("Expected IP %s not found in VM addresses %v" , expectedIP , initialAddresses ))
171
+ }
172
+ }
173
+ if workloadConfig .preconfiguredMAC != "" {
174
+ By ("Verifying VM received the preconfigured MAC address" )
175
+ verifyVMMAC (virtClient , vmName , workloadConfig .preconfiguredMAC )
176
+ }
154
177
httpServerPodsIPs := httpServerTestPodsMultusNetworkIPs (netConfig , httpServerPods )
155
178
156
179
By (fmt .Sprintf ("Check east/west traffic before test operation using IPs: %v" , httpServerPodsIPs ))
@@ -173,6 +196,10 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
173
196
ShouldNot (BeEmpty ())
174
197
Expect (obtainedAddresses ).To (ConsistOf (initialAddresses ))
175
198
199
+ if workloadConfig .preconfiguredMAC != "" {
200
+ By ("Verifying VM MAC address persisted after test operation" )
201
+ verifyVMMAC (virtClient , vmName , workloadConfig .preconfiguredMAC )
202
+ }
176
203
By ("Check east/west after test operation" )
177
204
checkEastWestTraffic (virtClient , vmName , httpServerPodsIPs )
178
205
},
@@ -241,7 +268,51 @@ var _ = Describe("[sig-network][OCPFeatureGate:PersistentIPsForVirtualization][F
241
268
},
242
269
kubevirt .FedoraVMWithSecondaryNetworkAttachment ,
243
270
restartVM ,
244
- ))
271
+ ),
272
+ Entry (
273
+ "[OCPFeatureGate:PreconfiguredUDNAddresses] when the VM with preconfigured IPs attached to a primary UDN is restarted" ,
274
+ networkAttachmentConfigParams {
275
+ name : nadName ,
276
+ topology : "layer2" ,
277
+ role : "primary" ,
278
+ allowPersistentIPs : true ,
279
+ },
280
+ kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
281
+ restartVM ,
282
+ workloadNetworkConfig {
283
+ preconfiguredIPs : []string {"203.203.0.50" , "2014:100:200::50" },
284
+ },
285
+ ),
286
+ Entry (
287
+ "[OCPFeatureGate:PreconfiguredUDNAddresses] when the VM with preconfigured MAC attached to a primary UDN is restarted" ,
288
+ networkAttachmentConfigParams {
289
+ name : nadName ,
290
+ topology : "layer2" ,
291
+ role : "primary" ,
292
+ allowPersistentIPs : true ,
293
+ },
294
+ kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
295
+ restartVM ,
296
+ workloadNetworkConfig {
297
+ preconfiguredMAC : "02:0A:0B:0C:0D:50" ,
298
+ },
299
+ ),
300
+ Entry (
301
+ "[OCPFeatureGate:PreconfiguredUDNAddresses] when the VM with preconfigured IP and MAC attached to a primary UDN is migrated between nodes" ,
302
+ networkAttachmentConfigParams {
303
+ name : nadName ,
304
+ topology : "layer2" ,
305
+ role : "primary" ,
306
+ allowPersistentIPs : true ,
307
+ },
308
+ kubevirt .FedoraVMWithPreconfiguredPrimaryUDNAttachment ,
309
+ migrateVM ,
310
+ workloadNetworkConfig {
311
+ preconfiguredIPs : []string {"203.203.0.51" , "2014:100:200::51" },
312
+ preconfiguredMAC : "02:0A:0B:0C:0D:51" ,
313
+ },
314
+ ),
315
+ )
245
316
},
246
317
Entry ("NetworkAttachmentDefinitions" , func (c networkAttachmentConfigParams ) networkAttachmentConfig {
247
318
netConfig := newNetworkAttachmentConfig (c )
@@ -428,6 +499,14 @@ func obtainAddresses(virtClient *kubevirt.Client, vmName string) ([]string, erro
428
499
return addressFromStatus (virtClient , vmName )
429
500
}
430
501
502
+ func obtainMAC (virtClient * kubevirt.Client , vmName string ) (string , error ) {
503
+ macStr , err := virtClient .GetJSONPath ("vmi" , vmName , "{@.status.interfaces[0].mac}" )
504
+ if err != nil {
505
+ return "" , fmt .Errorf ("failed to extract the MAC address from VM %q: %w" , vmName , err )
506
+ }
507
+ return strings .ToUpper (macStr ), nil
508
+ }
509
+
431
510
func restartVM (cli * kubevirt.Client , vmNamespace , vmName string ) {
432
511
GinkgoHelper ()
433
512
By (fmt .Sprintf ("Restarting vmi %s/%s" , vmNamespace , vmName ))
@@ -442,6 +521,22 @@ func migrateVM(cli *kubevirt.Client, vmNamespace, vmName string) {
442
521
waitForVMIMSuccess (cli , vmNamespace , vmName )
443
522
}
444
523
524
+ func verifyVMMAC (virtClient * kubevirt.Client , vmName , expectedMAC string ) {
525
+ GinkgoHelper ()
526
+ var actualMAC string
527
+ Eventually (func (g Gomega ) string {
528
+ GinkgoHelper ()
529
+
530
+ var err error
531
+ actualMAC , err = obtainMAC (virtClient , vmName )
532
+ g .Expect (err ).NotTo (HaveOccurred (), "Failed to obtain MAC address for VM" )
533
+ return actualMAC
534
+ }).
535
+ WithPolling (time .Second ).
536
+ WithTimeout (5 * time .Minute ).
537
+ Should (Equal (expectedMAC ))
538
+ }
539
+
445
540
func waitForPodsCondition (fr * framework.Framework , pods []* corev1.Pod , conditionFn func (g Gomega , pod * corev1.Pod )) {
446
541
for _ , pod := range pods {
447
542
Eventually (func (g Gomega ) {
@@ -627,3 +722,25 @@ func networkName(netSpecConfig string) string {
627
722
Expect (json .Unmarshal ([]byte (netSpecConfig ), & nc )).To (Succeed ())
628
723
return nc .Name
629
724
}
725
+
726
+ // formatAddressesAnnotation converts slice of IPs to the required JSON format for kubevirt addresses annotation
727
+ func formatAddressesAnnotation (preconfiguredIPs []string ) (string , error ) {
728
+ const primaryUDNNetworkName = "overlay"
729
+ if len (preconfiguredIPs ) == 0 {
730
+ return "" , nil
731
+ }
732
+
733
+ ips := make ([]string , len (preconfiguredIPs ))
734
+ for i , ip := range preconfiguredIPs {
735
+ ips [i ] = strings .TrimSpace (ip )
736
+ }
737
+
738
+ staticIPs , err := json .Marshal (map [string ][]string {
739
+ primaryUDNNetworkName : ips ,
740
+ })
741
+ if err != nil {
742
+ return "" , fmt .Errorf ("failed to marshal static IPs: %w" , err )
743
+ }
744
+
745
+ return string (staticIPs ), nil
746
+ }
0 commit comments