From 5ae4fb3ab96bd2f24418d2d2e2eb6a87187af3ec Mon Sep 17 00:00:00 2001 From: Matthew Stobbs Date: Sat, 16 Mar 2024 11:34:17 -0600 Subject: [PATCH] host now generates a piechart for memory usage --- lib/host/charts.go | 18 +++++--- lib/host/lib.go | 47 +++++++++----------- public/css/style.css | 5 +++ view/components/hostinfo.templ | 11 ++++- view/components/hostinfo_templ.go | 72 ++++++++++++++++++++++++++++++- 5 files changed, 119 insertions(+), 34 deletions(-) diff --git a/lib/host/charts.go b/lib/host/charts.go index 7f37068..5e8d255 100644 --- a/lib/host/charts.go +++ b/lib/host/charts.go @@ -1,6 +1,7 @@ package host import ( + "log" "strings" "github.com/wcharczuk/go-chart/v2" @@ -10,16 +11,21 @@ import ( // When a chart is rendered, it can return either an SVG or PNG. SVG is preferrable. func (h *Host) ChartMemory() string { + h.getNodeInfo() + log.Println("Generating Chart") c := chart.PieChart{ - Width: 256, - Height: 256, + Width: 128, + Height: 128, Values: []chart.Value{ - {Value: float64(h.NodeMemory.Free / h.NodeMemory.Total), Label: "Free"}, - {Value: float64(h.NodeMemory.Cached / h.NodeMemory.Total), Label: "Cached"}, - {Value: float64(h.NodeMemory.Buffers / h.NodeMemory.Total), Label: "Buffers"}, + {Value: float64(h.NodeMemory.Free) / float64(h.NodeMemory.Total), Label: "Free"}, + {Value: float64(h.NodeMemory.Cached) / float64(h.NodeMemory.Total), Label: "Cached"}, + {Value: float64(h.NodeMemory.Buffers) / float64(h.NodeMemory.Total), Label: "Buffers"}, }, } sb := new(strings.Builder) - c.Render(chart.SVG, sb) + log.Println("Rendering chart") + if err := c.Render(chart.SVG, sb); err != nil { + return err.Error() + } return sb.String() } diff --git a/lib/host/lib.go b/lib/host/lib.go index 72bba2d..364f885 100644 --- a/lib/host/lib.go +++ b/lib/host/lib.go @@ -113,13 +113,13 @@ type StoragePoolInfo struct { // VolumeInfo holds basic information about Volumes available in storage pools type VolumeInfo struct { - Name string - Key string - Path string - Type string - Capacity uint64 + Name string + Key string + Path string + Type string + Capacity uint64 Allocation uint64 - XML string + XML string } // NetIfInfo holds basic information about available network interfaces (not their connections, the devices themselves) @@ -228,9 +228,9 @@ func (h *Host) Close() error { // private methods that load the different informational parts func (h *Host) getInfo() { - var wg sync.WaitGroup + var wg = new(sync.WaitGroup) - infoFuncs := []func(*sync.WaitGroup){ + infoFuncs := []func(){ h.getDevicesInfo, h.getDomainInfo, h.getIfaceInfo, @@ -243,14 +243,16 @@ func (h *Host) getInfo() { for _, f := range infoFuncs { wg.Add(1) - f(&wg) + go func(wg *sync.WaitGroup) { + defer wg.Done() + f() + }(wg) } wg.Wait() } -func (h *Host) getStoragePools(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getStoragePools() { spools, err := h.conn.ListAllStoragePools(0) if err != nil { log.Println(err) @@ -295,7 +297,7 @@ func (h *Host) getStoragePools(wg *sync.WaitGroup) { if h.StoragePoolList[i].Volumes[j].Name, err = sv.GetName(); err != nil { log.Println(err) } - if h.StoragePoolList[i].Volumes[j].Key, err = sv.GetKey(); err != nil { + if h.StoragePoolList[i].Volumes[j].Key, err = sv.GetKey(); err != nil { log.Println(err) } if h.StoragePoolList[i].Volumes[j].Path, err = sv.GetPath(); err != nil { @@ -321,8 +323,7 @@ func (h *Host) getStoragePools(wg *sync.WaitGroup) { } } -func (h *Host) getSecretsInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getSecretsInfo() { nsecrets, err := h.conn.ListAllSecrets(0) if err != nil { log.Println(err) @@ -344,8 +345,7 @@ func (h *Host) getSecretsInfo(wg *sync.WaitGroup) { } } -func (h *Host) getNodeInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getNodeInfo() { var err error h.AvailableCPUTypes, err = h.conn.GetCPUModelNames("x86_64", 0) if err != nil { @@ -413,8 +413,7 @@ func (h *Host) getNodeInfo(wg *sync.WaitGroup) { } } -func (h *Host) getSEVInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getSEVInfo() { // getSEVInfo h.HostSEVInfo.SEVEnabled = true ns, err := h.conn.GetSEVInfo(0) @@ -442,8 +441,7 @@ func (h *Host) getSEVInfo(wg *sync.WaitGroup) { } } -func (h *Host) getDomainInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getDomainInfo() { // getDomainInfo doms, err := h.conn.ListAllDomains(0) if err != nil { @@ -471,8 +469,7 @@ func (h *Host) getDomainInfo(wg *sync.WaitGroup) { } } -func (h *Host) getIfaceInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getIfaceInfo() { // getIfaceInfo ifaces, err := h.conn.ListInterfaces() if err != nil { @@ -498,8 +495,7 @@ func (h *Host) getIfaceInfo(wg *sync.WaitGroup) { } } -func (h *Host) getNetsInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getNetsInfo() { // getNetsInfo nets, err := h.conn.ListNetworks() if err != nil { @@ -527,8 +523,7 @@ func (h *Host) getNetsInfo(wg *sync.WaitGroup) { } } -func (h *Host) getDevicesInfo(wg *sync.WaitGroup) { - defer wg.Done() +func (h *Host) getDevicesInfo() { ndevs, err := h.conn.ListAllNodeDevices(0) if err != nil { log.Println(err) diff --git a/public/css/style.css b/public/css/style.css index c13d444..10a004f 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -852,6 +852,11 @@ span>a:visited { display: contents; } +.size-64 { + width: 16rem; + height: 16rem; +} + .h-28 { height: 7rem; } diff --git a/view/components/hostinfo.templ b/view/components/hostinfo.templ index 230e603..05a3b80 100644 --- a/view/components/hostinfo.templ +++ b/view/components/hostinfo.templ @@ -1,12 +1,21 @@ package components import ( + "fmt" "git.staur.ca/stobbsm/clustvirt/lib/host" ) // HostInfo is meant to be an HTMX response templ HostInfo(h *host.Host) { - @templ.Raw(h.ChartMemory()) +
+ @templ.Raw(h.ChartMemory()) +
+ } diff --git a/view/components/hostinfo_templ.go b/view/components/hostinfo_templ.go index 405d91c..7470e90 100644 --- a/view/components/hostinfo_templ.go +++ b/view/components/hostinfo_templ.go @@ -11,6 +11,7 @@ import "io" import "bytes" import ( + "fmt" "git.staur.ca/stobbsm/clustvirt/lib/host" ) @@ -32,11 +33,80 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + var templ_7745c5c3_Var2 = []any{"size-64"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } templ_7745c5c3_Err = templ.Raw(h.ChartMemory()).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }