github.com/rancher/elemental/tests@v0.0.0-20240517125144-ae048c615b3f/e2e/ui_test.go (about) 1 /* 2 Copyright © 2022 - 2024 SUSE LLC 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 http://www.apache.org/licenses/LICENSE-2.0 8 Unless required by applicable law or agreed to in writing, software 9 distributed under the License is distributed on an "AS IS" BASIS, 10 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 See the License for the specific language governing permissions and 12 limitations under the License. 13 */ 14 15 package e2e_test 16 17 import ( 18 "os/exec" 19 "strings" 20 "sync" 21 "time" 22 23 . "github.com/onsi/ginkgo/v2" 24 . "github.com/onsi/gomega" 25 "github.com/rancher-sandbox/ele-testhelpers/kubectl" 26 "github.com/rancher-sandbox/ele-testhelpers/rancher" 27 "github.com/rancher-sandbox/ele-testhelpers/tools" 28 "github.com/rancher/elemental/tests/e2e/helpers/elemental" 29 "github.com/rancher/elemental/tests/e2e/helpers/misc" 30 "github.com/rancher/elemental/tests/e2e/helpers/network" 31 ) 32 33 var _ = Describe("E2E - Bootstrap node for UI", Label("ui"), func() { 34 var ( 35 bootstrappedNodes int 36 wg sync.WaitGroup 37 ) 38 39 It("Configure libvirt and bootstrap a node", func() { 40 By("Downloading MachineRegistration", func() { 41 tokenURL, err := kubectl.RunWithoutErr("get", "MachineRegistration", 42 "--namespace", clusterNS, 43 "machine-registration", "-o", "jsonpath={.status.registrationURL}") 44 Expect(err).To(Not(HaveOccurred())) 45 46 // Get the YAML config file 47 Eventually(func() error { 48 return tools.GetFileFromURL(tokenURL, installConfigYaml, false) 49 }, tools.SetTimeout(2*time.Minute), 10*time.Second).ShouldNot(HaveOccurred()) 50 }) 51 52 By("Starting default network", func() { 53 // Don't check return code, as the default network could be already removed 54 cmds := []string{"net-destroy", "net-undefine"} 55 for _, c := range cmds { 56 _ = exec.Command("sudo", "virsh", c, "default").Run() 57 } 58 59 err := exec.Command("sudo", "virsh", "net-create", netDefaultFileName).Run() 60 Expect(err).To(Not(HaveOccurred())) 61 }) 62 63 if !isoBoot && !rawBoot { 64 By("Configuring iPXE boot script for network installation", func() { 65 numberOfFile, err := network.ConfigureiPXE(httpSrv) 66 Expect(err).To(Not(HaveOccurred())) 67 Expect(numberOfFile).To(BeNumerically(">=", 1)) 68 }) 69 } 70 71 // Loop on node provisionning 72 // NOTE: if numberOfVMs == vmIndex then only one node will be provisionned 73 bootstrappedNodes = 0 74 for index := vmIndex; index <= numberOfVMs; index++ { 75 // Set node hostname 76 hostName := elemental.SetHostname(vmNameRoot, index) 77 Expect(hostName).To(Not(BeEmpty())) 78 79 // Add node in network configuration 80 err := rancher.AddNode(netDefaultFileName, hostName, index) 81 Expect(err).To(Not(HaveOccurred())) 82 83 // Get generated MAC address 84 client, macAdrs := GetNodeInfo(hostName) 85 Expect(client).To(Not(BeNil())) 86 Expect(macAdrs).To(Not(BeEmpty())) 87 88 wg.Add(1) 89 go func(s, h, m string, i int, cl *tools.Client) { 90 defer wg.Done() 91 defer GinkgoRecover() 92 93 By("Installing node "+h, func() { 94 // Execute node deployment in parallel 95 err := exec.Command(s, h, m).Run() 96 Expect(err).To(Not(HaveOccurred())) 97 98 if rawBoot { 99 // Report to Qase that we boot from raw image 100 testCaseID = 75 101 102 // The VM will boot first on the recovery partition to create the normal partition 103 // No need to check the recovery process 104 // Only make sure the VM is up and running on the normal partition 105 GinkgoWriter.Printf("Checking ssh on VM %s\n", h) 106 CheckSSH(cl) 107 GinkgoWriter.Printf("Checking ssh OK on VM %s\n", h) 108 109 // Wait for the end of the elemental-register process 110 Eventually(func() error { 111 _, err := cl.RunSSH("(journalctl --no-pager -u elemental-register.service) | grep -Eiq 'Finished Elemental Register'") 112 return err 113 }, tools.SetTimeout(4*time.Minute), 10*time.Second).Should(Not(HaveOccurred())) 114 115 // Wait a bit more to be sure the VM is ready and halt it 116 time.Sleep(1 * time.Minute) 117 GinkgoWriter.Printf("Stopping VM %s\n", h) 118 err := exec.Command("sudo", "virsh", "destroy", h).Run() 119 Expect(err).To(Not(HaveOccurred())) 120 121 // Make sure VM status is equal to shut-off 122 Eventually(func() string { 123 out, _ := exec.Command("sudo", "virsh", "domstate", h).Output() 124 return strings.Trim(string(out), "\n\n") 125 }, tools.SetTimeout(5*time.Minute), 5*time.Second).Should(Equal("shut off")) 126 } else { 127 // Report to Qase that we boot from ISO 128 testCaseID = 9 129 } 130 131 }) 132 }(installVMScript, hostName, macAdrs, index, client) 133 134 // Wait a bit before starting more nodes to reduce CPU and I/O load 135 bootstrappedNodes = misc.WaitNodesBoot(index, vmIndex, bootstrappedNodes, numberOfNodesMax) 136 } 137 138 // Wait for all parallel jobs 139 wg.Wait() 140 }) 141 142 It("Add the nodes in Rancher Manager", func() { 143 // Wait a bit to make sure the VMs is really halted 144 // TODO: Find a better way to check this 145 time.Sleep(5 * time.Minute) 146 147 for index := vmIndex; index <= numberOfVMs; index++ { 148 // Set node hostname 149 hostName := elemental.SetHostname(vmNameRoot, index) 150 Expect(hostName).To(Not(BeEmpty())) 151 152 // Get node information 153 client, _ := GetNodeInfo(hostName) 154 Expect(client).To(Not(BeNil())) 155 156 // Execute in parallel 157 wg.Add(1) 158 go func(c, h string, i int, t bool, cl *tools.Client) { 159 defer wg.Done() 160 defer GinkgoRecover() 161 162 // Restart the node(s) 163 By("Restarting "+h+" to add it in the cluster", func() { 164 // Wait a little bit to avoid starting all VMs at the same time 165 misc.RandomSleep(sequential, i) 166 167 err := exec.Command("sudo", "virsh", "start", h).Run() 168 GinkgoWriter.Printf("Starting VM %s\n", h) 169 Expect(err).To(Not(HaveOccurred())) 170 }) 171 172 By("Checking "+h+" SSH connection", func() { 173 CheckSSH(cl) 174 }) 175 176 By("Checking that TPM is correctly configured on "+h, func() { 177 testValue := "-c" 178 if t == true { 179 testValue = "! -e" 180 } 181 _ = RunSSHWithRetry(cl, "[[ "+testValue+" /dev/tpm0 ]]") 182 }) 183 184 By("Checking OS version on "+h, func() { 185 out := RunSSHWithRetry(cl, "cat /etc/os-release") 186 GinkgoWriter.Printf("OS Version on %s:\n%s\n", h, out) 187 }) 188 }(clusterNS, hostName, index, emulateTPM, client) 189 190 // Wait a bit before starting more nodes to reduce CPU and I/O load 191 bootstrappedNodes = misc.WaitNodesBoot(index, vmIndex, bootstrappedNodes, numberOfNodesMax) 192 } 193 194 // Wait for all parallel jobs 195 wg.Wait() 196 }) 197 })