Skip to content

Commit 8d6569e

Browse files
committed
networking: Add primaryUDN VM Addr collision test w/ preconfigured addr
Validates that KubeVirt VMs with preconfigured MAC and IP addresses maintain those addresses correctly before and after a vmi with duplicate IP/MAC request is made, and that the vmi with the duplicate address get the appropriate address conflict error event. Signed-off-by: Ram Lavi <[email protected]>
1 parent ce10d09 commit 8d6569e

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

test/extended/networking/kubevirt/client.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,29 @@ func (c *Client) GetJSONPath(resource, name, jsonPath string) (string, error) {
9393
}
9494
return strings.TrimSuffix(strings.TrimPrefix(output, `"`), `"`), nil
9595
}
96+
97+
func (c *Client) GetPodsByLabel(labelKey, labelValue string) ([]string, error) {
98+
output, err := c.oc.AsAdmin().Run("get").Args("pods", "-n", c.oc.Namespace(), "-l", fmt.Sprintf("%s=%s", labelKey, labelValue), "-o", "jsonpath={.items[*].metadata.name}").Output()
99+
if err != nil {
100+
return nil, err
101+
}
102+
if output == "" {
103+
return []string{}, nil
104+
}
105+
return strings.Fields(output), nil
106+
}
107+
108+
func (c *Client) GetEventsForPod(podName string) ([]string, error) {
109+
output, err := c.oc.AsAdmin().Run("get").Args("events", "-n", c.oc.Namespace(), "--field-selector", fmt.Sprintf("involvedObject.name=%s,involvedObject.kind=Pod", podName), "-o", "jsonpath={.items[*].message}").Output()
110+
if err != nil {
111+
return nil, err
112+
}
113+
if output == "" {
114+
return []string{}, nil
115+
}
116+
return strings.Fields(output), nil
117+
}
118+
96119
func ensureVirtctl(oc *exutil.CLI, dir string) (string, error) {
97120
filepath := filepath.Join(dir, "virtctl")
98121
_, err := os.Stat(filepath)

test/extended/networking/livemigration.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
528610
func 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

Comments
 (0)