From e7b393f3588110eebe7b2b70015f302f892efe7a Mon Sep 17 00:00:00 2001 From: Lennart Jern Date: Fri, 24 Jan 2025 13:21:56 +0000 Subject: [PATCH 1/3] E2E: Refactor PerformSSHBootCheck Signed-off-by: Lennart Jern --- test/e2e/common.go | 9 ++++++++- test/e2e/config/bmcs-fixture.yaml | 2 -- test/e2e/config/bmcs-ipmi.yaml | 2 -- test/e2e/config/bmcs-redfish-virtualmedia.yaml | 2 -- test/e2e/config/bmcs-redfish.yaml | 2 -- test/e2e/config/ironic.yaml | 1 + test/e2e/live_iso_test.go | 10 +--------- test/e2e/provisioning_and_annotation_test.go | 12 +----------- 8 files changed, 11 insertions(+), 29 deletions(-) diff --git a/test/e2e/common.go b/test/e2e/common.go index 59ff1850a9..42fd43ac45 100644 --- a/test/e2e/common.go +++ b/test/e2e/common.go @@ -292,8 +292,15 @@ echo "%s" >> /root/.ssh/authorized_keys`, sshPubKeyData) // PerformSSHBootCheck performs an SSH check to verify the node's boot source. // The `expectedBootMode` parameter should be "disk" or "memory". // The `auth` parameter is an ssh.AuthMethod for authentication. -func PerformSSHBootCheck(e2eConfig *Config, expectedBootMode string, auth ssh.AuthMethod, sshAddress string) { +func PerformSSHBootCheck(e2eConfig *Config, expectedBootMode string, ipAddress string) { user := e2eConfig.GetVariable("SSH_USERNAME") + keyPath := e2eConfig.GetVariable("SSH_PRIV_KEY") + key, err := os.ReadFile(keyPath) + Expect(err).NotTo(HaveOccurred(), "unable to read private key") + signer, err := ssh.ParsePrivateKey(key) + Expect(err).NotTo(HaveOccurred(), "unable to parse private key") + auth := ssh.PublicKeys(signer) + sshAddress := fmt.Sprintf("%s:%s", ipAddress, e2eConfig.GetVariable("SSH_PORT")) client := EstablishSSHConnection(e2eConfig, auth, user, sshAddress) defer func() { diff --git a/test/e2e/config/bmcs-fixture.yaml b/test/e2e/config/bmcs-fixture.yaml index c16c8a36eb..011c09fb55 100644 --- a/test/e2e/config/bmcs-fixture.yaml +++ b/test/e2e/config/bmcs-fixture.yaml @@ -6,11 +6,9 @@ bootMacAddress: "00:60:2f:31:81:01" hostName: "" ipAddress: "192.168.222.122" - sshPort: "22" - user: admin password: password address: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1" bootMacAddress: "00:60:2f:31:81:02" hostName: "" ipAddress: "192.168.222.123" - sshPort: "22" diff --git a/test/e2e/config/bmcs-ipmi.yaml b/test/e2e/config/bmcs-ipmi.yaml index 758d93459b..f3fe772be6 100644 --- a/test/e2e/config/bmcs-ipmi.yaml +++ b/test/e2e/config/bmcs-ipmi.yaml @@ -4,11 +4,9 @@ bootMacAddress: "00:60:2f:31:81:01" hostName: "bmo-e2e-0" ipAddress: "192.168.222.122" - sshPort: "22" - user: admin password: password address: "ipmi://192.168.222.1:16231" bootMacAddress: "00:60:2f:31:81:02" hostName: "bmo-e2e-1" ipAddress: "192.168.222.123" - sshPort: "22" diff --git a/test/e2e/config/bmcs-redfish-virtualmedia.yaml b/test/e2e/config/bmcs-redfish-virtualmedia.yaml index f991a792d1..d1200a20fd 100644 --- a/test/e2e/config/bmcs-redfish-virtualmedia.yaml +++ b/test/e2e/config/bmcs-redfish-virtualmedia.yaml @@ -4,11 +4,9 @@ bootMacAddress: "00:60:2f:31:81:01" hostName: "bmo-e2e-0" ipAddress: "192.168.222.122" - sshPort: "22" - user: admin password: password address: "redfish-virtualmedia+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1" bootMacAddress: "00:60:2f:31:81:02" hostName: "bmo-e2e-1" ipAddress: "192.168.222.123" - sshPort: "22" diff --git a/test/e2e/config/bmcs-redfish.yaml b/test/e2e/config/bmcs-redfish.yaml index 8ec2b33a71..683f1e5a8d 100644 --- a/test/e2e/config/bmcs-redfish.yaml +++ b/test/e2e/config/bmcs-redfish.yaml @@ -4,11 +4,9 @@ bootMacAddress: "00:60:2f:31:81:01" hostName: "bmo-e2e-0" ipAddress: "192.168.222.122" - sshPort: "22" - user: admin password: password address: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1" bootMacAddress: "00:60:2f:31:81:02" hostName: "bmo-e2e-1" ipAddress: "192.168.222.123" - sshPort: "22" diff --git a/test/e2e/config/ironic.yaml b/test/e2e/config/ironic.yaml index 9d05da1cb7..81e9935179 100644 --- a/test/e2e/config/ironic.yaml +++ b/test/e2e/config/ironic.yaml @@ -41,6 +41,7 @@ variables: CERT_MANAGER_VERSION: "v1.13.1" SSH_CHECK_PROVISIONED: "true" SSH_USERNAME: "root" + SSH_PORT: "22" SSH_PRIV_KEY: "./images/ssh_testkey" SSH_PUB_KEY: "./images/ssh_testkey.pub" FETCH_IRONIC_NODES: "true" diff --git a/test/e2e/live_iso_test.go b/test/e2e/live_iso_test.go index ce9115b8ba..11652e0ae1 100644 --- a/test/e2e/live_iso_test.go +++ b/test/e2e/live_iso_test.go @@ -6,14 +6,12 @@ package e2e import ( "context" "fmt" - "os" "path" metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1" metal3bmc "github.com/metal3-io/baremetal-operator/pkg/hardwareutils/bmc" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "golang.org/x/crypto/ssh" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" @@ -105,13 +103,7 @@ var _ = Describe("Live-ISO", Label("required", "live-iso"), func() { // The ssh check is not possible in all situations (e.g. fixture) so it can be skipped if e2eConfig.GetVariable("SSH_CHECK_PROVISIONED") == "true" { By("Verifying the node booted from live ISO image") - keyPath := e2eConfig.GetVariable("SSH_PRIV_KEY") - key, err := os.ReadFile(keyPath) - Expect(err).NotTo(HaveOccurred(), "unable to read private key") - signer, err := ssh.ParsePrivateKey(key) - Expect(err).NotTo(HaveOccurred(), "unable to parse private key") - auth := ssh.PublicKeys(signer) - PerformSSHBootCheck(e2eConfig, "memory", auth, fmt.Sprintf("%s:%s", bmc.IPAddress, bmc.SSHPort)) + PerformSSHBootCheck(e2eConfig, "memory", bmc.IPAddress) } else { Logf("WARNING: Skipping SSH check since SSH_CHECK_PROVISIONED != true") } diff --git a/test/e2e/provisioning_and_annotation_test.go b/test/e2e/provisioning_and_annotation_test.go index 0d9e8c9264..0f18f987a8 100644 --- a/test/e2e/provisioning_and_annotation_test.go +++ b/test/e2e/provisioning_and_annotation_test.go @@ -7,14 +7,12 @@ import ( "context" "encoding/json" "fmt" - "os" "path" "time" metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "golang.org/x/crypto/ssh" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -121,15 +119,7 @@ var _ = Describe("Provision, detach, recreate from status and deprovision", Labe // The ssh check is not possible in all situations (e.g. fixture) so it can be skipped if e2eConfig.GetVariable("SSH_CHECK_PROVISIONED") == "true" { By("Verifying the node booting from disk") - keyPath := e2eConfig.GetVariable("SSH_PRIV_KEY") - key, err := os.ReadFile(keyPath) - Expect(err).NotTo(HaveOccurred(), "unable to read private key") - - signer, err := ssh.ParsePrivateKey(key) - Expect(err).NotTo(HaveOccurred(), "unable to parse private key") - - auth := ssh.PublicKeys(signer) - PerformSSHBootCheck(e2eConfig, "disk", auth, fmt.Sprintf("%s:%s", bmc.IPAddress, bmc.SSHPort)) + PerformSSHBootCheck(e2eConfig, "disk", bmc.IPAddress) } else { Logf("WARNING: Skipping SSH check since SSH_CHECK_PROVISIONED != true") } From a44601dc58f0d6a63b594ed100200dba00699672 Mon Sep 17 00:00:00 2001 From: Lennart Jern Date: Fri, 24 Jan 2025 13:59:34 +0000 Subject: [PATCH 2/3] VBMCTL: Cleanup Rename confusing variables. Mostly "hostname" -> "name", because it didn't have anything to do with the hostname. It is just the name of the VM we create, and that happens to also become the hostname unless changed elsewhere. Simplify LoadBMCConfig and vbmctl main. Signed-off-by: Lennart Jern --- hack/ci-e2e.sh | 2 +- test/e2e/bmc.go | 30 +++++------ test/e2e/config/bmcs-fixture.yaml | 9 ++-- test/e2e/config/bmcs-ipmi.yaml | 4 +- .../e2e/config/bmcs-redfish-virtualmedia.yaml | 4 +- test/e2e/config/bmcs-redfish.yaml | 4 +- test/e2e/e2e_suite_test.go | 2 +- test/e2e/re_inspection_test.go | 3 +- test/vbmctl/main.go | 51 ++++++++++--------- test/vbmctl/templates/VM.xml.tpl | 8 +-- 10 files changed, 60 insertions(+), 57 deletions(-) diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh index b3100f5ee5..89c1624f9d 100755 --- a/hack/ci-e2e.sh +++ b/hack/ci-e2e.sh @@ -82,7 +82,7 @@ if [[ "${BMO_E2E_EMULATOR}" == "vbmc" ]]; then readarray -t BMCS < <(yq e -o=j -I=0 '.[]' "${E2E_BMCS_CONF_FILE}") for bmc in "${BMCS[@]}"; do address=$(echo "${bmc}" | jq -r '.address') - hostName=$(echo "${bmc}" | jq -r '.hostName') + hostName=$(echo "${bmc}" | jq -r '.name') vbmc_port="${address##*:}" "${REPO_ROOT}/tools/bmh_test/vm2vbmc.sh" "${hostName}" "${vbmc_port}" "${IP_ADDRESS}" done diff --git a/test/e2e/bmc.go b/test/e2e/bmc.go index 319f06b06b..7d1da9c10c 100644 --- a/test/e2e/bmc.go +++ b/test/e2e/bmc.go @@ -9,28 +9,28 @@ import ( "gopkg.in/yaml.v2" ) -// BMC defines a BMH to use in the tests. +// BMC defines connection details for a baseboard management controller +// and other details needed for creating a virtual machine related to it. type BMC struct { - // BMC initial username + // User is the username for accessing the BMC. User string `yaml:"user,omitempty"` - // BMC initial password + // Password is the password for accessing the BMC. Password string `yaml:"password,omitempty"` - // BMC initial address + // Address of the BMC, e.g. "redfish-virtualmedia+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1". Address string `yaml:"address,omitempty"` - // BMC Mac address + // BootMacAddress is the MAC address of the VMs network interface. BootMacAddress string `yaml:"bootMacAddress,omitempty"` - // The Hostname of the node, which will be read into BMH object - HostName string `yaml:"hostName,omitempty"` - // The IP address of the node - // Optional. Only needed if e2eConfig variable - // SSH_CHECK_PROVISIONED is true + // Name of the machine associated with this BMC. + Name string `yaml:"name,omitempty"` + // NetworkName is the name of the network that the new VM should be attached to + NetworkName string `yaml:"networkName,omitempty"` + // IPAddress is a reserved IP address for the VM. + // This will be paired with the MAC address in the DHCP configuration. + // Example: 192.168.222.122 IPAddress string `yaml:"ipAddress,omitempty"` - // Optional. Only needed if e2eConfig variable - // SSH_CHECK_PROVISIONED is true - SSHPort string `yaml:"sshPort,omitempty"` } -func LoadBMCConfig(configPath string) (*[]BMC, error) { +func LoadBMCConfig(configPath string) ([]BMC, error) { configData, err := os.ReadFile(configPath) //#nosec var bmcs []BMC if err != nil { @@ -39,5 +39,5 @@ func LoadBMCConfig(configPath string) (*[]BMC, error) { if err := yaml.Unmarshal(configData, &bmcs); err != nil { return nil, err } - return &bmcs, nil + return bmcs, nil } diff --git a/test/e2e/config/bmcs-fixture.yaml b/test/e2e/config/bmcs-fixture.yaml index 011c09fb55..93762eb260 100644 --- a/test/e2e/config/bmcs-fixture.yaml +++ b/test/e2e/config/bmcs-fixture.yaml @@ -1,14 +1,11 @@ -# For fixture config, only the `hostName` field matters. The number of BMCs, -# however, needs to be equal or larger than `GINKGO_NODES`. +# For fixture it doesn't matter much what we put here. The number of BMCs, +# however, needs to be equal or larger than `GINKGO_NODES` or we will +# run out of BMCs to test on. - user: admin password: password address: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-0" bootMacAddress: "00:60:2f:31:81:01" - hostName: "" - ipAddress: "192.168.222.122" - user: admin password: password address: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1" bootMacAddress: "00:60:2f:31:81:02" - hostName: "" - ipAddress: "192.168.222.123" diff --git a/test/e2e/config/bmcs-ipmi.yaml b/test/e2e/config/bmcs-ipmi.yaml index f3fe772be6..f2dad11e45 100644 --- a/test/e2e/config/bmcs-ipmi.yaml +++ b/test/e2e/config/bmcs-ipmi.yaml @@ -2,11 +2,11 @@ password: password address: "ipmi://192.168.222.1:16230" bootMacAddress: "00:60:2f:31:81:01" - hostName: "bmo-e2e-0" + name: "bmo-e2e-0" ipAddress: "192.168.222.122" - user: admin password: password address: "ipmi://192.168.222.1:16231" bootMacAddress: "00:60:2f:31:81:02" - hostName: "bmo-e2e-1" + name: "bmo-e2e-1" ipAddress: "192.168.222.123" diff --git a/test/e2e/config/bmcs-redfish-virtualmedia.yaml b/test/e2e/config/bmcs-redfish-virtualmedia.yaml index d1200a20fd..7b2d523b79 100644 --- a/test/e2e/config/bmcs-redfish-virtualmedia.yaml +++ b/test/e2e/config/bmcs-redfish-virtualmedia.yaml @@ -2,11 +2,11 @@ password: password address: "redfish-virtualmedia+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-0" bootMacAddress: "00:60:2f:31:81:01" - hostName: "bmo-e2e-0" + name: "bmo-e2e-0" ipAddress: "192.168.222.122" - user: admin password: password address: "redfish-virtualmedia+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1" bootMacAddress: "00:60:2f:31:81:02" - hostName: "bmo-e2e-1" + name: "bmo-e2e-1" ipAddress: "192.168.222.123" diff --git a/test/e2e/config/bmcs-redfish.yaml b/test/e2e/config/bmcs-redfish.yaml index 683f1e5a8d..360587d58a 100644 --- a/test/e2e/config/bmcs-redfish.yaml +++ b/test/e2e/config/bmcs-redfish.yaml @@ -2,11 +2,11 @@ password: password address: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-0" bootMacAddress: "00:60:2f:31:81:01" - hostName: "bmo-e2e-0" + name: "bmo-e2e-0" ipAddress: "192.168.222.122" - user: admin password: password address: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-1" bootMacAddress: "00:60:2f:31:81:02" - hostName: "bmo-e2e-1" + name: "bmo-e2e-1" ipAddress: "192.168.222.123" diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 26b8d78322..19fe4c5942 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -306,7 +306,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { e2eConfig = LoadE2EConfig(configPath) bmcs, err := LoadBMCConfig(bmcConfigPath) Expect(err).ToNot(HaveOccurred(), "Failed to read the bmcs config file") - bmc = (*bmcs)[GinkgoParallelProcess()-1] + bmc = (bmcs)[GinkgoParallelProcess()-1] clusterProxy = framework.NewClusterProxy("bmo-e2e", kubeconfigPath, scheme) }) diff --git a/test/e2e/re_inspection_test.go b/test/e2e/re_inspection_test.go index e72c4c5388..f09e5caaed 100644 --- a/test/e2e/re_inspection_test.go +++ b/test/e2e/re_inspection_test.go @@ -105,7 +105,8 @@ var _ = Describe("Re-Inspection", Label("required", "re-inspection"), func() { By("checking that the hardware details are corrected after re-inspection") key = types.NamespacedName{Namespace: bmh.Namespace, Name: bmh.Name} Expect(clusterProxy.GetClient().Get(ctx, key, &bmh)).To(Succeed()) - Expect(bmh.Status.HardwareDetails.Hostname).To(Equal(bmc.HostName)) + // TODO(lentzi90): Hostname should not be determined or configured through BMC + Expect(bmh.Status.HardwareDetails.Hostname).To(Equal(bmc.Name)) }) AfterEach(func() { diff --git a/test/vbmctl/main.go b/test/vbmctl/main.go index bc8cb1649b..9f9faf4add 100644 --- a/test/vbmctl/main.go +++ b/test/vbmctl/main.go @@ -146,14 +146,14 @@ func CreateVolume(volumeName, poolName, poolPath string, capacityInGB int) error return nil } -// CreateLibvirtVM creates a new virtual machine with the given hostname, +// CreateLibvirtVM creates a new virtual machine with the given name, // network name, and MAC address. It first creates a qcow2 file with a size // of 3GB and defines it in the default storage pool. The function then connects // to the libvirt daemon and uses a template to generate the VM's XML configuration. // If the domain is successfully defined and created, the virtual machine is // started. Errors during qcow2 file creation, volume creation, libvirt connection, // template rendering, or domain creation are returned. -func CreateLibvirtVM(hostName, networkName, macAddress string) error { +func CreateLibvirtVM(name, networkName, macAddress string) error { poolName := "default" poolPath := "/tmp/pool_oo" opts := make(map[string]any) @@ -161,7 +161,7 @@ func CreateLibvirtVM(hostName, networkName, macAddress string) error { opts[qcow2.OPT_FMT] = "qcow2" // qcow2 format opts[qcow2.OPT_SUBCLUSTER] = true // enable sub-cluster - err := qcow2.Blk_Create("/tmp/"+hostName+".qcow2", opts) + err := qcow2.Blk_Create("/tmp/"+name+".qcow2", opts) if err != nil { fmt.Println("Failed to create qcow2 file") @@ -169,7 +169,7 @@ func CreateLibvirtVM(hostName, networkName, macAddress string) error { return err } - if err = CreateVolume(hostName, poolName, poolPath, 20); err != nil { + if err = CreateVolume(name, poolName, poolPath, 20); err != nil { return err } @@ -181,12 +181,12 @@ func CreateLibvirtVM(hostName, networkName, macAddress string) error { defer conn.Close() data := struct { - HostName string + Name string Network string MacAddress string PoolPath string }{ - HostName: hostName, + Name: name, Network: networkName, MacAddress: macAddress, PoolPath: poolPath, @@ -216,12 +216,12 @@ func CreateLibvirtVM(hostName, networkName, macAddress string) error { return nil } -// CreateLibvirtBMC creates a VM with the given MAC address, hostname, IP address +// CreateLibvirtBMC creates a VM with the given MAC address, name, IP address // and adds a DHCP host entry on the given network. // // It will return an error if the network does not exist, or if creating the VM // or adding the DHCP host entry fails. -func CreateLibvirtBMC(macAddress, hostName, ipAddress, networkName string) error { +func CreateLibvirtBMC(macAddress, name, ipAddress, networkName string) error { var err error conn, err := libvirt.NewConnect("qemu:///system") if err != nil { @@ -234,7 +234,7 @@ func CreateLibvirtBMC(macAddress, hostName, ipAddress, networkName string) error return err } - xmlTpl, err := template.New("xml").Parse("") + xmlTpl, err := template.New("xml").Parse("") if err != nil { return err @@ -242,11 +242,11 @@ func CreateLibvirtBMC(macAddress, hostName, ipAddress, networkName string) error data := struct { MacAddress string - HostName string + Name string IPAddress string }{ MacAddress: macAddress, - HostName: hostName, + Name: name, IPAddress: ipAddress, } @@ -270,7 +270,7 @@ func CreateLibvirtBMC(macAddress, hostName, ipAddress, networkName string) error fmt.Printf("Error occurred: %v\n", err) return err } - if err = CreateLibvirtVM(hostName, networkName, macAddress); err != nil { + if err = CreateLibvirtVM(name, networkName, macAddress); err != nil { fmt.Printf("Error occurred: %v\n", err) return err } @@ -278,8 +278,8 @@ func CreateLibvirtBMC(macAddress, hostName, ipAddress, networkName string) error } func main() { - var vmName = flag.String( - "vm-name", "VM-1", "The name of the VM to create") + var name = flag.String( + "name", "BMH-0", "The name of the VM to create") var networkName = flag.String( "network-name", "baremetal-e2e", "The name of the network that the new VM should be attached to") var macAddress = flag.String( @@ -290,21 +290,26 @@ func main() { "yaml-source-file", "", "yaml file where BMCS are defined. If this is set, ignore all other options") flag.Parse() var err error + bmcs := []bmoe2e.BMC{} if *configFile == "" { - if err = CreateLibvirtBMC(*macAddress, *vmName, *ipAddress, *networkName); err != nil { - fmt.Printf("Error occurred: %v\n", err) - os.Exit(1) + bmc := bmoe2e.BMC{ + IPAddress: *ipAddress, + BootMacAddress: *macAddress, + Name: *name, + NetworkName: *networkName, } + bmcs = append(bmcs, bmc) } else { - bmcs, err := bmoe2e.LoadBMCConfig(*configFile) + bmcs, err = bmoe2e.LoadBMCConfig(*configFile) if err != nil { + fmt.Printf("Error occurred: %v\n", err) os.Exit(1) } - for _, bmc := range *bmcs { - if err = CreateLibvirtBMC(bmc.BootMacAddress, bmc.HostName, bmc.IPAddress, "baremetal-e2e"); err != nil { - fmt.Printf("Error occurred: %v\n", err) - os.Exit(1) - } + } + for _, bmc := range bmcs { + if err = CreateLibvirtBMC(bmc.BootMacAddress, bmc.Name, bmc.IPAddress, "baremetal-e2e"); err != nil { + fmt.Printf("Error occurred: %v\n", err) + os.Exit(1) } } } diff --git a/test/vbmctl/templates/VM.xml.tpl b/test/vbmctl/templates/VM.xml.tpl index bd3de83fb7..1cc796a916 100644 --- a/test/vbmctl/templates/VM.xml.tpl +++ b/test/vbmctl/templates/VM.xml.tpl @@ -1,5 +1,5 @@ - {{ .HostName }} + {{ .Name }} 4194304 4194304 2 @@ -29,7 +29,7 @@ - + @@ -78,13 +78,13 @@ - + - + From 3f1ff15c895ded3e4f521ae0af29050f5c95f226 Mon Sep 17 00:00:00 2001 From: Lennart Jern Date: Mon, 27 Jan 2025 08:44:55 +0000 Subject: [PATCH 3/3] VBMCTL: Refactor Libvirt connection Initialize the connection once and reuse, instead of constantly creating new connections. Signed-off-by: Lennart Jern --- test/vbmctl/main.go | 60 +++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/test/vbmctl/main.go b/test/vbmctl/main.go index 9f9faf4add..5ddb1457b9 100644 --- a/test/vbmctl/main.go +++ b/test/vbmctl/main.go @@ -38,15 +38,7 @@ func RenderTemplate(inputFile string, data interface{}) (string, error) { // CreateVolumePool creates a volume pool with specified name if a pool with // that name does not exist yet. -func CreateVolumePool(poolName, poolPath string) (*libvirt.StoragePool, error) { - // Connect to libvirt daemon - conn, err := libvirt.NewConnect("qemu:///system") - if err != nil { - fmt.Println("Failed to connect to qemu:///system") - return nil, err - } - defer conn.Close() - +func CreateVolumePool(conn *libvirt.Connect, poolName, poolPath string) (*libvirt.StoragePool, error) { pool, err := conn.LookupStoragePoolByName(poolName) if err == nil { @@ -100,16 +92,8 @@ func CreateVolumePool(poolName, poolPath string) (*libvirt.StoragePool, error) { return pool, nil } -func CreateVolume(volumeName, poolName, poolPath string, capacityInGB int) error { - // Connect to libvirt daemon - conn, err := libvirt.NewConnect("qemu:///system") - if err != nil { - fmt.Println("Failed to connect to qemu:///system") - return err - } - defer conn.Close() - - pool, err := CreateVolumePool(poolName, poolPath) +func CreateVolume(conn *libvirt.Connect, volumeName, poolName, poolPath string, capacityInGB int) error { + pool, err := CreateVolumePool(conn, poolName, poolPath) if err != nil { fmt.Println("Failed to create storage pool") @@ -153,7 +137,7 @@ func CreateVolume(volumeName, poolName, poolPath string, capacityInGB int) error // If the domain is successfully defined and created, the virtual machine is // started. Errors during qcow2 file creation, volume creation, libvirt connection, // template rendering, or domain creation are returned. -func CreateLibvirtVM(name, networkName, macAddress string) error { +func CreateLibvirtVM(conn *libvirt.Connect, name, networkName, macAddress string) error { poolName := "default" poolPath := "/tmp/pool_oo" opts := make(map[string]any) @@ -169,17 +153,10 @@ func CreateLibvirtVM(name, networkName, macAddress string) error { return err } - if err = CreateVolume(name, poolName, poolPath, 20); err != nil { + if err = CreateVolume(conn, name, poolName, poolPath, 20); err != nil { return err } - conn, err := libvirt.NewConnect("qemu:///system") - if err != nil { - fmt.Println("Failed to connect to qemu:///system") - return err - } - defer conn.Close() - data := struct { Name string Network string @@ -216,19 +193,12 @@ func CreateLibvirtVM(name, networkName, macAddress string) error { return nil } -// CreateLibvirtBMC creates a VM with the given MAC address, name, IP address +// CreateLibvirtVMWithReservedIPAddress creates a VM with the given MAC address, name, IP address // and adds a DHCP host entry on the given network. // // It will return an error if the network does not exist, or if creating the VM // or adding the DHCP host entry fails. -func CreateLibvirtBMC(macAddress, name, ipAddress, networkName string) error { - var err error - conn, err := libvirt.NewConnect("qemu:///system") - if err != nil { - return err - } - defer conn.Close() - +func CreateLibvirtVMWithReservedIPAddress(conn *libvirt.Connect, macAddress, name, ipAddress, networkName string) error { network, err := conn.LookupNetworkByName(networkName) if err != nil { return err @@ -270,7 +240,7 @@ func CreateLibvirtBMC(macAddress, name, ipAddress, networkName string) error { fmt.Printf("Error occurred: %v\n", err) return err } - if err = CreateLibvirtVM(name, networkName, macAddress); err != nil { + if err = CreateLibvirtVM(conn, name, networkName, macAddress); err != nil { fmt.Printf("Error occurred: %v\n", err) return err } @@ -306,10 +276,20 @@ func main() { os.Exit(1) } } + + // Connect to Libvirt + conn, err := libvirt.NewConnect("qemu:///system") + if err != nil { + fmt.Printf("Error occurred: %v\n", err) + os.Exit(1) + } + defer conn.Close() + for _, bmc := range bmcs { - if err = CreateLibvirtBMC(bmc.BootMacAddress, bmc.Name, bmc.IPAddress, "baremetal-e2e"); err != nil { + if err = CreateLibvirtVMWithReservedIPAddress(conn, bmc.BootMacAddress, bmc.Name, bmc.IPAddress, "baremetal-e2e"); err != nil { fmt.Printf("Error occurred: %v\n", err) - os.Exit(1) + // Not using os.Exit here so that we still close the connection + break } } }