Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show ipmi last updated #211

Merged
merged 6 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
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
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