From e112fb70d1b0b21301f847a82dc51343e6ee3e0f Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Fri, 31 May 2024 14:43:07 +0200 Subject: [PATCH] Fix for NPE in superuserpassword (#129) --- cmd/bios.go | 14 +++++++------- cmd/install.go | 32 +++++++++++++++--------------- cmd/install_test.go | 2 +- cmd/reinstall.go | 4 ++-- cmd/root.go | 47 +++++++++++++++++++++------------------------ cmd/supwd.go | 6 +++--- 6 files changed, 51 insertions(+), 54 deletions(-) diff --git a/cmd/bios.go b/cmd/bios.go index 96fe40e..2105159 100644 --- a/cmd/bios.go +++ b/cmd/bios.go @@ -9,12 +9,12 @@ import ( // ConfigureBIOS ensures that UEFI boot is enabled and CSM-support is disabled. // It then reboots the machine. -func (h *Hammer) ConfigureBIOS() error { - if h.Hal.Board().VM { +func (h *hammer) ConfigureBIOS() error { + if h.hal.Board().VM { return nil } - reboot, err := h.Hal.ConfigureBIOS() + reboot, err := h.hal.ConfigureBIOS() if err != nil { return err } @@ -22,7 +22,7 @@ func (h *Hammer) ConfigureBIOS() error { if reboot { msg := "BIOS configuration requires a reboot" - h.EventEmitter.Emit(event.ProvisioningEventPlannedReboot, msg) + h.eventEmitter.Emit(event.ProvisioningEventPlannedReboot, msg) h.log.Info("bios", msg, "reboot in 1 sec") time.Sleep(1 * time.Second) err = kernel.Reboot() @@ -36,12 +36,12 @@ func (h *Hammer) ConfigureBIOS() error { // EnsureBootOrder ensures that the BIOS boot order is properly set, // i.e. first boot from OS image and then PXE boot -func (h *Hammer) EnsureBootOrder(bootloaderID string) error { - if h.Hal.Board().VM { +func (h *hammer) EnsureBootOrder(bootloaderID string) error { + if h.hal.Board().VM { return nil } - err := h.Hal.EnsureBootOrder(bootloaderID) + err := h.hal.EnsureBootOrder(bootloaderID) if err != nil { return err } diff --git a/cmd/install.go b/cmd/install.go index 80879cc..1b30a0d 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -22,8 +22,8 @@ import ( ) // Install a given image to the disk by using genuinetools/img -func (h *Hammer) Install(machine *models.V1MachineResponse) (*api.Bootinfo, error) { - s := storage.New(h.log, h.ChrootPrefix, *h.FilesystemLayout) +func (h *hammer) Install(machine *models.V1MachineResponse) (*api.Bootinfo, error) { + s := storage.New(h.log, h.chrootPrefix, *h.filesystemLayout) err := s.Run() if err != nil { return nil, err @@ -31,17 +31,17 @@ func (h *Hammer) Install(machine *models.V1MachineResponse) (*api.Bootinfo, erro image := machine.Allocation.Image.URL - err = img.NewImage(h.log).Pull(image, h.OsImageDestination) + err = img.NewImage(h.log).Pull(image, h.osImageDestination) if err != nil { return nil, err } - err = img.NewImage(h.log).Burn(h.ChrootPrefix, image, h.OsImageDestination) + err = img.NewImage(h.log).Burn(h.chrootPrefix, image, h.osImageDestination) if err != nil { return nil, err } - info, err := h.install(h.ChrootPrefix, machine, s.RootUUID) + info, err := h.install(h.chrootPrefix, machine, s.RootUUID) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func (h *Hammer) Install(machine *models.V1MachineResponse) (*api.Bootinfo, erro // install will execute /install.sh in the pulled docker image which was extracted onto disk // to finish installation e.g. install mbr, grub, write network and filesystem config -func (h *Hammer) install(prefix string, machine *models.V1MachineResponse, rootUUID string) (*api.Bootinfo, error) { +func (h *hammer) install(prefix string, machine *models.V1MachineResponse, rootUUID string) (*api.Bootinfo, error) { h.log.Info("install", "image", machine.Allocation.Image.URL) err := h.writeInstallerConfig(machine, rootUUID) @@ -148,10 +148,10 @@ func (h *Hammer) install(prefix string, machine *models.V1MachineResponse, rootU // writeLVMLocalConf to make lvm more compatible with os without udevd // will only be written if lvm is installed in the target image -func (h *Hammer) writeLVMLocalConf() error { +func (h *hammer) writeLVMLocalConf() error { srclvmlocal := "/etc/lvm/lvmlocal.conf" - dstlvm := path.Join(h.ChrootPrefix, "/etc/lvm") - dstlvmlocal := path.Join(h.ChrootPrefix, srclvmlocal) + dstlvm := path.Join(h.chrootPrefix, "/etc/lvm") + dstlvmlocal := path.Join(h.chrootPrefix, srclvmlocal) _, err := os.Stat(srclvmlocal) // FIXME use fileExists below if os.IsNotExist(err) { @@ -176,8 +176,8 @@ func (h *Hammer) writeLVMLocalConf() error { return nil } -func (h *Hammer) writeUserData(machine *models.V1MachineResponse) error { - configdir := path.Join(h.ChrootPrefix, "etc", "metal") +func (h *hammer) writeUserData(machine *models.V1MachineResponse) error { + configdir := path.Join(h.chrootPrefix, "etc", "metal") destination := path.Join(configdir, "userdata") base64UserData := machine.Allocation.UserData @@ -192,9 +192,9 @@ func (h *Hammer) writeUserData(machine *models.V1MachineResponse) error { return nil } -func (h *Hammer) writeInstallerConfig(machine *models.V1MachineResponse, rootUUiD string) error { +func (h *hammer) writeInstallerConfig(machine *models.V1MachineResponse, rootUUiD string) error { h.log.Info("write installation configuration") - configdir := path.Join(h.ChrootPrefix, "etc", "metal") + configdir := path.Join(h.chrootPrefix, "etc", "metal") err := os.MkdirAll(configdir, 0755) if err != nil { return fmt.Errorf("mkdir of %s target os failed %w", configdir, err) @@ -223,8 +223,8 @@ func (h *Hammer) writeInstallerConfig(machine *models.V1MachineResponse, rootUUi Hostname: *alloc.Hostname, SSHPublicKey: sshPubkeys, Networks: alloc.Networks, - MachineUUID: h.Spec.MachineUUID, - Password: h.Spec.ConsolePassword, + MachineUUID: h.spec.MachineUUID, + Password: h.spec.ConsolePassword, Console: console, Timestamp: time.Now().Format(time.RFC3339), Nics: h.onlyNicsWithNeighbors(machine.Hardware.Nics), @@ -242,7 +242,7 @@ func (h *Hammer) writeInstallerConfig(machine *models.V1MachineResponse, rootUUi return os.WriteFile(destination, yamlContent, 0600) } -func (h *Hammer) onlyNicsWithNeighbors(nics []*models.V1MachineNic) []*models.V1MachineNic { +func (h *hammer) onlyNicsWithNeighbors(nics []*models.V1MachineNic) []*models.V1MachineNic { noNeighbors := func(neighbors []*models.V1MachineNic) bool { if len(neighbors) == 0 { return true diff --git a/cmd/install_test.go b/cmd/install_test.go index f4ab377..c1f302b 100644 --- a/cmd/install_test.go +++ b/cmd/install_test.go @@ -45,7 +45,7 @@ func TestHammer_onlyNicsWithNeighbors(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - h := &Hammer{ + h := &hammer{ log: slog.Default(), } if got := h.onlyNicsWithNeighbors(tt.nics); !reflect.DeepEqual(got, tt.want) { diff --git a/cmd/reinstall.go b/cmd/reinstall.go index 70ba8b0..e594b42 100644 --- a/cmd/reinstall.go +++ b/cmd/reinstall.go @@ -9,14 +9,14 @@ import ( "github.com/metal-stack/metal-hammer/pkg/kernel" ) -func (h *Hammer) abortReinstall(reason error, machineID string, primaryDiskWiped bool) error { +func (h *hammer) abortReinstall(reason error, machineID string, primaryDiskWiped bool) error { h.log.Error("reinstall cancelled => boot into existing OS...", "reason", reason) var bootInfo *kernelapi.Bootinfo ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - resp, err := h.MetalAPIClient.BootService().AbortReinstall(ctx, &v1.BootServiceAbortReinstallRequest{Uuid: machineID, PrimaryDiskWiped: primaryDiskWiped}) + resp, err := h.metalAPIClient.BootService().AbortReinstall(ctx, &v1.BootServiceAbortReinstallRequest{Uuid: machineID, PrimaryDiskWiped: primaryDiskWiped}) if err != nil { h.log.Error("failed to abort reinstall", "error", err) time.Sleep(5 * time.Second) diff --git a/cmd/root.go b/cmd/root.go index b52e5aa..28da520 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,20 +20,17 @@ import ( "github.com/metal-stack/v" ) -// Hammer is the machine which forms a bare metal to a working server -type Hammer struct { - Spec *Specification +// hammer is the machine which forms a bare metal to a working server +type hammer struct { log *slog.Logger - Hal hal.InBand - MetalAPIClient *MetalAPIClient - EventEmitter *event.EventEmitter - LLDPClient *network.LLDPClient - FilesystemLayout *models.V1FilesystemLayoutResponse + spec *Specification + hal hal.InBand + metalAPIClient *MetalAPIClient + eventEmitter *event.EventEmitter + filesystemLayout *models.V1FilesystemLayoutResponse // IPAddress is the ip of the eth0 interface during installation - IPAddress string - Started time.Time - ChrootPrefix string - OsImageDestination string + chrootPrefix string + osImageDestination string } // Run orchestrates the whole register/wipe/format/burn and reboot process @@ -56,14 +53,14 @@ func Run(log *slog.Logger, spec *Specification, hal hal.InBand) (*event.EventEmi return eventEmitter, err } - hammer := &Hammer{ - Hal: hal, - Spec: spec, + hammer := &hammer{ + hal: hal, + spec: spec, log: log, - IPAddress: spec.IP, - EventEmitter: eventEmitter, - ChrootPrefix: "/rootfs", - OsImageDestination: "/tmp/os.tgz", + eventEmitter: eventEmitter, + chrootPrefix: "/rootfs", + osImageDestination: "/tmp/os.tgz", + metalAPIClient: metalAPIClient, } // Reboot after 24Hours if no allocation was requested. @@ -71,7 +68,7 @@ func Run(log *slog.Logger, spec *Specification, hal hal.InBand) (*event.EventEmi eventEmitter.Emit(event.ProvisioningEventPlannedReboot, "autoreboot after 24h") }) - hammer.Spec.ConsolePassword = password.Generate(16) + hammer.spec.ConsolePassword = password.Generate(16) err = hammer.createBmcSuperuser() if err != nil { @@ -111,7 +108,7 @@ func Run(log *slog.Logger, spec *Specification, hal hal.InBand) (*event.EventEmi } m := resp.Payload if m != nil && m.Allocation != nil && m.Allocation.Reinstall != nil && *m.Allocation.Reinstall { - hammer.FilesystemLayout = m.Allocation.Filesystemlayout + hammer.filesystemLayout = m.Allocation.Filesystemlayout primaryDiskWiped := false if m.Allocation.Image == nil || m.Allocation.Image.ID == nil { err = fmt.Errorf("no image specified") @@ -149,12 +146,12 @@ func Run(log *slog.Logger, spec *Specification, hal hal.InBand) (*event.EventEmi m = resp.Payload log.Info("perform install", "machineID", m.ID, "imageID", *m.Allocation.Image.ID) - hammer.FilesystemLayout = m.Allocation.Filesystemlayout + hammer.filesystemLayout = m.Allocation.Filesystemlayout err = hammer.installImage(eventEmitter, bootService, m) return eventEmitter, err } -func (h *Hammer) installImage(eventEmitter *event.EventEmitter, bootService v1.BootServiceClient, m *models.V1MachineResponse) error { +func (h *hammer) installImage(eventEmitter *event.EventEmitter, bootService v1.BootServiceClient, m *models.V1MachineResponse) error { eventEmitter.Emit(event.ProvisioningEventInstalling, "start installation") installationStart := time.Now() info, err := h.Install(m) @@ -165,9 +162,9 @@ func (h *Hammer) installImage(eventEmitter *event.EventEmitter, bootService v1.B } rep := &report.Report{ - MachineUUID: h.Spec.MachineUUID, + MachineUUID: h.spec.MachineUUID, Client: bootService, - ConsolePassword: h.Spec.ConsolePassword, + ConsolePassword: h.spec.ConsolePassword, Initrd: info.Initrd, Cmdline: info.Cmdline, Kernel: info.Kernel, diff --git a/cmd/supwd.go b/cmd/supwd.go index eaf4065..de193a5 100644 --- a/cmd/supwd.go +++ b/cmd/supwd.go @@ -9,9 +9,9 @@ import ( ) // createBmcSuperuser creates the bmc super user. -func (h *Hammer) createBmcSuperuser() error { +func (h *hammer) createBmcSuperuser() error { req := &v1.BootServiceSuperUserPasswordRequest{} - resp, err := h.MetalAPIClient.BootService().SuperUserPassword(context.Background(), req) + resp, err := h.metalAPIClient.BootService().SuperUserPassword(context.Background(), req) if err != nil { return fmt.Errorf("failed to fetch SuperUser password %w", err) } @@ -21,7 +21,7 @@ func (h *Hammer) createBmcSuperuser() error { return nil } - bmcConn := h.Hal.BMCConnection() + bmcConn := h.hal.BMCConnection() err = bmcConn.CreateUser(bmcConn.SuperUser(), api.AdministratorPrivilege, resp.SuperUserPassword) if err != nil {