diff --git a/actions/interface.go b/actions/interface.go index ba92f820..a06e3482 100644 --- a/actions/interface.go +++ b/actions/interface.go @@ -2,6 +2,7 @@ package actions import ( "context" + "log/slog" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib/model" @@ -202,5 +203,5 @@ type VirtualDiskManager interface { // DiskWiper defines an interface to override disk data type DiskWiper interface { - WipeDisk(ctx context.Context, logicalName string) error + WipeDisk(ctx context.Context, log *slog.Logger, logicalName string) error } diff --git a/actions/inventory.go b/actions/inventory.go index 76ab4a86..5a21cd57 100644 --- a/actions/inventory.go +++ b/actions/inventory.go @@ -4,6 +4,7 @@ package actions import ( "context" "encoding/json" + "log/slog" "runtime/debug" "strings" @@ -13,7 +14,6 @@ import ( "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" "github.com/r3labs/diff/v2" - "github.com/sirupsen/logrus" "golang.org/x/exp/slices" ) @@ -28,7 +28,7 @@ type InventoryCollectorAction struct { collectors Collectors // something to track our execution - log *logrus.Logger + log *slog.Logger // device is the model in which the collected inventory is recorded. device *common.Device @@ -130,9 +130,10 @@ func WithDisabledCollectorUtilities(utilityNames []model.CollectorUtility) Optio } // NewActionrunner returns an Actions runner that is capable of collecting inventory. -func NewInventoryCollectorAction(ll *logrus.Logger, options ...Option) *InventoryCollectorAction { +func NewInventoryCollectorAction(log *slog.Logger, options ...Option) *InventoryCollectorAction { a := &InventoryCollectorAction{ - log: ll, + log: log, + trace: log.Enabled(nil, -5), } // set options to override @@ -205,7 +206,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect initial device inventory a.log.Debug("collect initial inventory") err := a.collectors.InventoryCollector.Collect(ctx, a.device) - a.log.WithError(err).Debug("collect initial done") + a.log.Debug("collect initial done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving device inventory") } @@ -213,7 +214,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect drive smart data a.log.Debug("collect drives") err = a.CollectDrives(ctx) - a.log.WithError(err).Debug("collect drives done") + a.log.Debug("collect drives done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving drive inventory") } @@ -221,7 +222,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect NIC info a.log.Debug("collect nics") err = a.CollectNICs(ctx) - a.log.WithError(err).Debug("collect nics done") + a.log.Debug("collect nics done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving NIC inventory") } @@ -229,7 +230,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect BIOS info a.log.Debug("collect bios") err = a.CollectBIOS(ctx) - a.log.WithError(err).Debug("collect bios done") + a.log.Debug("collect bios done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving BIOS inventory") } @@ -237,7 +238,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect CPLD info a.log.Debug("collect cpld") err = a.CollectCPLDs(ctx) - a.log.WithError(err).Debug("collect cpld done") + a.log.Debug("collect cpld done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving CPLD inventory") } @@ -245,7 +246,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect BMC info a.log.Debug("collect bmc") err = a.CollectBMC(ctx) - a.log.WithError(err).Debug("collect bmc done") + a.log.Debug("collect bmc done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving BMC inventory") } @@ -253,7 +254,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect TPM info a.log.Debug("collect tpm") err = a.CollectTPMs(ctx) - a.log.WithError(err).Debug("collect tpm done") + a.log.Debug("collect tpm done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving TPM inventory") } @@ -261,7 +262,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect Firmware checksums a.log.Debug("collect firmware checksum") err = a.CollectFirmwareChecksums(ctx) - a.log.WithError(err).Debug("collect firmware checksum done") + a.log.Debug("collect firmware checksum done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving Firmware checksums") } @@ -269,7 +270,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect UEFI variables a.log.Debug("collect uefi variables") err = a.CollectUEFIVariables(ctx) - a.log.WithError(err).Debug("collect uefi variables done") + a.log.Debug("collect uefi variables done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving UEFI variables") } @@ -286,7 +287,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D // Collect StorageController info a.log.Debug("collect storage controller") err = a.CollectStorageControllers(ctx) - a.log.WithError(err).Debug("collect storage controller done") + a.log.Debug("collect storage controller done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving StorageController inventory") } @@ -302,7 +303,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D if len(a.collectors.DriveCollectors) > 0 { a.log.Debug("dynamic collect drive") err = a.CollectDrives(ctx) - a.log.WithError(err).Debug("dynamic collect drive done") + a.log.Debug("dynamic collect drive done", "error", err) if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving drive inventory") @@ -316,7 +317,7 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D if err != nil && a.failOnError { return errors.Wrap(err, "error retrieving DriveCapabilities") } - a.log.WithError(err).Debug("collect drive capabilities done") + a.log.Debug("collect drive capabilities done", "error", err) a.setDefaultAttributes() @@ -731,13 +732,13 @@ func (a *InventoryCollectorAction) CollectFirmwareChecksums(ctx context.Context) sumStr, err := a.collectors.FirmwareChecksumCollector.BIOSLogoChecksum(ctx) if err != nil { - a.log.WithError(err).Warn("error collecting BIOS Logo checksum") + a.log.Warn("error collecting BIOS Logo checksum", "error", err) return err } if a.device.BIOS == nil { // XXX: how did we get here? - a.log.Error("nil device bios data") + a.log.Error("expected bios data", "error", errors.New("nil device bios data")) return nil } diff --git a/actions/inventory_test.go b/actions/inventory_test.go index fa6d1738..44d26f8b 100644 --- a/actions/inventory_test.go +++ b/actions/inventory_test.go @@ -11,7 +11,7 @@ import ( smcFixtures "github.com/metal-toolbox/ironlib/fixtures/supermicro" "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" - "github.com/sirupsen/logrus" + "github.com/neilotoole/slogt" "github.com/stretchr/testify/assert" ) @@ -47,7 +47,7 @@ func Test_Inventory_dell(t *testing.T) { WithDisabledCollectorUtilities([]model.CollectorUtility{"dmidecode"}), } - collector := NewInventoryCollectorAction(logrus.New(), options...) + collector := NewInventoryCollectorAction(slogt.New(t), options...) if err := collector.Collect(context.TODO(), &device); err != nil { t.Error(err) } @@ -124,7 +124,7 @@ func Test_Inventory_smc(t *testing.T) { StorageControllerCollectors: []StorageControllerCollector{storecli}, } - collector := NewInventoryCollectorAction(logrus.New(), WithCollectors(collectors), WithTraceLevel()) + collector := NewInventoryCollectorAction(slogt.New(t), WithCollectors(collectors), WithTraceLevel()) if err := collector.Collect(context.TODO(), &device); err != nil { t.Error(err) } @@ -187,7 +187,7 @@ func TestNewInventoryCollectorAction(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := NewInventoryCollectorAction(logrus.New(), tt.options...) + got := NewInventoryCollectorAction(slogt.New(t), tt.options...) switch tt.name { case "trace-enabled": diff --git a/actions/storage_controller.go b/actions/storage_controller.go index cecf9f21..f48dadd6 100644 --- a/actions/storage_controller.go +++ b/actions/storage_controller.go @@ -3,24 +3,27 @@ package actions import ( "context" "fmt" - "log" + "log/slog" "strings" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) var ErrVirtualDiskManagerUtilNotIdentified = errors.New("virtual disk management utility not identifed") type StorageControllerAction struct { - Logger *logrus.Logger + Logger *slog.Logger + trace bool } -func NewStorageControllerAction(logger *logrus.Logger) *StorageControllerAction { - return &StorageControllerAction{logger} +func NewStorageControllerAction(logger *slog.Logger) *StorageControllerAction { + return &StorageControllerAction{ + Logger: logger, + trace: logger.Enabled(nil, -5), + } } func (s *StorageControllerAction) CreateVirtualDisk(ctx context.Context, hba *common.StorageController, options *model.CreateVirtualDiskOptions) error { @@ -67,14 +70,8 @@ func (s *StorageControllerAction) ListVirtualDisks(ctx context.Context, hba *com // GetControllerUtility returns the utility command for the given vendor func (s *StorageControllerAction) GetControllerUtility(vendorName, modelName string) (VirtualDiskManager, error) { - var trace bool - - if s.Logger.GetLevel().String() == "trace" { - trace = true - } - if strings.EqualFold(vendorName, common.VendorMarvell) { - return utils.NewMvcliCmd(trace), nil + return utils.NewMvcliCmd(s.trace), nil } return nil, errors.Wrap(ErrVirtualDiskManagerUtilNotIdentified, "vendor: "+vendorName+" model: "+modelName) @@ -82,43 +79,28 @@ func (s *StorageControllerAction) GetControllerUtility(vendorName, modelName str // GetWipeUtility returns the wipe utility based on the disk wipping features func (s *StorageControllerAction) GetWipeUtility(logicalName string) (DiskWiper, error) { - var trace bool - - if s.Logger.GetLevel().String() == "trace" { - trace = true - } - // TODO: use disk wipping features to return the best wipe utility, currently only one available - if trace { - log.Printf("%s | Detecting wipe utility", logicalName) - } - - return utils.NewFillZeroCmd(trace), nil + s.Logger.Debug("Detecting wipe utility", "device", logicalName) + return utils.NewFillZeroCmd(s.trace), nil } -func (s *StorageControllerAction) WipeDisk(ctx context.Context, logicalName string) error { +func (s *StorageControllerAction) WipeDisk(ctx context.Context, log *slog.Logger, logicalName string) error { util, err := s.GetWipeUtility(logicalName) if err != nil { return err } + // Watermark disk // Before wiping the disk, we apply watermarks to later verify successful deletion - log.Printf("%s | Initiating watermarking process", logicalName) check, err := utils.ApplyWatermarks(logicalName) if err != nil { return err } + // Wipe the disk - err = util.WipeDisk(ctx, logicalName) + err = util.WipeDisk(ctx, log, logicalName) if err != nil { return err } - // Check if the watermark has been removed after wiping - log.Printf("%s | Checking if the watermark has been removed", logicalName) - err = check() - if err != nil { - return err - } - // Watermarks have been successfully removed, indicating successful deletion - log.Printf("%s | Watermarks has been removed", logicalName) - return nil + + return check() } diff --git a/device.go b/device.go index 160f5b4a..d3429d92 100644 --- a/device.go +++ b/device.go @@ -2,6 +2,7 @@ package ironlib import ( "fmt" + "log/slog" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib/actions" @@ -12,12 +13,11 @@ import ( "github.com/metal-toolbox/ironlib/providers/supermicro" "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) // New returns a device Manager interface based on the hardware deviceVendor, model attributes // by default returns a Generic device instance that only returns the device inventory -func New(logger *logrus.Logger) (m actions.DeviceManager, err error) { +func New(logger *slog.Logger) (m actions.DeviceManager, err error) { dmidecode, err := utils.NewDmidecode() if err != nil { return nil, errors.Wrap(errs.ErrDmiDecodeRun, err.Error()) @@ -94,18 +94,3 @@ func CheckDependencies() { fmt.Printf("util: %s, path: %s %s[ok]%s\n", name, uPath, green, reset) } } - -// Logformat adds default fields to each log entry. -type LogFormat struct { - Fields logrus.Fields - Formatter logrus.Formatter -} - -// Format satisfies the logrus.Formatter interface. -func (f *LogFormat) Format(e *logrus.Entry) ([]byte, error) { - for k, v := range f.Fields { - e.Data[k] = v - } - - return f.Formatter.Format(e) -} diff --git a/examples/biosconfig/biosconfig.go b/examples/biosconfig/biosconfig.go index 07cef091..65284cf6 100644 --- a/examples/biosconfig/biosconfig.go +++ b/examples/biosconfig/biosconfig.go @@ -4,29 +4,37 @@ import ( "context" "encoding/json" "fmt" + "log/slog" + "os" "github.com/metal-toolbox/ironlib" - "github.com/sirupsen/logrus" ) // This example invokes ironlib and prints out the BIOS features on supported platforms // a sample output can be seen in the biosconfig.json file func main() { - logger := logrus.New() + trace := &slog.LevelVar{} + trace.Set(-5) + h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: trace}) + logger := slog.New(h) + device, err := ironlib.New(logger) if err != nil { - logger.Fatal(err) + logger.Error("creating ironlib manager", "error", err) + os.Exit(1) } features, err := device.GetBIOSConfiguration(context.TODO()) if err != nil { - logger.Fatal(err) + logger.Error("getting bios config", "error", err) + os.Exit(1) } j, err := json.MarshalIndent(features, " ", " ") if err != nil { - logger.Fatal(err) + logger.Error("formatting json", "error", err) + os.Exit(1) } fmt.Println(string(j)) diff --git a/examples/diskwipe/main.go b/examples/diskwipe/main.go index 43124f05..8657a8fd 100644 --- a/examples/diskwipe/main.go +++ b/examples/diskwipe/main.go @@ -2,24 +2,29 @@ package main import ( "context" + "log/slog" + "os" "time" "github.com/metal-toolbox/ironlib/actions" - "github.com/sirupsen/logrus" ) // This example invokes ironlib and wipes the disk /dev/sdZZZ with a timeout of 1 day func main() { - logger := logrus.New() - logger.Formatter = new(logrus.JSONFormatter) - logger.SetLevel(logrus.TraceLevel) + trace := &slog.LevelVar{} + trace.Set(-5) + h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: trace}) + logger := slog.New(h) + sca := actions.NewStorageControllerAction(logger) ctx, cancel := context.WithTimeout(context.Background(), 86400*time.Second) defer cancel() - err := sca.WipeDisk(ctx, "/dev/sdZZZ") + + err := sca.WipeDisk(ctx, logger, "/dev/sdZZZ") if err != nil { - logger.Fatal(err) + logger.Error("wiping disk", "error", err) + os.Exit(0) } - logger.Println("Wiped successfully!") + logger.Info("Wiped successfully!") } diff --git a/examples/firmware-install/firmware-install.go b/examples/firmware-install/firmware-install.go index ce2e566e..441774fe 100644 --- a/examples/firmware-install/firmware-install.go +++ b/examples/firmware-install/firmware-install.go @@ -3,21 +3,26 @@ package main import ( "context" "fmt" + "log/slog" + "os" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib" "github.com/metal-toolbox/ironlib/model" - "github.com/sirupsen/logrus" ) // This example invokes ironlib to install the supermicro BMC firmware func main() { - logger := logrus.New() + trace := &slog.LevelVar{} + trace.Set(-5) + h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: trace}) + logger := slog.New(h) device, err := ironlib.New(logger) if err != nil { - logger.Fatal(err) + logger.Error("creating ironlib manager", "error", err) + os.Exit(1) } options := &model.UpdateOptions{ @@ -29,13 +34,15 @@ func main() { hardware, err := device.GetInventory(context.TODO()) if err != nil { - logger.Fatal(err) + logger.Error("getting inventory", "error", err) + os.Exit(1) } fmt.Println(hardware.BMC.Firmware.Installed) err = device.InstallUpdates(context.TODO(), options) if err != nil { - logger.Fatal(err) + logger.Error("insatlling updates", "error", err) + os.Exit(1) } } diff --git a/examples/inventory/inventory.go b/examples/inventory/inventory.go index 9630b48b..4e4a8916 100644 --- a/examples/inventory/inventory.go +++ b/examples/inventory/inventory.go @@ -4,31 +4,37 @@ import ( "context" "encoding/json" "fmt" + "log/slog" + "os" "github.com/metal-toolbox/ironlib" - "github.com/sirupsen/logrus" ) // This example invokes ironlib and prints out the device inventory // a sample output can be seen in the inventory.json file func main() { - logger := logrus.New() - logger.Formatter = new(logrus.JSONFormatter) - logger.SetLevel(logrus.TraceLevel) + trace := &slog.LevelVar{} + trace.Set(-5) + h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: trace}) + logger := slog.New(h) + device, err := ironlib.New(logger) if err != nil { - logger.Fatal(err) + logger.Error("creating ironlib manager", "error", err) + os.Exit(1) } inv, err := device.GetInventory(context.TODO()) if err != nil { - logger.Fatal(err) + logger.Error("getting inventory", "error", err) + os.Exit(1) } j, err := json.MarshalIndent(inv, " ", " ") if err != nil { - logger.Fatal(err) + logger.Error("formatting json", "error", err) + os.Exit(1) } fmt.Println(string(j)) diff --git a/go.mod b/go.mod index 2ac21609..077631de 100644 --- a/go.mod +++ b/go.mod @@ -6,15 +6,13 @@ require ( github.com/beevik/etree v1.1.0 github.com/bmc-toolbox/common v0.0.0-20230220061748-93ff001f4a1d github.com/dselans/dmidecode v0.0.0-20180814053009-65c3f9d81910 + github.com/neilotoole/slogt v1.1.0 github.com/pkg/errors v0.9.1 github.com/r3labs/diff/v2 v2.15.1 - github.com/r3labs/diff/v3 v3.0.1 - github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.2 github.com/tidwall/gjson v1.14.4 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/net v0.9.0 - gotest.tools v2.2.0+incompatible ) require ( @@ -26,7 +24,6 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect - golang.org/x/sys v0.7.0 // indirect golang.org/x/text v0.9.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 574d8c36..89ce6ae2 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/neilotoole/slogt v1.1.0 h1:c7qE92sq+V0yvCuaxph+RQ2jOKL61c4hqS1Bv9W7FZE= +github.com/neilotoole/slogt v1.1.0/go.mod h1:RCrGXkPc/hYybNulqQrMHRtvlQ7F6NktNVLuLwk6V+w= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -29,17 +31,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/r3labs/diff/v2 v2.15.1 h1:EOrVqPUzi+njlumoqJwiS/TgGgmZo83619FNDB9xQUg= github.com/r3labs/diff/v2 v2.15.1/go.mod h1:I8noH9Fc2fjSaMxqF3G2lhDdC0b+JXCfyx85tWFM9kc= -github.com/r3labs/diff/v3 v3.0.1/go.mod h1:f1S9bourRbiM66NskseyUdo0fTmEE0qKrikYJX63dgo= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= @@ -53,8 +50,6 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= -github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -62,9 +57,6 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= @@ -85,5 +77,3 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/providers/asrockrack/asrockrack.go b/providers/asrockrack/asrockrack.go index 35761106..362c3fdf 100644 --- a/providers/asrockrack/asrockrack.go +++ b/providers/asrockrack/asrockrack.go @@ -2,31 +2,23 @@ package asrockrack import ( "context" + "log/slog" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib/actions" "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" - "github.com/sirupsen/logrus" ) // A asrockrack device has methods to collect hardware inventory, regardless of the vendor type asrockrack struct { trace bool hw *model.Hardware - logger *logrus.Logger + logger *slog.Logger } // New returns a ASRockRack device manager -func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, error) { - var trace bool - - if l.Level == logrus.TraceLevel { - trace = true - } - - var err error - +func New(dmidecode *utils.Dmidecode, l *slog.Logger) (actions.DeviceManager, error) { // set device device := common.NewDevice() @@ -43,7 +35,6 @@ func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, e dm := &asrockrack{ hw: model.NewHardware(&device), logger: l, - trace: trace, } return dm, nil diff --git a/providers/dell/dell.go b/providers/dell/dell.go index 2ab62888..339f4c69 100644 --- a/providers/dell/dell.go +++ b/providers/dell/dell.go @@ -2,6 +2,7 @@ package dell import ( "context" + "log/slog" "os" "github.com/bmc-toolbox/common" @@ -10,7 +11,6 @@ import ( "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) // The dell device provider struct @@ -19,7 +19,10 @@ type dell struct { hw *model.Hardware dnf *utils.Dnf dsu *utils.Dsu - logger *logrus.Logger + logger *slog.Logger + trace bool + updateBaseURL string + // The DSU package version // for example 1.9.1.0-21.03.00 from https://linux.dell.com/repo/hardware/DSU_21.05.01/os_independent/x86_64/dell-system-update-1.9.1.0-21.03.00.x86_64.rpm dsuPackageVersion string @@ -27,18 +30,10 @@ type dell struct { // The DSU release version // for example: 21.05.01, from https://linux.dell.com/repo/hardware/DSU_21.05.01 dsuReleaseVersion string - - updateBaseURL string } // New returns a new Dell device manager -func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, error) { - var trace bool - - if l.GetLevel().String() == "trace" { - trace = true - } - +func New(dmidecode *utils.Dmidecode, l *slog.Logger) (actions.DeviceManager, error) { deviceVendor, err := dmidecode.Manufacturer() if err != nil { return nil, errors.Wrap(errs.NewDmidecodeValueError("manufacturer", "", 0), err.Error()) @@ -78,6 +73,7 @@ func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, e updateBaseURL := os.Getenv(model.EnvUpdateBaseURL) // set device manager + trace := l.Enabled(nil, -5) dm := &dell{ hw: model.NewHardware(&device), dnf: utils.NewDnf(trace), @@ -86,6 +82,7 @@ func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, e dsuPackageVersion: dsuPackageVersion, updateBaseURL: updateBaseURL, logger: l, + trace: trace, } return dm, nil @@ -157,7 +154,7 @@ func (d *dell) ListAvailableUpdates(ctx context.Context, options *model.UpdateOp return nil, nil } - d.logger.WithField("count", count).Info("component updates identified..") + d.logger.Info("component updates identified", "count", count) d.hw.OemComponents.Dell = append(d.hw.OemComponents.Dell, oemUpdates...) @@ -190,10 +187,10 @@ func (d *dell) installAvailableUpdates(ctx context.Context, downloadOnly bool) e if err != nil { switch exitCode { case utils.DSUExitCodeNoUpdatesAvailable: - d.logger.Debug("update(s) not applicable for this device") + d.logger.Warn("update(s) not applicable for this device") return errs.ErrNoUpdatesApplicable case utils.DSUExitCodeRebootRequired: - d.logger.Debug("update(s) applied, device requires a reboot") + d.logger.Warn("update(s) applied, device requires a reboot") d.hw.PendingReboot = true default: return err @@ -219,13 +216,7 @@ func (d *dell) setUpdateOptions(options *model.UpdateOptions) { d.updateBaseURL = options.BaseURL } - d.logger.WithFields( - logrus.Fields{ - "dsu version": d.dsuPackageVersion, - "dsu repo": d.dsuReleaseVersion, - "base url": d.updateBaseURL, - }, - ).Info("update parameters") + d.logger.Info("update parameters", "dsu version", d.dsuPackageVersion, "dsu repo", d.dsuReleaseVersion, "base url", d.updateBaseURL) } // ApplyUpdate is here to satisfy the actions.Updater interface diff --git a/providers/dell/dell_test.go b/providers/dell/dell_test.go index 2974a989..27236e17 100644 --- a/providers/dell/dell_test.go +++ b/providers/dell/dell_test.go @@ -11,13 +11,13 @@ import ( dellFixtures "github.com/metal-toolbox/ironlib/fixtures/dell" "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" - "github.com/sirupsen/logrus" - "gotest.tools/assert" + "github.com/neilotoole/slogt" + "github.com/stretchr/testify/assert" ) var r6515fixtures = "../../fixtures/dell/r6515" -func newFakeDellDevice() *dell { +func newFakeDellDevice(t *testing.T) *dell { device := common.NewDevice() device.Oem = true @@ -31,7 +31,7 @@ func newFakeDellDevice() *dell { return &dell{ hw: hardware, dnf: utils.NewFakeDnf(), - logger: logrus.New(), + logger: slogt.New(t), } } @@ -42,7 +42,7 @@ func TestGetInventory(t *testing.T) { expected.Oem = true expectedOemComponents := dellFixtures.R6515_oem_components - dell := newFakeDellDevice() + dell := newFakeDellDevice(t) // dsu b, err := os.ReadFile(r6515fixtures + "/dsu_inventory") @@ -92,13 +92,13 @@ func TestGetInventory(t *testing.T) { t.Error(err) } - assert.DeepEqual(t, dellFixtures.R6515_inventory_lshw_smartctl, device) - assert.DeepEqual(t, expectedOemComponents, dell.hw.OemComponents) + assert.Equal(t, dellFixtures.R6515_inventory_lshw_smartctl, device) + assert.Equal(t, expectedOemComponents, dell.hw.OemComponents) } // Get inventory, not listing updates available func TestListUpdates(t *testing.T) { - dell := newFakeDellDevice() + dell := newFakeDellDevice(t) // dsu b, err := os.ReadFile(r6515fixtures + "/dsu_preview") @@ -121,5 +121,5 @@ func TestListUpdates(t *testing.T) { t.Error(err) } - assert.DeepEqual(t, dellFixtures.R6515_updatePreview, device) + assert.Equal(t, dellFixtures.R6515_updatePreview, device) } diff --git a/providers/dell/helpers.go b/providers/dell/helpers.go index 249597e2..ba221716 100644 --- a/providers/dell/helpers.go +++ b/providers/dell/helpers.go @@ -8,7 +8,6 @@ import ( "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) const ( @@ -74,22 +73,19 @@ func (d *dell) installUpdate(ctx context.Context, updateFile string, downgrade b e := utils.NewExecutor(updateFile) e.SetArgs(args) - if d.logger.Level == logrus.TraceLevel { + if d.trace { e.SetVerbose() } - d.logger.WithFields( - logrus.Fields{"file": updateFile}, - ).Info("Installing dell Update Bin file") + logger := d.logger.With("file", updateFile) + logger.Info("Installing dell Update Bin file") result, err := e.ExecWithContext(ctx) if err != nil { return result.ExitCode, err } - d.logger.WithFields( - logrus.Fields{"file": updateFile}, - ).Info("Installed") + logger.Info("Installed") d.hw.PendingReboot = true @@ -224,17 +220,17 @@ func (d *dell) checkExitCode(exitCode int) error { case utils.DSUExitCodeUpdatesApplied: d.hw.UpdatesInstalled = true d.hw.PendingReboot = true - d.logger.Trace("update applied successfully") + d.logger.Debug("update applied successfully") return nil case utils.DSUExitCodeRebootRequired, BinUpdateExitCodeRebootRequired: // updates applied, reboot required - d.logger.Trace("update applied, reboot required") + d.logger.Debug("update applied, reboot required") d.hw.UpdatesInstalled = true d.hw.PendingReboot = true return nil case utils.DSUExitCodeNoUpdatesAvailable: // no applicable updates - d.logger.Trace("no pending/applicable update(s) for device") + d.logger.Debug("no pending/applicable update(s) for device") return nil default: diff --git a/providers/generic/generic.go b/providers/generic/generic.go index f9b73f87..0226c1bc 100644 --- a/providers/generic/generic.go +++ b/providers/generic/generic.go @@ -2,6 +2,7 @@ package generic import ( "context" + "log/slog" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib/actions" @@ -9,24 +10,17 @@ import ( "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) // A Generic device has methods to collect hardware inventory, regardless of the vendor type Generic struct { - trace bool hw *model.Hardware - logger *logrus.Logger + logger *slog.Logger + trace bool } // New returns a generic device manager -func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, error) { - var trace bool - - if l.GetLevel().String() == "trace" { - trace = true - } - +func New(dmidecode *utils.Dmidecode, l *slog.Logger) (actions.DeviceManager, error) { deviceVendor, err := dmidecode.Manufacturer() if err != nil { return nil, errors.Wrap(errs.NewDmidecodeValueError("manufacturer", "", 0), err.Error()) @@ -52,7 +46,7 @@ func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, e return &Generic{ hw: model.NewHardware(&device), logger: l, - trace: trace, + trace: l.Enabled(nil, -5), }, nil } diff --git a/providers/supermicro/bios.go b/providers/supermicro/bios.go index cd4b9dee..076d6649 100644 --- a/providers/supermicro/bios.go +++ b/providers/supermicro/bios.go @@ -4,7 +4,6 @@ import ( "context" "github.com/metal-toolbox/ironlib/utils" - "github.com/sirupsen/logrus" ) // SetBIOSConfiguration sets bios configuration settings @@ -14,12 +13,6 @@ func (s *supermicro) SetBIOSConfiguration(context.Context, map[string]string) er // GetBIOSConfiguration returns bios configuration settings func (s *supermicro) GetBIOSConfiguration(ctx context.Context) (map[string]string, error) { - var trace bool - if s.logger.Level >= logrus.TraceLevel { - trace = true - } - - sum := utils.NewSupermicroSUM(trace) - + sum := utils.NewSupermicroSUM(s.trace) return sum.GetBIOSConfiguration(ctx, "") } diff --git a/providers/supermicro/supermicro.go b/providers/supermicro/supermicro.go index dcbafe75..ea2a5603 100644 --- a/providers/supermicro/supermicro.go +++ b/providers/supermicro/supermicro.go @@ -2,6 +2,7 @@ package supermicro import ( "context" + "log/slog" "github.com/bmc-toolbox/common" "github.com/metal-toolbox/ironlib/actions" @@ -10,17 +11,16 @@ import ( "github.com/metal-toolbox/ironlib/model" "github.com/metal-toolbox/ironlib/utils" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) type supermicro struct { trace bool hw *model.Hardware - logger *logrus.Logger + logger *slog.Logger dmidecode *utils.Dmidecode } -func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, error) { +func New(dmidecode *utils.Dmidecode, l *slog.Logger) (actions.DeviceManager, error) { deviceVendor, err := dmidecode.Manufacturer() if err != nil { return nil, errors.Wrap(errs.NewDmidecodeValueError("manufacturer", "", 0), err.Error()) @@ -47,7 +47,7 @@ func New(dmidecode *utils.Dmidecode, l *logrus.Logger) (actions.DeviceManager, e hw: model.NewHardware(&device), logger: l, dmidecode: dmidecode, - trace: l.GetLevel().String() == "trace", + trace: l.Enabled(nil, -5), }, nil } @@ -72,31 +72,26 @@ func (s *supermicro) GetInventory(ctx context.Context, options ...actions.Option // Collect device inventory s.logger.Info("Collecting hardware inventory") - var trace bool - if s.logger.GetLevel().String() == "trace" { - trace = true - } - // define collectors for supermicro hardware collectors := &actions.Collectors{ - BMCCollector: utils.NewIpmicfgCmd(trace), - BIOSCollector: utils.NewIpmicfgCmd(trace), - CPLDCollector: utils.NewIpmicfgCmd(trace), + BMCCollector: utils.NewIpmicfgCmd(s.trace), + BIOSCollector: utils.NewIpmicfgCmd(s.trace), + CPLDCollector: utils.NewIpmicfgCmd(s.trace), DriveCollectors: []actions.DriveCollector{ - utils.NewSmartctlCmd(trace), - utils.NewLsblkCmd(trace), + utils.NewSmartctlCmd(s.trace), + utils.NewLsblkCmd(s.trace), }, DriveCapabilitiesCollectors: []actions.DriveCapabilityCollector{ - utils.NewHdparmCmd(trace), - utils.NewNvmeCmd(trace), + utils.NewHdparmCmd(s.trace), + utils.NewNvmeCmd(s.trace), }, StorageControllerCollectors: []actions.StorageControllerCollector{ - utils.NewStoreCLICmd(trace), + utils.NewStoreCLICmd(s.trace), }, - NICCollector: utils.NewMlxupCmd(trace), + NICCollector: utils.NewMlxupCmd(s.trace), FirmwareChecksumCollector: firmware.NewChecksumCollector( firmware.MakeOutputPath(), - firmware.TraceExecution(trace), + firmware.TraceExecution(s.trace), ), UEFIVarsCollector: &utils.UEFIVariableCollector{}, } diff --git a/utils/fill_zero.go b/utils/fill_zero.go index 37a74448..81725522 100644 --- a/utils/fill_zero.go +++ b/utils/fill_zero.go @@ -2,8 +2,9 @@ package utils import ( "context" + "fmt" "io" - "log" + "log/slog" "os" "time" ) @@ -21,24 +22,29 @@ func NewFillZeroCmd(trace bool) *FillZero { return &z } -func (z *FillZero) WipeDisk(ctx context.Context, logicalName string) error { - log.Println("Starting zero-fill of", logicalName) +func (z *FillZero) WipeDisk(ctx context.Context, log *slog.Logger, logicalName string) error { + log = log.With("device", logicalName) + log.Info("starting zero-fill") + // Write open file, err := os.OpenFile(logicalName, os.O_WRONLY, 0) if err != nil { return err } defer file.Close() + // Get disk or partition size partitionSize, err := file.Seek(0, io.SeekEnd) if err != nil { return err } - log.Printf("%s | Size: %dB\n", logicalName, partitionSize) + + log.With("size", fmt.Sprintf("%dB", partitionSize)).Info("disk info detected") _, err = file.Seek(0, io.SeekStart) if err != nil { return err } + var bytesSinceLastPrint int64 var totalBytesWritten int64 buffer := make([]byte, 4096) @@ -47,7 +53,7 @@ func (z *FillZero) WipeDisk(ctx context.Context, logicalName string) error { // Check if the context has been canceled select { case <-ctx.Done(): - log.Println("Context canceled. Stopping WipeDisk") + log.Info("stopping") return ctx.Err() default: l := min(int64(len(buffer)), bytesRemaining) @@ -55,12 +61,13 @@ func (z *FillZero) WipeDisk(ctx context.Context, logicalName string) error { if writeError != nil { return writeError } + totalBytesWritten += int64(bytesWritten) bytesSinceLastPrint += int64(bytesWritten) bytesRemaining -= int64(bytesWritten) // Print progress report every 10 seconds and when done if bytesRemaining == 0 || time.Since(start) >= 10*time.Second { - printProgress(totalBytesWritten, partitionSize, &start, &bytesSinceLastPrint, logicalName) + printProgress(log, totalBytesWritten, partitionSize, start, bytesSinceLastPrint) start = time.Now() bytesSinceLastPrint = 0 } @@ -73,15 +80,19 @@ func (z *FillZero) WipeDisk(ctx context.Context, logicalName string) error { return nil } -func printProgress(totalBytesWritten, partitionSize int64, start *time.Time, bytesSinceLastPrint *int64, path string) { +func printProgress(log *slog.Logger, totalBytesWritten, partitionSize int64, start time.Time, bytesSinceLastPrint int64) { // Calculate progress and ETA progress := float64(totalBytesWritten) / float64(partitionSize) * 100 - elapsed := time.Since(*start).Seconds() - speed := float64(*bytesSinceLastPrint) / elapsed // Speed in bytes per second + elapsed := time.Since(start).Seconds() + speed := float64(bytesSinceLastPrint) / elapsed // Speed in bytes per second remainingSeconds := (float64(partitionSize) - float64(totalBytesWritten)) / speed // Remaining time in seconds remainingHours := float64(remainingSeconds / 3600) mbPerSecond := speed / (1024 * 1024) - log.Printf("%s | Progress: %.2f%% | Speed: %.2f MB/s | Estimated time left: %.2f hour(s)\n", path, progress, mbPerSecond, remainingHours) + log.With( + "progress", fmt.Sprintf("%.2f%%", progress), + "speed", fmt.Sprintf("%.2f MB/s", mbPerSecond), + "remaining", fmt.Sprintf("%.2f hour(s)", remainingHours), + ).Info("") } // We are in go 1.19 min not available yet diff --git a/utils/fill_zero_test.go b/utils/fill_zero_test.go index 79ecf301..502f7b77 100644 --- a/utils/fill_zero_test.go +++ b/utils/fill_zero_test.go @@ -5,6 +5,8 @@ import ( "os" "strconv" "testing" + + "github.com/neilotoole/slogt" ) func Test_NewFillZeroCmd(t *testing.T) { @@ -24,25 +26,31 @@ func Test_WipeDisk(t *testing.T) { t.Fatal(err) } defer os.Remove(tmpfile.Name()) // clean up + // Write some content to the temporary file expectedSize := int64(4096) if _, err = tmpfile.Write(make([]byte, expectedSize)); err != nil { t.Fatal(err) } + // Simulate a context ctx := context.Background() + // Create a FillZero instance zw := &FillZero{} + // Test Fill function - err = zw.WipeDisk(ctx, tmpfile.Name()) + err = zw.WipeDisk(ctx, slogt.New(t), tmpfile.Name()) if err != nil { t.Errorf("Fill returned an error: %v", err) } + // Check if the file size remains the same after overwrite fileInfo, err := os.Stat(tmpfile.Name()) if err != nil { t.Fatal(err) } + if size := fileInfo.Size(); size != expectedSize { t.Errorf("Expected file size to remain %d after overwrite, got %d", expectedSize, size) }