Skip to content

Commit

Permalink
show ipmi last updated (#211)
Browse files Browse the repository at this point in the history
  • Loading branch information
majst01 authored Sep 14, 2023
1 parent 1120847 commit 8c27c9a
Show file tree
Hide file tree
Showing 6 changed files with 487 additions and 260 deletions.
88 changes: 85 additions & 3 deletions cmd/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ ID LAST EVENT WHEN AGE HOSTNAME PROJECT SIZE IMAGE
1 Phoned Home 7d 14d machine-hostname-1 project-1 1 debian-name 1 rack-1
`),
wantWideTable: pointer.Pointer(`
ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION RACK STARTED TAGS LOCK/RESERVE
2 Waiting 1m 1 1 rack-1 b
ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION RACK STARTED TAGS LOCK/RESERVE
2 Waiting 1m 1 1 rack-1 b
1 Phoned Home 7d 14d machine allocation 1 machine-1 machine-hostname-1 project-1 1.1.1.1 1 debian-name 1 rack-1 2022-05-05T01:02:03Z a
`),
template: pointer.Pointer("{{ .id }} {{ .name }}"),
Expand Down Expand Up @@ -280,7 +280,7 @@ ID LAST EVENT WHEN AGE HOSTNAME PROJECT SIZE IMAGE
1 Phoned Home 7d 14d machine-hostname-1 project-1 1 debian-name 1 rack-1
`),
wantWideTable: pointer.Pointer(`
ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION RACK STARTED TAGS LOCK/RESERVE
ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION RACK STARTED TAGS LOCK/RESERVE
1 Phoned Home 7d 14d machine allocation 1 machine-1 machine-hostname-1 project-1 1.1.1.1 1 debian-name 1 rack-1 2022-05-05T01:02:03Z a
`),
template: pointer.Pointer("{{ .id }} {{ .name }}"),
Expand Down Expand Up @@ -377,3 +377,85 @@ ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME
tt.testCmd(t)
}
}

func Test_MachineIPMICmd_MultiResult(t *testing.T) {
ipmiMachine1 := &models.V1MachineIPMIResponse{
Allocation: machine1.Allocation,
Bios: &models.V1MachineBIOS{
Version: pointer.Pointer("2.0"),
},
Changed: machine1.Changed,
Created: machine1.Created,
Description: machine1.Description,
Events: machine1.Events,
Hardware: machine1.Hardware,
ID: machine1.ID,
Ipmi: &models.V1MachineIPMI{
Address: pointer.Pointer("1.2.3.4"),
Bmcversion: pointer.Pointer("1.1"),
Fru: &models.V1MachineFru{
BoardPartNumber: "part123",
ChassisPartSerial: "chassis123",
ProductSerial: "product123",
},
LastUpdated: pointer.Pointer(strfmt.DateTime(testTime.Add(-5 * time.Second))),
Mac: pointer.Pointer("1.2.3.4"),
Powermetric: &models.V1PowerMetric{
Averageconsumedwatts: pointer.Pointer(float32(16.0)),
},
Powerstate: pointer.Pointer("ON"),
},
Ledstate: &models.V1ChassisIdentifyLEDState{},
Liveliness: machine1.Liveliness,
Name: machine1.Name,
Partition: machine1.Partition,
Rackid: machine1.Rackid,
Size: machine1.Size,
State: machine1.State,
Tags: machine1.Tags,
}

tests := []*test[[]*models.V1MachineIPMIResponse]{
{
name: "machine ipmi",
cmd: func(want []*models.V1MachineIPMIResponse) []string {
return []string{"machine", "ipmi"}
},
mocks: &client.MetalMockFns{
Machine: func(mock *mock.Mock) {
mock.On("FindIPMIMachines", testcommon.MatchIgnoreContext(t, machine.NewFindIPMIMachinesParams().WithBody(&models.V1MachineFindRequest{
NicsMacAddresses: []string{},
Tags: []string{},
})), nil).Return(&machine.FindIPMIMachinesOK{
Payload: []*models.V1MachineIPMIResponse{
ipmiMachine1,
},
}, nil)
},
},
want: []*models.V1MachineIPMIResponse{
ipmiMachine1,
},
wantTable: pointer.Pointer(`
ID POWER IP MAC BOARD PART NUMBER BIOS BMC SIZE PARTITION RACK UPDATED
1 ●  (16.0W) 1.2.3.4 1.2.3.4 part123 2.0 1.1 1 1 rack-1 5s ago
`),
wantWideTable: pointer.Pointer(`
ID STATUS POWER IP MAC BOARD PART NUMBER CHASSIS SERIAL PRODUCT SERIAL BIOS VERSION BMC VERSION SIZE PARTITION RACK UPDATED
1 ON 16.00W 1.2.3.4 1.2.3.4 part123 chassis123 product123 2.0 1.1 1 1 rack-1 5s ago
`),
template: pointer.Pointer("{{ .id }} {{ .name }}"),
wantTemplate: pointer.Pointer(`
1 machine-1
`),
wantMarkdown: pointer.Pointer(`
| ID | | POWER | IP | MAC | BOARD PART NUMBER | BIOS | BMC | SIZE | PARTITION | RACK | UPDATED |
|----|--|------------|---------|---------|-------------------|------|-----|------|-----------|--------|---------|
| 1 | | ●  (16.0W) | 1.2.3.4 | 1.2.3.4 | part123 | 2.0 | 1.1 | 1 | 1 | rack-1 | 5s ago |
`),
},
}
for _, tt := range tests {
tt.testCmd(t)
}
}
19 changes: 13 additions & 6 deletions cmd/tableprinters/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"strings"
"time"

