@@ -17,6 +17,7 @@ import (
1717 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1818 "k8s.io/client-go/kubernetes"
1919 "k8s.io/kubernetes/test/e2e/framework"
20+ e2enode "k8s.io/kubernetes/test/e2e/framework/node"
2021 "k8s.io/kubernetes/test/e2e/framework/skipper"
2122 admissionapi "k8s.io/pod-security-admission/api"
2223
@@ -564,6 +565,124 @@ var _ = g.Describe("[sig-network][Feature:EgressIP][apigroup:operator.openshift.
564565 spawnProberSendEgressIPTrafficCheckLogs (oc , externalNamespace , probePodName , routeName , targetProtocol , targetHost , targetPort , numberOfRequestsToSend , numberOfRequestsToSend , packetSnifferDaemonSet , egressIPSet )
565566 }
566567 })
568+
569+ g .It ("Rebooting a node/Restarting CNCC pod should not change the EgressIPs capacity" , func () {
570+ g .By ("Get one Egress node" )
571+ egressNodeName := egressIPNodesOrderedNames [0 ]
572+ for _ , node := range egressIPNodesOrderedNames [1 :] {
573+ // Only keep one egress node, remove egress labels from other nodes
574+ _ , _ = runOcWithRetry (oc .AsAdmin (), "label" , "node" , node , "k8s.ovn.org/egress-assignable-" )
575+ }
576+
577+ g .By ("Get capacity of one Egress node before reboot" )
578+ egressNode , err := clientset .CoreV1 ().Nodes ().Get (context .TODO (), egressNodeName , metav1.GetOptions {})
579+ o .Expect (err ).NotTo (o .HaveOccurred ())
580+ nodeEgressIPConfigs , err := getNodeEgressIPConfiguration (egressNode )
581+ o .Expect (err ).NotTo (o .HaveOccurred ())
582+ capacityBeforeReboot := nodeEgressIPConfigs [0 ].Capacity
583+ framework .Logf ("The capacity of node %s before reboot is %v" , egressNodeName , capacityBeforeReboot )
584+
585+ g .By ("Getting a map of source nodes and potential Egress IPs for these nodes" )
586+ var egressIPsPerNode int
587+ if capacityBeforeReboot .IPv4 == 0 {
588+ // On OpenStack and GCP, the capacity per node is the number of IPs per node, not the number of IPv4 addresses, like "capacity":{"ip":8}
589+ egressIPsPerNode = capacityBeforeReboot .IP
590+ } else {
591+ egressIPsPerNode = capacityBeforeReboot .IPv4
592+ }
593+ if egressIPsPerNode > 20 {
594+ egressIPsPerNode = 20
595+ }
596+
597+ nodeEgressIPMap , err := findNodeEgressIPs (oc , clientset , cloudNetworkClientset , egressIPNodesOrderedNames , cloudType , egressIPsPerNode )
598+ framework .Logf ("%v" , nodeEgressIPMap )
599+ o .Expect (err ).NotTo (o .HaveOccurred ())
600+
601+ g .By (fmt .Sprintf ("Creating %d EgressIPs objects for the Egress node" , egressIPsPerNode ))
602+ defer func () {
603+ g .By ("Deleting all EgressIPs objects" )
604+ _ , err := runOcWithRetry (oc .AsAdmin (), "delete" , "egressIP" , "--all" )
605+ o .Expect (err ).NotTo (o .HaveOccurred ())
606+ }()
607+ for i := 0 ; i < egressIPsPerNode ; i ++ {
608+ egressIPSet := make (map [string ]string )
609+ egressIPSet [nodeEgressIPMap [egressNodeName ][i ]] = egressNodeName
610+
611+ g .By (fmt .Sprintf ("Creating %dth EgressIP object " , i ))
612+ egressIPObjectName := egressIPNamespace + fmt .Sprintf ("-%d" , i )
613+ egressIPYamlPath := tmpDirEgressIP + "/" + fmt .Sprintf ("egressip-%d.yaml" , i )
614+ createEgressIPObject (oc , egressIPYamlPath , egressIPObjectName , egressIPNamespace , "" , egressIPSet )
615+
616+ g .By (fmt .Sprintf ("Applying %dth EgressIP object " , i ))
617+ applyEgressIPObject (oc , cloudNetworkClientset , egressIPYamlPath , egressIPObjectName , egressIPSet , egressUpdateTimeout )
618+
619+ }
620+ g .By ("Rebooting the node gracefully" )
621+ err = exutil .TriggerNodeRebootGraceful (clientset , egressNodeName )
622+ o .Expect (err ).NotTo (o .HaveOccurred ())
623+
624+ g .By ("Waiting for the node to become NotReady" )
625+ ctx := context .TODO ()
626+ isNotReady := e2enode .WaitForNodeToBeNotReady (ctx , clientset , egressNodeName , 10 * time .Minute )
627+ o .Expect (isNotReady ).To (o .BeTrue (), "Node should become NotReady after reboot trigger" )
628+
629+ g .By ("Waiting for the node to become Ready again after reboot" )
630+ isReady := e2enode .WaitForNodeToBeReady (ctx , clientset , egressNodeName , 15 * time .Minute )
631+ o .Expect (isReady ).To (o .BeTrue (), "Node should become Ready again after reboot" )
632+
633+ g .By ("Waiting for all EgressIPs to be assigned" )
634+ err = waitAllEgressIPsAssigned (oc , 15 * time .Minute )
635+ o .Expect (err ).NotTo (o .HaveOccurred ())
636+
637+ g .By ("Get capacity of the Egress node after reboot" )
638+ nodeEgressIPConfigsAfterReboot , err := getNodeEgressIPConfiguration (egressNode )
639+ o .Expect (err ).NotTo (o .HaveOccurred ())
640+ capacityAfterReboot := nodeEgressIPConfigsAfterReboot [0 ].Capacity
641+ framework .Logf ("The capacity of node %s after reboot is %v" , egressNodeName , capacityAfterReboot )
642+
643+ g .By ("Checking CloudPrivateIPConfigs for CloudResponseError, should be 0, after node reboot" )
644+ errorCount , err := countCloudPrivateIPConfigsByReason (oc , "CloudResponseError" )
645+ o .Expect (err ).NotTo (o .HaveOccurred ())
646+ framework .Logf ("Found %d CloudPrivateIPConfigs with CloudResponseError" , errorCount )
647+ o .Expect (errorCount ).To (o .Equal (0 ), "Expected no CloudPrivateIPConfigs with CloudResponseError, but found %d" , errorCount )
648+
649+ g .By ("Checking CloudPrivateIPConfigs for CloudResponseSuccess" )
650+ successCount , err := countCloudPrivateIPConfigsByReason (oc , "CloudResponseSuccess" )
651+ o .Expect (err ).NotTo (o .HaveOccurred ())
652+ framework .Logf ("Found %d CloudPrivateIPConfigs with CloudResponseSuccess" , successCount )
653+ o .Expect (successCount ).To (o .Equal (egressIPsPerNode ), "Expected %d CloudPrivateIPConfigs with CloudResponseSuccess, but found %d" , egressIPsPerNode , successCount )
654+
655+ g .By ("Comparing capacity before and after reboot" )
656+ o .Expect (capacityAfterReboot ).To (o .Equal (capacityBeforeReboot ),
657+ "EgressIP capacity should remain the same after node reboot. Before: %v, After: %v" ,
658+ capacityBeforeReboot , capacityAfterReboot )
659+
660+ g .By ("Restarting the CNCC pod" )
661+ restartCNCCPod (oc , clientset )
662+
663+ g .By ("Get capacity of the Egress node after CNCC restart" )
664+ nodeEgressIPConfigsAfterCNCCRestart , err := getNodeEgressIPConfiguration (egressNode )
665+ o .Expect (err ).NotTo (o .HaveOccurred ())
666+ capacityAfterCNCCRestart := nodeEgressIPConfigsAfterCNCCRestart [0 ].Capacity
667+ framework .Logf ("The capacity of node %s after CNCC restart is %v" , egressNodeName , capacityAfterCNCCRestart )
668+
669+ g .By ("Comparing capacity before and after CNCC restart" )
670+ o .Expect (capacityAfterCNCCRestart ).To (o .Equal (capacityBeforeReboot ),
671+ "EgressIP capacity should remain the same after CNCC restart. Before: %v, After: %v" ,
672+ capacityBeforeReboot , capacityAfterCNCCRestart )
673+
674+ g .By ("Checking CloudPrivateIPConfigs for CloudResponseError,should be 0, after CNCC restart" )
675+ errorCount , err = countCloudPrivateIPConfigsByReason (oc , "CloudResponseError" )
676+ o .Expect (err ).NotTo (o .HaveOccurred ())
677+ framework .Logf ("Found %d CloudPrivateIPConfigs with CloudResponseError" , errorCount )
678+ o .Expect (errorCount ).To (o .Equal (0 ), "Expected no CloudPrivateIPConfigs with CloudResponseError, but found %d" , errorCount )
679+
680+ g .By ("Checking CloudPrivateIPConfigs for CloudResponseSuccess" )
681+ successCount , err = countCloudPrivateIPConfigsByReason (oc , "CloudResponseSuccess" )
682+ o .Expect (err ).NotTo (o .HaveOccurred ())
683+ framework .Logf ("Found %d CloudPrivateIPConfigs with CloudResponseSuccess" , successCount )
684+ o .Expect (successCount ).To (o .Equal (egressIPsPerNode ), "Expected %d CloudPrivateIPConfigs with CloudResponseSuccess, but found %d" , egressIPsPerNode , successCount )
685+ })
567686 }) // end testing to external targets
568687})
569688
0 commit comments