github.com/nmstate/kubernetes-nmstate@v0.82.0/test/e2e/handler/bonding_default_interface_test.go (about) 1 /* 2 Copyright The Kubernetes NMState Authors. 3 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 */ 17 18 package handler 19 20 import ( 21 "fmt" 22 "time" 23 24 . "github.com/onsi/ginkgo/v2" 25 . "github.com/onsi/gomega" 26 27 nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" 28 "github.com/nmstate/kubernetes-nmstate/test/e2e/policy" 29 ) 30 31 func boundUpWithPrimaryAndSecondary(bondName string) nmstate.State { 32 return nmstate.NewState(fmt.Sprintf(`interfaces: 33 - name: %s 34 type: bond 35 state: up 36 copy-mac-from: %s 37 ipv4: 38 dhcp: true 39 enabled: true 40 link-aggregation: 41 mode: active-backup 42 options: 43 miimon: %s 44 primary: %s 45 %s: 46 - %s 47 - %s 48 `, bondName, primaryNic, fmt.Sprintf(miimonFormat, 140), primaryNic, portFieldName, primaryNic, firstSecondaryNic)) 49 } 50 51 func bondAbsentWithPrimaryUp(bondName string) nmstate.State { 52 return nmstate.NewState(fmt.Sprintf(`interfaces: 53 - name: %s 54 type: bond 55 state: absent 56 - name: %s 57 state: up 58 type: ethernet 59 ipv4: 60 dhcp: true 61 enabled: true 62 `, bondName, primaryNic)) 63 } 64 65 var _ = Describe("NodeNetworkConfigurationPolicy bonding default interface", func() { 66 Context("when there is a default interface with dynamic address", func() { 67 addressByNode := map[string]string{} 68 BeforeEach(func() { 69 Byf("Check %s is the default route interface and has dynamic address", primaryNic) 70 for _, node := range nodes { 71 defaultRouteNextHopInterface(node).Should(Equal(primaryNic)) 72 Expect(dhcpFlag(node, primaryNic)).Should(BeTrue()) 73 } 74 75 By("Fetching current IP address") 76 for _, node := range nodes { 77 address := "" 78 Eventually(func() string { 79 address = ipv4Address(node, primaryNic) 80 return address 81 }, 15*time.Second, 1*time.Second).ShouldNot(BeEmpty(), fmt.Sprintf("Interface %s has no ipv4 address", primaryNic)) 82 Byf("Fetching current IP address %s", address) 83 addressByNode[node] = address 84 } 85 Byf("Reseting state of %s", firstSecondaryNic) 86 resetNicStateForNodes(firstSecondaryNic) 87 Byf("Creating %s on %s and %s", bond1, primaryNic, firstSecondaryNic) 88 updateDesiredStateAndWait(boundUpWithPrimaryAndSecondary(bond1)) 89 By("Done configuring test") 90 91 }) 92 AfterEach(func() { 93 Byf("Removing bond %s and configuring %s with dhcp", bond1, primaryNic) 94 updateDesiredStateAndWait(bondAbsentWithPrimaryUp(bond1)) 95 96 By("Waiting until the node becomes ready again") 97 for _, node := range nodes { 98 99 interfacesNameForNodeEventually(node).ShouldNot(ContainElement(bond1)) 100 } 101 102 resetDesiredStateForNodes() 103 104 Byf("Check %s has the default ip address", primaryNic) 105 for _, node := range nodes { 106 Eventually( 107 func() string { 108 return ipv4Address(node, primaryNic) 109 }, 110 30*time.Second, 111 1*time.Second, 112 ).Should(Equal(addressByNode[node]), fmt.Sprintf("Interface %s address is not the original one", primaryNic)) 113 } 114 115 }) 116 117 It("should successfully move default IP address on top of the bond", func() { 118 var ( 119 expectedBond = interfaceByName(interfaces(boundUpWithPrimaryAndSecondary(bond1)), bond1) 120 ) 121 122 By("Checking that bond was configured and obtained the same IP address") 123 for _, node := range nodes { 124 verifyBondIsUpWithPrimaryNicIP(node, expectedBond, addressByNode[node]) 125 } 126 // Restart only first node that it's a control-plane if other node is restarted it will stuck in NotReady state 127 nodeToReboot := nodes[0] 128 Byf("Reboot node %s and verify that bond still has ip of primary nic", nodeToReboot) 129 restartNodeWithoutWaiting(nodeToReboot) 130 131 By("Wait for policy re-reconciled after node reboot") 132 policy.WaitForPolicyTransitionUpdate(TestPolicy) 133 policy.WaitForAvailablePolicy(TestPolicy) 134 135 Byf("Node %s was rebooted, verifying %s exists and ip was not changed", nodeToReboot, bond1) 136 verifyBondIsUpWithPrimaryNicIP(nodeToReboot, expectedBond, addressByNode[nodeToReboot]) 137 }) 138 }) 139 }) 140 141 func verifyBondIsUpWithPrimaryNicIP(node string, expectedBond map[string]interface{}, ip string) { 142 interfacesForNode(node).Should(ContainElement(matchingBond(expectedBond))) 143 144 Eventually(func() string { 145 return ipv4Address(node, bond1) 146 }, 30*time.Second, 1*time.Second).Should(Equal(ip), fmt.Sprintf("Interface bond1 has not take over the %s address", primaryNic)) 147 } 148 149 func resetNicStateForNodes(nicName string) { 150 updateDesiredStateAndWait(ethernetNicsUp(nicName)) 151 deletePolicy(TestPolicy) 152 }