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  }