Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions pkg/infrastructure/baremetal/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package baremetal

import (
"encoding/xml"
"errors"
"fmt"
"io"
"net/url"
"os"
"strings"

"github.com/digitalocean/go-libvirt"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -272,7 +274,7 @@ func createIgnition(virConn *libvirt.Libvirt, config baremetalConfig, pool libvi
return nil
}

func getCapabilities(virConn *libvirt.Libvirt) (libvirtxml.Caps, error) {
func getHostCapabilities(virConn *libvirt.Libvirt) (libvirtxml.Caps, error) {
var caps libvirtxml.Caps

capsBytes, err := virConn.Capabilities()
Expand All @@ -291,19 +293,25 @@ func getCapabilities(virConn *libvirt.Libvirt) (libvirtxml.Caps, error) {
func createBootstrapDomain(virConn *libvirt.Libvirt, config baremetalConfig, pool libvirt.StoragePool, volume libvirt.StorageVol) error {
bootstrapDom := newDomain(fmt.Sprintf("%s-bootstrap", config.ClusterID))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're so close to being able to pass the arch to newDomain() 😜

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that newDomain() returns all of the /static/ parts of the structure and then you can customize it with runtime values. 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or maybe using the builder pattern :)


if bootstrapDom.OS.Type.Arch == "aarch64" {
capabilities, err := getHostCapabilities(virConn)
if err != nil {
return fmt.Errorf("failed to get libvirt capabilities: %w", err)
}

arch := capabilities.Host.CPU.Arch
bootstrapDom.OS.Type.Arch = arch

if arch == "aarch64" {
// for aarch64 speciffying this will automatically select the firmware and NVRAM file
// reference: https://libvirt.org/formatdomain.html#bios-bootloader
bootstrapDom.OS.Firmware = "efi"
}

capabilities, err := getCapabilities(virConn)
if err != nil {
return fmt.Errorf("failed to get libvirt capabilities: %w", err)
// For aarch64, s390x, ppc64 and ppc64le spice is not supported
if arch == "aarch64" || arch == "s390x" || strings.HasPrefix(arch, "ppc64") {
bootstrapDom.Devices.Graphics = nil
}

bootstrapDom.OS.Type.Arch = capabilities.Host.CPU.Arch

for _, bridge := range config.Bridges {
netIface := libvirtxml.DomainInterface{
Model: &libvirtxml.DomainInterfaceModel{
Expand Down Expand Up @@ -451,9 +459,22 @@ func destroyBootstrap(config baremetalConfig) error {
}

logrus.Debug(" Undefining domain")
err = virConn.DomainUndefine(dom)
if err != nil {
return err

if err := virConn.DomainUndefineFlags(dom, libvirt.DomainUndefineNvram|libvirt.DomainUndefineSnapshotsMetadata|libvirt.DomainUndefineManagedSave|libvirt.DomainUndefineCheckpointsMetadata); err != nil {
var libvirtErr *libvirt.Error

if !errors.As(err, &libvirtErr) {
return fmt.Errorf("failed to cast to libvirt.Error: %w", err)
}

if libvirtErr.Code == uint32(libvirt.ErrNoSupport) || libvirtErr.Code == uint32(libvirt.ErrInvalidArg) {
logrus.Printf("libvirt does not support undefine flags: will try again without flags")
if err := virConn.DomainUndefine(dom); err != nil {
return fmt.Errorf("couldn't undefine libvirt domain: %w", err)
}
} else {
return fmt.Errorf("couldn't undefine libvirt domain with flags: %w", err)
}
}

pool, err := virConn.StoragePoolLookupByName(name)
Expand Down