Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix vm not running after changing the subnet #4199

Merged
merged 1 commit into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/ovs/ovn-nb-logical_switch_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ func (c *OVNNbClient) CreateLogicalSwitchPort(lsName, lspName, ip, mac, podName,
var ops []ovsdb.Operation
lsp := buildLogicalSwitchPort(lspName, lsName, ip, mac, podName, namespace, portSecurity, securityGroups, vips, enableDHCP, dhcpOptions, vpc)
if existingLsp != nil {
if lsp.ExternalIDs[logicalSwitchKey] == lsName {
if existingLsp.ExternalIDs[logicalSwitchKey] == lsName {
if err := c.UpdateLogicalSwitchPort(lsp, &lsp.Addresses, &lsp.Dhcpv4Options, &lsp.Dhcpv6Options, &lsp.PortSecurity, &lsp.ExternalIDs); err != nil {
klog.Error(err)
return fmt.Errorf("failed to update logical switch port %s: %v", lspName, err)
}
return nil
}
if ops, err = c.LogicalSwitchUpdatePortOp(lsp.ExternalIDs[logicalSwitchKey], existingLsp.UUID, ovsdb.MutateOperationDelete); err != nil {
if ops, err = c.LogicalSwitchUpdatePortOp(existingLsp.ExternalIDs[logicalSwitchKey], existingLsp.UUID, ovsdb.MutateOperationDelete); err != nil {
klog.Error(err)
return err
}
Expand Down
97 changes: 66 additions & 31 deletions test/e2e/kubevirt/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"os/exec"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -158,7 +159,7 @@ var _ = framework.Describe("[group:kubevirt]", func() {
framework.ExpectEqual(ips, pod.Status.PodIPs)
})

framework.ConformanceIt("restart vm should be able to handle subnet change after the namespace has its first subnet", func() {
framework.ConformanceIt("should be able to handle vm restart when subnet changes before the vm is stopped", func() {
// create a vm within a namespace, the namespace has no subnet, so the vm use ovn-default subnet
// create a subnet in the namespace later, the vm should use its own subnet
// stop the vm, the vm should delete the vm ip, because of the namespace only has one subnet but not ovn-default
Expand All @@ -183,19 +184,11 @@ var _ = framework.Describe("[group:kubevirt]", func() {
framework.ExpectHaveKeyWithValue(pod.Annotations, util.VMAnnotation, vmName)
ips := pod.Status.PodIPs

ginkgo.By("Checking old lsp ExternalIDs contains should contains default subnet " + util.DefaultSubnet)
portName := ovs.PodNameToPortName(vmName, namespaceName, util.OvnProvider)
conditions := fmt.Sprintf("name=%s", portName)
execCmd := "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids find logical-switch-port " + conditions
framework.Logf("exec cmd %s", execCmd)
output, err := exec.Command("bash", "-c", execCmd).CombinedOutput()
framework.ExpectNoError(err)
framework.ExpectContainSubstring(string(output), util.DefaultSubnet)

ginkgo.By("Stopping vm " + vmName)
vmClient.StopSync(vmName)

// the ip is deleted
portName := ovs.PodNameToPortName(vmName, namespaceName, util.OvnProvider)
err = ipClient.WaitToDisappear(portName, 2*time.Second, 2*time.Minute)
framework.ExpectNoError(err)

Expand All @@ -218,13 +211,64 @@ var _ = framework.Describe("[group:kubevirt]", func() {
ginkgo.By("Checking whether pod ips are changed")
framework.ExpectNotEqual(ips, pod.Status.PodIPs)

ginkgo.By("Checking new lsp ExternalIDs should contains new subnet " + subnetName)
conditions = fmt.Sprintf("name=%s", portName)
execCmd = "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids find logical-switch-port " + conditions
framework.Logf("exec cmd %s", execCmd)
output, err = exec.Command("bash", "-c", execCmd).CombinedOutput()
ginkgo.By("Checking external-ids of LSP " + portName)
cmd := "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids list logical-switch-port " + portName
framework.Logf("exec cmd %q", cmd)
output, err := exec.Command("bash", "-c", cmd).CombinedOutput()
framework.ExpectNoError(err)
framework.ExpectContainElement(strings.Fields(string(output)), "ls="+subnetName)
})

framework.ConformanceIt("should be able to handle vm restart when subnet changes after the vm is stopped", func() {
ginkgo.By("Getting pod of vm " + vmName)
labelSelector := fmt.Sprintf("%s=%s", v1.VirtualMachineNameLabel, vmName)
podList, err := podClient.List(context.TODO(), metav1.ListOptions{
LabelSelector: labelSelector,
})
framework.ExpectNoError(err)
framework.ExpectHaveLen(podList.Items, 1)

ginkgo.By("Validating pod annotations")
pod := &podList.Items[0]
framework.ExpectHaveKeyWithValue(pod.Annotations, util.AllocatedAnnotation, "true")
framework.ExpectHaveKeyWithValue(pod.Annotations, util.RoutedAnnotation, "true")
framework.ExpectHaveKeyWithValue(pod.Annotations, util.VMAnnotation, vmName)
ips := pod.Status.PodIPs

ginkgo.By("Stopping vm " + vmName)
vmClient.StopSync(vmName)

ginkgo.By("Creating subnet " + subnetName)
cidr := framework.RandomCIDR(f.ClusterIPFamily)
subnet := framework.MakeSubnet(subnetName, "", cidr, "", "", "", nil, nil, []string{namespaceName})
_ = subnetClient.CreateSync(subnet)

ginkgo.By("Starting vm " + vmName)
vmClient.StartSync(vmName)

ginkgo.By("Getting pod of vm " + vmName)
podList, err = podClient.List(context.TODO(), metav1.ListOptions{
LabelSelector: labelSelector,
})
framework.ExpectNoError(err)
framework.ExpectHaveLen(podList.Items, 1)

ginkgo.By("Validating new pod annotations")
pod = &podList.Items[0]
framework.ExpectHaveKeyWithValue(pod.Annotations, util.AllocatedAnnotation, "true")
framework.ExpectHaveKeyWithValue(pod.Annotations, util.RoutedAnnotation, "true")
framework.ExpectHaveKeyWithValue(pod.Annotations, util.VMAnnotation, vmName)

ginkgo.By("Checking whether pod ips are changed")
framework.ExpectNotEqual(ips, pod.Status.PodIPs)

portName := ovs.PodNameToPortName(vmName, namespaceName, util.OvnProvider)
ginkgo.By("Checking external-ids of LSP " + portName)
cmd := "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids list logical-switch-port " + portName
framework.Logf("exec cmd %q", cmd)
output, err := exec.Command("bash", "-c", cmd).CombinedOutput()
framework.ExpectNoError(err)
framework.ExpectContainSubstring(string(output), subnetName)
framework.ExpectContainElement(strings.Fields(string(output)), "ls="+subnetName)
})

framework.ConformanceIt("restart vm should be able to change vm subnet after deleting the old ip", func() {
Expand All @@ -247,17 +291,9 @@ var _ = framework.Describe("[group:kubevirt]", func() {
framework.ExpectHaveKeyWithValue(pod.Annotations, util.VMAnnotation, vmName)
ginkgo.By("Stopping vm " + vmName)
vmClient.StopSync(vmName)
portName := ovs.PodNameToPortName(vmName, namespaceName, util.OvnProvider)

ginkgo.By("Checking old lsp ExternalIDs contains should contains default subnet " + util.DefaultSubnet)
conditions := fmt.Sprintf("name=%s", portName)
execCmd := "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids find logical-switch-port " + conditions
framework.Logf("exec cmd %s", execCmd)
output, err := exec.Command("bash", "-c", execCmd).CombinedOutput()
framework.ExpectNoError(err)
framework.ExpectContainSubstring(string(output), util.DefaultSubnet)

// make sure the vm ip is still exist
portName := ovs.PodNameToPortName(vmName, namespaceName, util.OvnProvider)
oldVMIP := ipClient.Get(portName)
framework.ExpectNotEmpty(oldVMIP.Spec.IPAddress)
ipClient.DeleteSync(portName)
Expand Down Expand Up @@ -293,12 +329,11 @@ var _ = framework.Describe("[group:kubevirt]", func() {
ginkgo.By("Checking whether pod ips are changed")
framework.ExpectNotEqual(newVMIP.Spec.IPAddress, oldVMIP.Spec.IPAddress)

ginkgo.By("Checking new lsp ExternalIDs should contains new subnet " + subnetName)
conditions = fmt.Sprintf("name=%s", portName)
execCmd = "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids find logical-switch-port " + conditions
framework.Logf("exec cmd %s", execCmd)
output, err = exec.Command("bash", "-c", execCmd).CombinedOutput()
ginkgo.By("Checking external-ids of LSP " + portName)
cmd := "kubectl ko nbctl --format=list --data=bare --no-heading --columns=external_ids list logical-switch-port " + portName
framework.Logf("exec cmd %q", cmd)
output, err := exec.Command("bash", "-c", cmd).CombinedOutput()
framework.ExpectNoError(err)
framework.ExpectContainSubstring(string(output), subnetName)
framework.ExpectContainElement(strings.Fields(string(output)), "ls="+subnetName)
})
})
Loading