Skip to content

Commit

Permalink
fix vm not running after changing the subnet (#4199)
Browse files Browse the repository at this point in the history
Signed-off-by: zhangzujian <zhangzujian.7@gmail.com>
  • Loading branch information
zhangzujian authored and bobz965 committed Jun 21, 2024
1 parent a70a0ff commit ccd5b9e
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 33 deletions.
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)
})
})

0 comments on commit ccd5b9e

Please sign in to comment.