From ff1a3b1add8850f8be7b66a9d0ce25882f5ea22b Mon Sep 17 00:00:00 2001 From: Joel Rebello Date: Wed, 7 Aug 2024 17:39:10 +0200 Subject: [PATCH 1/6] utils/uefi: fix up returned value to be returned from const came across this when fixing up another utility --- utils/uefi_firmware_parser.go | 7 ++++--- utils/uefi_vars.go | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/utils/uefi_firmware_parser.go b/utils/uefi_firmware_parser.go index 46b6af1a..7abcc4a8 100644 --- a/utils/uefi_firmware_parser.go +++ b/utils/uefi_firmware_parser.go @@ -13,7 +13,8 @@ import ( // https://github.com/linuxboot/fiano const ( - EnvUefiFirmwareParserUtility = "IRONLIB_UTIL_UTIL_UEFI_FIRMWARE_PARSER" + EnvUefiFirmwareParserUtility = "IRONLIB_UTIL_UTIL_UEFI_FIRMWARE_PARSER" + UefiFirmwareParserUtility model.CollectorUtility = "uefi-firmware-parser" ) type UefiFirmwareParser struct { @@ -24,7 +25,7 @@ var directoryPermissions fs.FileMode = 0o750 // Return a new UefiFirmwareParser executor func NewUefiFirmwareParserCmd(trace bool) *UefiFirmwareParser { - utility := "uefi-firmware-parser" + utility := string(UefiFirmwareParserUtility) // lookup env var for util if eVar := os.Getenv(EnvUefiFirmwareParserUtility); eVar != "" { @@ -46,7 +47,7 @@ func (u *UefiFirmwareParser) Attributes() (model.CollectorUtility, string, error // Call CheckExecutable first so that the Executable CmdPath is resolved. err := u.Executor.CheckExecutable() - return "uefi-firmware-parser", u.Executor.CmdPath(), err + return UefiFirmwareParserUtility, u.Executor.CmdPath(), err } // ExtractLogo extracts the Logo BMP image. It creates the output directory if required. diff --git a/utils/uefi_vars.go b/utils/uefi_vars.go index 68448515..923fc29a 100644 --- a/utils/uefi_vars.go +++ b/utils/uefi_vars.go @@ -11,10 +11,14 @@ import ( "github.com/metal-toolbox/ironlib/model" ) +const ( + UefiVariableCollectorUtility model.CollectorUtility = "uefi-variable-collector" +) + type UEFIVariableCollector struct{} func (UEFIVariableCollector) Attributes() (model.CollectorUtility, string, error) { - return "uefi-variable-collector", "", nil + return UefiVariableCollectorUtility, "", nil } type UEFIVarEntry struct { From f5bed4a61334420084908fadf7a7a20b6213d566 Mon Sep 17 00:00:00 2001 From: Joel Rebello Date: Wed, 7 Aug 2024 17:40:17 +0200 Subject: [PATCH 2/6] utils/lsblk: fix returned util name return whats defined in the const --- utils/lsblk.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/utils/lsblk.go b/utils/lsblk.go index 2abb26c5..f20f6e98 100644 --- a/utils/lsblk.go +++ b/utils/lsblk.go @@ -12,7 +12,8 @@ import ( ) const ( - EnvLsblkUtility = "IRONLIB_UTIL_LSBLK" + EnvLsblkUtility = "IRONLIB_UTIL_LSBLK" + LsblkUtility model.CollectorUtility = "lsblk" ) var ErrLsblkTransportUnsupported = errors.New("Unsupported transport type") @@ -32,7 +33,7 @@ type lsblkDeviceAttributes struct { // Return a new lsblk executor func NewLsblkCmd(trace bool) *Lsblk { - utility := "lsblk" + utility := string(LsblkUtility) // lookup env var for util if eVar := os.Getenv(EnvLsblkUtility); eVar != "" { @@ -54,7 +55,7 @@ func (l *Lsblk) Attributes() (utilName model.CollectorUtility, absolutePath stri // Call CheckExecutable first so that the Executable CmdPath is resolved. er := l.Executor.CheckExecutable() - return "lsblk", l.Executor.CmdPath(), er + return LsblkUtility, l.Executor.CmdPath(), er } // Executes lsblk list, parses the output and returns a slice of *common.Drive From 3c7e01ad5d388f10174c33c64bb582ccd7997d8f Mon Sep 17 00:00:00 2001 From: Joel Rebello Date: Wed, 7 Aug 2024 17:41:36 +0200 Subject: [PATCH 3/6] utils/msecli: add 5300MAX product name and update model lookup This adds support for the 5300MAX micron drive --- utils/msecli.go | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/utils/msecli.go b/utils/msecli.go index 71408f96..fe2693e0 100644 --- a/utils/msecli.go +++ b/utils/msecli.go @@ -124,10 +124,7 @@ func (m *Msecli) UpdateDrive(ctx context.Context, updateFile, modelNumber, seria } } - // get the product name from the model number - msecli expects the product name - modelNForMsecli := model.FormatProductName(d.ModelNumber) - - return m.updateDrive(ctx, modelNForMsecli, updateFile) + return m.updateDrive(ctx, d.ModelNumber, updateFile) } return ErrMseCliDriveNotIdentified @@ -135,12 +132,18 @@ func (m *Msecli) UpdateDrive(ctx context.Context, updateFile, modelNumber, seria // updateDrive installs the given updatefile func (m *Msecli) updateDrive(ctx context.Context, modelNumber, updateFile string) error { + // get the product name from the model number - msecli expects the product name + modelNForMsecli, err := mseCLIModelType(modelNumber) + if err != nil { + return err + } + // echo 'y' m.Executor.SetStdin(bytes.NewReader([]byte("y\n"))) m.Executor.SetArgs( "-U", // update "-m", // model - modelNumber, + modelNForMsecli, "-i", // directory containing the update file filepath.Dir(updateFile), ) @@ -219,3 +222,25 @@ func parseMsecliDeviceAttributes(bSlice []byte) *MsecliDevice { return device } + +// msecli expects a model type which we derive from the model number +// +// Invalid model type MICRON_5200_MTFDDAK480TDN! Valid options are: +// M500, M510, M550, MX100, M600, M500DC, MX200, BX100, P400M, P400E, M510DC, +// M500IT, BX200, BX300, S610DC, S630DC, S650DC, S655DC, 9100PRO, 9100MAX, 2100, +// TX3, MX300, 1100, M500ITL, 7100ECO, 7100MAX, 5100ECO, 5100PRO, 5100MAX, 5300PRO, +// 5300MAX, 5300BOOT, 5200ECO, 5200PRO, 5200MAX, 9200ECO, 9200MAX, 9200PRO, 9300ECO, 9300MAX, +// 9300PRO, 7300ECO, 7300MAX, 7300PRO, MX500, 5210, 1300, MX600, BX500, P1, +// 2200, 2200S, P4, 2300, 2300V, 2210, P1W2, 2100IT, 3400, 2450, +// BX503, BX504, P7 +func mseCLIModelType(mseModel string) (string, error) { + errUnsupported := errors.New("unsupported model number: " + mseModel) + switch mseModel { + case "Micron_5300_MTFDDAK480TDT": + return "5300MAX", nil + case "Micron_5200_MTFDDAK480TDN": + return "5200MAX", nil + default: + return "", errors.Wrap(errUnsupported, mseModel) + } +} From d7a38363b668c4cbb263ffe19a559c22a3bc2a3f Mon Sep 17 00:00:00 2001 From: Joel Rebello Date: Thu, 8 Aug 2024 12:08:17 +0200 Subject: [PATCH 4/6] UpdateNIC: accept force install parameter and pass force param to mlxup The force parameter is required to downgrade/reinstall firmware on a component --- actions/interface.go | 2 +- actions/update.go | 2 +- model/update.go | 2 +- providers/dell/dell.go | 2 +- utils/mlxup.go | 10 ++++++++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/actions/interface.go b/actions/interface.go index 60a0029c..4b363fb3 100644 --- a/actions/interface.go +++ b/actions/interface.go @@ -158,7 +158,7 @@ type DriveUpdater interface { // NICUpdater defines an interface to update NIC firmware type NICUpdater interface { UtilAttributeGetter - UpdateNIC(ctx context.Context, updateFile, modelNumber string) error + UpdateNIC(ctx context.Context, updateFile, modelNumber string, force bool) error } // BMCUpdater defines an interface to update BMC firmware diff --git a/actions/update.go b/actions/update.go index a3399c48..f16d6eee 100644 --- a/actions/update.go +++ b/actions/update.go @@ -133,7 +133,7 @@ func UpdateNIC(ctx context.Context, nics []*common.NIC, options *model.UpdateOpt return err } - return updater.UpdateNIC(ctx, options.UpdateFile, options.Model) + return updater.UpdateNIC(ctx, options.UpdateFile, options.Model, options.ForceInstall) } return errors.Wrap(ErrUpdaterUtilNotIdentified, options.Vendor) diff --git a/model/update.go b/model/update.go index 84860e1c..50494d79 100644 --- a/model/update.go +++ b/model/update.go @@ -2,7 +2,7 @@ package model // UpdateOptions sets firmware update options for a device component type UpdateOptions struct { - AllowDowngrade bool // Allow firmware to be downgraded + ForceInstall bool // Allow firmware to be downgraded InstallAll bool // Install all available updates (vendor tooling like DSU fetches the updates and installs them) DownloadOnly bool // Only download updates, skip install - Works with InstallAll (where updates are fetched by the vendor tooling) Serial string diff --git a/providers/dell/dell.go b/providers/dell/dell.go index d898003c..e5bf6196 100644 --- a/providers/dell/dell.go +++ b/providers/dell/dell.go @@ -172,7 +172,7 @@ func (d *dell) InstallUpdates(ctx context.Context, options *model.UpdateOptions) return d.installAvailableUpdates(ctx, options.DownloadOnly) } - exitCode, err := d.installUpdate(ctx, options.Slug, options.AllowDowngrade) + exitCode, err := d.installUpdate(ctx, options.Slug, options.ForceInstall) if err != nil { return err } diff --git a/utils/mlxup.go b/utils/mlxup.go index 2971824e..257038a6 100644 --- a/utils/mlxup.go +++ b/utils/mlxup.go @@ -150,7 +150,7 @@ func setNICFirmware(d *MlxupDevice, firmware *common.Firmware) { } // UpdateNIC updates mellanox NIC with the given update file -func (m *Mlxup) UpdateNIC(ctx context.Context, updateFile, modelNumber string) error { +func (m *Mlxup) UpdateNIC(ctx context.Context, updateFile, modelNumber string, force bool) error { // query list of nics nics, err := m.Query(ctx) if err != nil { @@ -165,7 +165,13 @@ func (m *Mlxup) UpdateNIC(ctx context.Context, updateFile, modelNumber string) e } } - m.Executor.SetArgs("--yes", "--dev", nic.PCIDeviceName, "--image-file", updateFile) + args := []string{"--yes", "--dev", nic.PCIDeviceName, "--image-file", updateFile} + + if force { + args = append(args, "--force") + } + + m.Executor.SetArgs(args...) result, err := m.Executor.Exec(ctx) if err != nil { return err From 0ebda50c975bba80e3e903e6e1025dff4aac4bf8 Mon Sep 17 00:00:00 2001 From: Joel Rebello Date: Thu, 8 Aug 2024 12:10:18 +0200 Subject: [PATCH 5/6] actions/update: format NIC vendor attribute for comparision --- actions/update.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/actions/update.go b/actions/update.go index f16d6eee..5b7e44f5 100644 --- a/actions/update.go +++ b/actions/update.go @@ -124,11 +124,12 @@ func GetNICUpdater(vendor string) (NICUpdater, error) { // UpdateNIC identifies the nic eligible for update from the inventory and runs the firmware update utility based on the nic vendor func UpdateNIC(ctx context.Context, nics []*common.NIC, options *model.UpdateOptions) error { for _, nic := range nics { - if !strings.EqualFold(options.Vendor, nic.Vendor) { + nicVendor := common.FormatVendorName(nic.Vendor) + if !strings.EqualFold(options.Vendor, nicVendor) { continue } - updater, err := GetNICUpdater(nic.Vendor) + updater, err := GetNICUpdater(nicVendor) if err != nil { return err } From 8b4513588cf88baafeb0a03cab8054518149c803 Mon Sep 17 00:00:00 2001 From: Joel Rebello Date: Thu, 8 Aug 2024 12:24:45 +0200 Subject: [PATCH 6/6] actions/NICUpdater: extend interface for update requirements method The UpdateRequirements() method is implemented by the mlxup NIC update utility --- actions/interface.go | 1 + model/update.go | 5 +++++ utils/mlxup.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/actions/interface.go b/actions/interface.go index 4b363fb3..601f8390 100644 --- a/actions/interface.go +++ b/actions/interface.go @@ -159,6 +159,7 @@ type DriveUpdater interface { type NICUpdater interface { UtilAttributeGetter UpdateNIC(ctx context.Context, updateFile, modelNumber string, force bool) error + UpdateRequirements() model.UpdateRequirements } // BMCUpdater defines an interface to update BMC firmware diff --git a/model/update.go b/model/update.go index 50494d79..eb99152e 100644 --- a/model/update.go +++ b/model/update.go @@ -15,3 +15,8 @@ type UpdateOptions struct { RepositoryVersion string // The update repository version to activate when defined BaseURL string // The BaseURL for the updates } + +// UpdateRequirements holds attributes that indicate requirements for before/after a component firmware install +type UpdateRequirements struct { + PostInstallPowerCycle bool +} diff --git a/utils/mlxup.go b/utils/mlxup.go index 257038a6..5e98d2f3 100644 --- a/utils/mlxup.go +++ b/utils/mlxup.go @@ -149,6 +149,11 @@ func setNICFirmware(d *MlxupDevice, firmware *common.Firmware) { } } +// UpdateRequirements implements the actions/NICUpdater interface to return any pre/post firmware install requirements. +func (m *Mlxup) UpdateRequirements() model.UpdateRequirements { + return model.UpdateRequirements{PostInstallPowerCycle: true} +} + // UpdateNIC updates mellanox NIC with the given update file func (m *Mlxup) UpdateNIC(ctx context.Context, updateFile, modelNumber string, force bool) error { // query list of nics