"github.com/dustin/go-humanize"
"github.com/fatih/color"
"github.com/metal-stack/metal-go/api/models"
"github.com/metal-stack/metal-lib/pkg/genericcli"
Expand Down Expand Up @@ -149,9 +148,9 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi
rows [][]string
)

header := []string{"ID", "", "Power", "IP", "Mac", "Board Part Number", "Bios Version", "BMC Version", "Size", "Partition", "Rack"}
header := []string{"ID", "", "Power", "IP", "Mac", "Board Part Number", "Bios", "BMC", "Size", "Partition", "Rack", "Updated"}
if wide {
header = []string{"ID", "Status", "Power", "IP", "Mac", "Board Part Number", "Chassis Serial", "Product Serial", "Bios Version", "BMC Version", "Size", "Partition", "Rack"}
header = []string{"ID", "Status", "Power", "IP", "Mac", "Board Part Number", "Chassis Serial", "Product Serial", "Bios Version", "BMC Version", "Size", "Partition", "Rack", "Updated"}
}

for _, machine := range data {
Expand All @@ -169,6 +168,7 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi
powerText := ""
ipmi := machine.Ipmi
rack := machine.Rackid
lastUpdated := "never"

if ipmi != nil {
ipAddress = pointer.SafeDeref(ipmi.Address)
Expand All @@ -183,6 +183,10 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi
}

power, powerText = extractPowerState(ipmi)

if ipmi.LastUpdated != nil && !ipmi.LastUpdated.IsZero() {
lastUpdated = fmt.Sprintf("%s ago", humanizeDuration(time.Since(time.Time(*ipmi.LastUpdated))))
}
}

biosVersion := ""
Expand All @@ -194,9 +198,9 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi
emojis, wideEmojis := t.getMachineStatusEmojis(machine.Liveliness, machine.Events, machine.State, nil)

if wide {
rows = append(rows, []string{id, wideEmojis, powerText, ipAddress, mac, bpn, cs, ps, biosVersion, bmcVersion, size, partition, rack})
rows = append(rows, []string{id, wideEmojis, powerText, ipAddress, mac, bpn, cs, ps, biosVersion, bmcVersion, size, partition, rack, lastUpdated})
} else {
rows = append(rows, []string{id, emojis, power, ipAddress, mac, bpn, biosVersion, bmcVersion, size, partition, rack})
rows = append(rows, []string{id, emojis, power, ipAddress, mac, bpn, biosVersion, bmcVersion, size, partition, rack, lastUpdated})
}
}

Expand All @@ -217,9 +221,12 @@ func extractPowerState(ipmi *models.V1MachineIPMI) (short, wide string) {
default:
short = color.WhiteString(dot)
}

wide = state

if ipmi.Powermetric != nil {
wide = wide + " " + humanize.SI(float64(*ipmi.Powermetric.Averageconsumedwatts), "W")
short = fmt.Sprintf("%s"+nbr+nbr+"(%.1fW)", short, pointer.SafeDeref(ipmi.Powermetric.Averageconsumedwatts))
wide = fmt.Sprintf("%s %.2fW", wide, pointer.SafeDeref(ipmi.Powermetric.Averageconsumedwatts))
}

