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  })