return short, wide
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/go-openapi/runtime v0.26.0
github.com/go-openapi/strfmt v0.21.7
github.com/google/go-cmp v0.5.9
github.com/metal-stack/metal-go v0.24.0
github.com/metal-stack/metal-go v0.24.1
github.com/metal-stack/metal-lib v0.13.3
github.com/metal-stack/updater v1.1.5
github.com/metal-stack/v v1.0.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@ github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/metal-stack/metal-go v0.24.0 h1:Y+nGpA5iUhIX6UOCY4yVuJ8S+dsge02rEdpVkIyif9s=
github.com/metal-stack/metal-go v0.24.0/go.mod h1:jNJ0dWIBRwKeJoP+RGqTyE5qLsdZFISFrNHU5m3IDwA=
github.com/metal-stack/metal-go v0.24.1 h1:S4g3LXeWBELCKIyyCsRMa9B1pC5EClqcX35oV/8xv2U=
github.com/metal-stack/metal-go v0.24.1/go.mod h1:jNJ0dWIBRwKeJoP+RGqTyE5qLsdZFISFrNHU5m3IDwA=
github.com/metal-stack/metal-lib v0.13.3 h1:BOhwcKHILmBZd2pz2YMOhj8QxzDaz3G0F/CGuYhnu8o=
github.com/metal-stack/metal-lib v0.13.3/go.mod h1:BAR7fjdoV7DDg8i9GpJQBDaNSFirOcBs0vLYTBnhHQU=
github.com/metal-stack/security v0.6.7 h1:8wstGy0pdUmphVclAlT+9RKQmx9lF+cIGklJZAB5cIc=
Expand Down
46 changes: 44 additions & 2 deletions pkg/api/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
IssueTypeLastEventError IssueType = "last-event-error"
IssueTypeBMCWithoutMAC IssueType = "bmc-without-mac"
IssueTypeBMCWithoutIP IssueType = "bmc-without-ip"
IssueTypeBMCInfoOutdated IssueType = "bmc-info-outdated"
IssueTypeASNUniqueness IssueType = "asn-not-unique"
IssueTypeNonDistinctBMCIP IssueType = "bmc-no-distinct-ip"
)
Expand Down Expand Up @@ -65,8 +66,11 @@ type (
IssueLastEventError struct {
details string
}
IssueBMCWithoutMAC struct{}
IssueBMCWithoutIP struct{}
IssueBMCWithoutMAC struct{}
IssueBMCWithoutIP struct{}
IssueBMCInfoOutdated struct {
details string
}
IssueASNUniqueness struct {
details string
}
Expand Down Expand Up @@ -117,6 +121,7 @@ func AllIssueTypes() []IssueType {
IssueTypeLastEventError,
IssueTypeBMCWithoutMAC,
IssueTypeBMCWithoutIP,
IssueTypeBMCInfoOutdated,
IssueTypeASNUniqueness,
IssueTypeNonDistinctBMCIP,
}
Expand Down Expand Up @@ -271,6 +276,8 @@ func newIssueFromType(t IssueType) (issue, error) {
return &IssueBMCWithoutMAC{}, nil
case IssueTypeBMCWithoutIP:
return &IssueBMCWithoutIP{}, nil
case IssueTypeBMCInfoOutdated:
return &IssueBMCInfoOutdated{}, nil
case IssueTypeASNUniqueness:
return &IssueASNUniqueness{}, nil
case IssueTypeNonDistinctBMCIP:
Expand Down Expand Up @@ -454,6 +461,7 @@ func (i *IssueLastEventError) Evaluate(m *models.V1MachineIPMIResponse, c *Issue
return true
}
}

return false
}

Expand Down Expand Up @@ -495,6 +503,40 @@ func (i *IssueBMCWithoutIP) Details() string {
return ""
}

func (i *IssueBMCInfoOutdated) Details() string {
return i.details
}

func (i *IssueBMCInfoOutdated) Evaluate(m *models.V1MachineIPMIResponse, c *IssueConfig) bool {
if m.Ipmi == nil {
i.details = "machine ipmi has never been set"
return true
}

if m.Ipmi.LastUpdated == nil || m.Ipmi.LastUpdated.IsZero() {
// "last_updated has not been set yet"
return false
}

lastUpdated := time.Since(time.Time(*m.Ipmi.LastUpdated))

if lastUpdated > 20*time.Minute {
i.details = fmt.Sprintf("last updated %s ago", lastUpdated.String())
return true
}

return false
}

func (*IssueBMCInfoOutdated) Spec() *issueSpec {
return &issueSpec{
Type: IssueTypeBMCInfoOutdated,
Severity: IssueSeverityMajor,
Description: "BMC has not been updated from either metal-hammer or metal-bmc",
RefURL: "https://docs.metal-stack.io/stable/installation/troubleshoot/#bmc-info-outdated",
}
}

func (i *IssueASNUniqueness) Spec() *issueSpec {
return &issueSpec{
Type: IssueTypeASNUniqueness,
Expand Down
Loading

0 comments on commit 8c27c9a

Please sign in to comment.