implemented a router structure
- keep things localized a bit more - fixes import cycle
This commit is contained in:
parent
ffca8c3970
commit
851ae7a77f
@ -9,6 +9,7 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
||||||
@ -24,3 +25,10 @@ type Cluster struct {
|
|||||||
hosts map[string]*host.Host
|
hosts map[string]*host.Host
|
||||||
defaultURI *host.URI
|
defaultURI *host.URI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) GetHost(h string) (*host.Host, error) {
|
||||||
|
if hh, ok := c.hosts[h]; ok {
|
||||||
|
return hh, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("%s: %w", h, ErrHostNotFound)
|
||||||
|
}
|
||||||
|
8
cluster/errors.go
Normal file
8
cluster/errors.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// Errors that can happen in the cluster
|
||||||
|
var (
|
||||||
|
ErrHostNotFound = errors.New("host not found")
|
||||||
|
)
|
@ -82,7 +82,6 @@ type VMStats struct {
|
|||||||
// HostStats provides informatoin about the number of hosts defined, and how many
|
// HostStats provides informatoin about the number of hosts defined, and how many
|
||||||
// are currently available. An unavailable host will not have it's statistics counted
|
// are currently available. An unavailable host will not have it's statistics counted
|
||||||
type HostStats struct {
|
type HostStats struct {
|
||||||
Count uint32
|
|
||||||
Available uint32
|
Available uint32
|
||||||
Nodes uint32
|
Nodes uint32
|
||||||
}
|
}
|
||||||
@ -132,6 +131,7 @@ type CPUDiff struct {
|
|||||||
Cores int
|
Cores int
|
||||||
Threads int
|
Threads int
|
||||||
Allocated int
|
Allocated int
|
||||||
|
MHz int
|
||||||
}
|
}
|
||||||
type MemoryDiff struct {
|
type MemoryDiff struct {
|
||||||
Total int64
|
Total int64
|
||||||
@ -186,12 +186,13 @@ func (cs *ClusterStats) Update() {
|
|||||||
cs.reset()
|
cs.reset()
|
||||||
// Start looping through each host in the cluster, adding to the total
|
// Start looping through each host in the cluster, adding to the total
|
||||||
for _, h := range cs.c.hosts {
|
for _, h := range cs.c.hosts {
|
||||||
cs.Host.Count++
|
cs.Host.Nodes++
|
||||||
cs.Host.Available++
|
cs.Host.Available++
|
||||||
|
|
||||||
cs.CPU.Sockets += uint32(h.HostInfo.CPU.Topology.Sockets)
|
cs.CPU.Sockets += uint32(h.HostInfo.CPU.Topology.Sockets)
|
||||||
cs.CPU.Cores += uint32(h.HostInfo.CPU.Topology.Cores)
|
cs.CPU.Cores += uint32(h.HostInfo.CPU.Topology.Cores)
|
||||||
cs.CPU.Threads += uint32(h.HostInfo.CPU.Topology.Threads)
|
cs.CPU.Threads += uint32(h.HostInfo.CPU.Topology.Threads)
|
||||||
|
cs.CPU.MHz += uint64(h.HostInfo.CPU.Counter.Frequency)
|
||||||
|
|
||||||
cs.Memory.Total += h.NodeMemory.Total
|
cs.Memory.Total += h.NodeMemory.Total
|
||||||
cs.Memory.Free += h.NodeMemory.Free
|
cs.Memory.Free += h.NodeMemory.Free
|
||||||
@ -215,7 +216,7 @@ func (cs *ClusterStats) Update() {
|
|||||||
cs.Storage.Used += sp.Allocation.Value
|
cs.Storage.Used += sp.Allocation.Value
|
||||||
cs.Storage.Free += sp.Capacity.Value - sp.Allocation.Value
|
cs.Storage.Free += sp.Capacity.Value - sp.Allocation.Value
|
||||||
}
|
}
|
||||||
|
cs.Volume.Total += uint32(len(h.VolumeList))
|
||||||
// VM Count
|
// VM Count
|
||||||
cs.VM.Count += uint32(len(h.VMList))
|
cs.VM.Count += uint32(len(h.VMList))
|
||||||
for _, vm := range h.VMList {
|
for _, vm := range h.VMList {
|
||||||
@ -237,6 +238,7 @@ func (cs *ClusterStats) Diff() StatDiff {
|
|||||||
Cores: int(cs.CPU.Cores) - int(cs.old.CPU.Cores),
|
Cores: int(cs.CPU.Cores) - int(cs.old.CPU.Cores),
|
||||||
Threads: int(cs.CPU.Threads) - int(cs.old.CPU.Threads),
|
Threads: int(cs.CPU.Threads) - int(cs.old.CPU.Threads),
|
||||||
Allocated: int(cs.CPU.Allocated) - int(cs.old.CPU.Allocated),
|
Allocated: int(cs.CPU.Allocated) - int(cs.old.CPU.Allocated),
|
||||||
|
MHz: int(cs.CPU.MHz) - int(cs.old.CPU.MHz),
|
||||||
},
|
},
|
||||||
Memory: MemoryDiff{
|
Memory: MemoryDiff{
|
||||||
Total: int64(cs.old.Memory.Total) - int64(cs.Memory.Total),
|
Total: int64(cs.old.Memory.Total) - int64(cs.Memory.Total),
|
||||||
@ -265,7 +267,7 @@ func (cs *ClusterStats) Diff() StatDiff {
|
|||||||
Stopped: int(cs.old.VM.Stopped) - int(cs.VM.Stopped),
|
Stopped: int(cs.old.VM.Stopped) - int(cs.VM.Stopped),
|
||||||
},
|
},
|
||||||
Host: HostDiff{
|
Host: HostDiff{
|
||||||
Count: int(cs.old.Host.Count) - int(cs.Host.Count),
|
Count: int(cs.old.Host.Nodes) - int(cs.Host.Nodes),
|
||||||
Available: int(cs.old.Host.Available) - int(cs.Host.Available),
|
Available: int(cs.old.Host.Available) - int(cs.Host.Available),
|
||||||
},
|
},
|
||||||
Network: NetworkDiff{
|
Network: NetworkDiff{
|
||||||
@ -288,11 +290,13 @@ func (cs *ClusterStats) reset() {
|
|||||||
cs.CPU.Cores = 0
|
cs.CPU.Cores = 0
|
||||||
cs.CPU.Threads = 0
|
cs.CPU.Threads = 0
|
||||||
cs.CPU.Allocated = 0
|
cs.CPU.Allocated = 0
|
||||||
|
cs.CPU.MHz = 0
|
||||||
|
|
||||||
cs.Memory.Total = 0
|
cs.Memory.Total = 0
|
||||||
cs.Memory.Free = 0
|
cs.Memory.Free = 0
|
||||||
cs.Memory.Buffers = 0
|
cs.Memory.Buffers = 0
|
||||||
cs.Memory.Cached = 0
|
cs.Memory.Cached = 0
|
||||||
|
cs.Memory.Allocated = 0
|
||||||
|
|
||||||
cs.Storage.Total = 0
|
cs.Storage.Total = 0
|
||||||
cs.Storage.Used = 0
|
cs.Storage.Used = 0
|
||||||
@ -301,16 +305,25 @@ func (cs *ClusterStats) reset() {
|
|||||||
cs.Storage.Inactive = 0
|
cs.Storage.Inactive = 0
|
||||||
cs.Storage.Pools = 0
|
cs.Storage.Pools = 0
|
||||||
|
|
||||||
|
cs.Volume.Total = 0
|
||||||
|
cs.Volume.Active = 0
|
||||||
|
cs.Volume.Inactive = 0
|
||||||
|
|
||||||
cs.VM.Count = 0
|
cs.VM.Count = 0
|
||||||
cs.VM.Started = 0
|
cs.VM.Started = 0
|
||||||
cs.VM.Stopped = 0
|
cs.VM.Stopped = 0
|
||||||
|
|
||||||
cs.Host.Count = 0
|
|
||||||
cs.Host.Available = 0
|
cs.Host.Available = 0
|
||||||
|
cs.Host.Nodes = 0
|
||||||
|
|
||||||
cs.Network.Count = 0
|
cs.Network.Count = 0
|
||||||
cs.Network.Active = 0
|
cs.Network.Active = 0
|
||||||
cs.Network.Inactive = 0
|
cs.Network.Inactive = 0
|
||||||
|
|
||||||
|
cs.NetIF.Count = 0
|
||||||
|
cs.NetIF.Common = 0
|
||||||
|
cs.NetIF.Active = 0
|
||||||
|
cs.NetIF.Inactive = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNetworkPool(pooltype string) bool {
|
func isNetworkPool(pooltype string) bool {
|
||||||
|
11
go.mod
11
go.mod
@ -12,8 +12,19 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/go-chi/cors v1.2.1 // indirect
|
||||||
|
github.com/go-chi/docgen v1.2.0 // indirect
|
||||||
|
github.com/go-chi/jwtauth v1.2.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.3.5 // indirect
|
||||||
|
github.com/lestrrat-go/backoff/v2 v2.0.7 // indirect
|
||||||
|
github.com/lestrrat-go/httpcc v1.0.0 // indirect
|
||||||
|
github.com/lestrrat-go/iter v1.0.0 // indirect
|
||||||
|
github.com/lestrrat-go/jwx v1.1.0 // indirect
|
||||||
|
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.0.0 // indirect
|
github.com/mitchellh/go-homedir v1.0.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||||
golang.org/x/sys v0.15.0 // indirect
|
golang.org/x/sys v0.15.0 // indirect
|
||||||
)
|
)
|
||||||
|
65
go.sum
65
go.sum
@ -1,13 +1,38 @@
|
|||||||
github.com/a-h/templ v0.2.598 h1:6jMIHv6wQZvdPxTuv87erW4RqN/FPU0wk7ZHN5wVuuo=
|
github.com/a-h/templ v0.2.598 h1:6jMIHv6wQZvdPxTuv87erW4RqN/FPU0wk7ZHN5wVuuo=
|
||||||
github.com/a-h/templ v0.2.598/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
|
github.com/a-h/templ v0.2.598/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
|
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||||
|
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||||
|
github.com/go-chi/docgen v1.2.0 h1:da0Nq2PKU9W9pSOTUfVrKI1vIgTGpauo9cfh4Iwivek=
|
||||||
|
github.com/go-chi/docgen v1.2.0/go.mod h1:G9W0G551cs2BFMSn/cnGwX+JBHEloAgo17MBhyrnhPI=
|
||||||
|
github.com/go-chi/jwtauth v1.2.0 h1:Z116SPpevIABBYsv8ih/AHYBHmd4EufKSKsLUnWdrTM=
|
||||||
|
github.com/go-chi/jwtauth v1.2.0/go.mod h1:NTUpKoTQV6o25UwYE6w/VaLUu83hzrVKYTVo+lE6qDA=
|
||||||
|
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||||
|
github.com/goccy/go-json v0.3.5 h1:HqrLjEWx7hD62JRhBh+mHv+rEEzBANIu6O0kbDlaLzU=
|
||||||
|
github.com/goccy/go-json v0.3.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
|
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
|
||||||
github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
|
github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
|
||||||
|
github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE=
|
||||||
|
github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||||
|
github.com/lestrrat-go/codegen v1.0.0/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=
|
||||||
|
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
|
||||||
|
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||||
|
github.com/lestrrat-go/iter v1.0.0 h1:QD+hHQPDSHC4rCJkZYY/yXChYr/vjfBopKekTc+7l4Q=
|
||||||
|
github.com/lestrrat-go/iter v1.0.0/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||||
|
github.com/lestrrat-go/jwx v1.1.0 h1:gerfaQK3mEIL8X8oJ5MFvsB/JuxXoGryLtTlNmPi3/k=
|
||||||
|
github.com/lestrrat-go/jwx v1.1.0/go.mod h1:vn9FzD6gJtKkgYs7RTKV7CjWtEka8F/voUollhnn4QE=
|
||||||
|
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||||
|
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||||
|
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||||
|
github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
@ -16,15 +41,55 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
|
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
|
||||||
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
|
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
libvirt.org/go/libvirt v1.10001.0 h1:lEVDNE7xfzmZXiDEGIS8NvJSuaz11OjRXw+ufbQEtPY=
|
libvirt.org/go/libvirt v1.10001.0 h1:lEVDNE7xfzmZXiDEGIS8NvJSuaz11OjRXw+ufbQEtPY=
|
||||||
libvirt.org/go/libvirt v1.10001.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
|
libvirt.org/go/libvirt v1.10001.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
|
||||||
libvirt.org/go/libvirtxml v1.10001.0 h1:r9WBs24r3mxIG3/hAMRRwDMy4ZaPHmhHjw72o/ceXic=
|
libvirt.org/go/libvirtxml v1.10001.0 h1:r9WBs24r3mxIG3/hAMRRwDMy4ZaPHmhHjw72o/ceXic=
|
||||||
|
69
main.go
69
main.go
@ -1,24 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
"git.staur.ca/stobbsm/clustvirt/router/server"
|
||||||
"git.staur.ca/stobbsm/clustvirt/view"
|
|
||||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
|
||||||
"git.staur.ca/stobbsm/clustvirt/view/static"
|
|
||||||
"github.com/a-h/templ"
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
|
||||||
localmw "git.staur.ca/stobbsm/clustvirt/router/middleware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const DEBUG bool = true
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("Starting clustvirt, the libvirt cluster manager")
|
log.Println("Starting clustvirt, the libvirt cluster manager")
|
||||||
clst := cluster.New().
|
clst := cluster.New().
|
||||||
@ -26,59 +14,8 @@ func main() {
|
|||||||
AddHost("venus.staur.ca").
|
AddHost("venus.staur.ca").
|
||||||
AddHost("mars.staur.ca").
|
AddHost("mars.staur.ca").
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
initStats := cluster.InitStats(clst)
|
|
||||||
// Start webserver and serve homepage
|
// Start webserver and serve homepage
|
||||||
|
|
||||||
defaultNavBar := []components.NavItem{
|
r := server.New("127.0.0.1", 3000, clst)
|
||||||
{Name: "Cluster", Href: "/"},
|
r.Start()
|
||||||
{Name: "Configuration", Href: "/config"},
|
|
||||||
{Name: "About", Href: "/about"},
|
|
||||||
}
|
|
||||||
fs := http.StripPrefix("/static/", http.FileServer(http.Dir("public")))
|
|
||||||
|
|
||||||
r := chi.NewRouter()
|
|
||||||
r.Use(localmw.Logger)
|
|
||||||
if DEBUG {
|
|
||||||
r.Use(middleware.NoCache)
|
|
||||||
}
|
|
||||||
r.Get("/static/*", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
defer r.Body.Close()
|
|
||||||
fs.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
r.Get("/", templ.Handler(view.HostMain(defaultNavBar)).ServeHTTP)
|
|
||||||
r.Get("/cluster", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
initStats.Update()
|
|
||||||
log.Println(
|
|
||||||
"Rendering clusterstats",
|
|
||||||
view.ClusterInfo(
|
|
||||||
initStats,
|
|
||||||
initStats.Diff(),
|
|
||||||
defaultNavBar,
|
|
||||||
).Render(context.Background(), w))
|
|
||||||
})
|
|
||||||
r.Get("/about", templ.Handler(static.Home()).ServeHTTP)
|
|
||||||
|
|
||||||
r.Route("/htmx", func(r chi.Router) {
|
|
||||||
r.Get("/host/{hostname}", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
rhost, err := host.ConnectHost(host.URI_QEMU_SSH_SYSTEM, chi.URLParam(r, "hostname"))
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("error while getting host: %s", err), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer rhost.Close()
|
|
||||||
log.Println("Rendering HostInfo", view.HostInfo(rhost).Render(context.Background(), w))
|
|
||||||
})
|
|
||||||
r.Get("/host/{hostname}/stats", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
rhost, err := host.ConnectHost(host.URI_QEMU_SSH_SYSTEM, chi.URLParam(r, "hostname"))
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("error while getting host: %s", err), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer rhost.Close()
|
|
||||||
log.Println("Rendering stats", view.SysInfo(rhost).Render(context.Background(), w))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
log.Println(http.ListenAndServe(":3000", r))
|
|
||||||
}
|
}
|
||||||
|
6
router/errors.go
Normal file
6
router/errors.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// Errors uses by the router module and it's sub modules
|
||||||
|
var ErrMethodNotExist = errors.New("http method doesn't exist")
|
@ -1,4 +1,54 @@
|
|||||||
// Package htmx contains the routes for the WebUI HTMX
|
// Package htmx contains the routes for the WebUI HTMX
|
||||||
package htmx
|
package htmx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/router"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type htmx struct {
|
||||||
|
router chi.Router
|
||||||
|
routes []router.Route
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *htmx) MountTo(c *cluster.Cluster, rr chi.Router) error {
|
||||||
|
var errs []error
|
||||||
|
for _, r := range h.routes {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodTrace:
|
||||||
|
h.router.Trace(r.Path, r.Handler(c))
|
||||||
|
case http.MethodOptions:
|
||||||
|
h.router.Options(r.Path, r.Handler(c))
|
||||||
|
case http.MethodConnect:
|
||||||
|
h.router.Connect(r.Path, r.Handler(c))
|
||||||
|
case http.MethodHead:
|
||||||
|
h.router.Head(r.Path, r.Handler(c))
|
||||||
|
case http.MethodGet:
|
||||||
|
h.router.Get(r.Path, r.Handler(c))
|
||||||
|
case http.MethodPost:
|
||||||
|
h.router.Post(r.Path, r.Handler(c))
|
||||||
|
case http.MethodPut:
|
||||||
|
h.router.Put(r.Path, r.Handler(c))
|
||||||
|
case http.MethodPatch:
|
||||||
|
h.router.Patch(r.Path, r.Handler(c))
|
||||||
|
case http.MethodDelete:
|
||||||
|
h.router.Delete(r.Path, r.Handler(c))
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("method: %s: %w", r.Method, router.ErrMethodNotExist)
|
||||||
|
errs = append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Info("htmx.MoutnTo").
|
||||||
|
Str("Route.Path", r.Path).
|
||||||
|
Str("Route.Method", r.Method).
|
||||||
|
Msg("route registered")
|
||||||
|
}
|
||||||
|
rr.Mount("/htmx", h.router)
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
68
router/htmx/routes.go
Normal file
68
router/htmx/routes.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package htmx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/router"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/view"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Htmx = &htmx{
|
||||||
|
router: chi.NewRouter(),
|
||||||
|
routes: []router.Route{
|
||||||
|
router.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/host/{hostname}",
|
||||||
|
Handler: func(c *cluster.Cluster) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
host, err := c.GetHost(chi.URLParam(r, "hostname"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
log.Error("htmx.Handler").
|
||||||
|
Str("uri", r.RequestURI).
|
||||||
|
Err(err).
|
||||||
|
Int("statusCode", http.StatusBadRequest).
|
||||||
|
Send()
|
||||||
|
}
|
||||||
|
if err = view.HostInfo(host).Render(context.Background(), w); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
log.Error("htmx.Handler").
|
||||||
|
Str("uri", r.RequestURI).
|
||||||
|
Err(err).
|
||||||
|
Int("statusCode", http.StatusInternalServerError).
|
||||||
|
Send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
router.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/host/{hostname}/stats",
|
||||||
|
Handler: func(c *cluster.Cluster) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
host, err := c.GetHost(chi.URLParam(r, "hostname"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
log.Error("htmx.Handler").
|
||||||
|
Str("uri", r.RequestURI).
|
||||||
|
Err(err).
|
||||||
|
Int("statusCode", http.StatusBadRequest).
|
||||||
|
Send()
|
||||||
|
}
|
||||||
|
if err = view.HostStats(host).Render(context.Background(), w); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
log.Error("htmx.Handler").
|
||||||
|
Str("uri", r.RequestURI).
|
||||||
|
Err(err).
|
||||||
|
Int("statusCode", http.StatusInternalServerError).
|
||||||
|
Send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
22
router/middleware/fromchi.go
Normal file
22
router/middleware/fromchi.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import "github.com/go-chi/chi/v5/middleware"
|
||||||
|
|
||||||
|
// These middlewares are cloned from chi/middleware
|
||||||
|
var (
|
||||||
|
AllowContentEncoding = middleware.AllowContentEncoding
|
||||||
|
AllowContentType = middleware.AllowContentType
|
||||||
|
BasicAuth = middleware.BasicAuth
|
||||||
|
Compress = middleware.Compress
|
||||||
|
Heartbeat = middleware.Heartbeat
|
||||||
|
NoCache = middleware.NoCache
|
||||||
|
Profiler = middleware.Profiler
|
||||||
|
RealIP = middleware.RealIP
|
||||||
|
Recoverer = middleware.Recoverer
|
||||||
|
RequestID = middleware.RequestID
|
||||||
|
SetHeader = middleware.SetHeader
|
||||||
|
Sunset = middleware.Sunset
|
||||||
|
Throttle = middleware.Throttle
|
||||||
|
Timeout = middleware.Timeout
|
||||||
|
URLFormat = middleware.URLFormat
|
||||||
|
)
|
@ -1,57 +1,28 @@
|
|||||||
// Package router defines the base routes http server
|
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
// Types that are shared among routers
|
||||||
bindAddr string
|
|
||||||
ssl bool
|
// SubRouter defines an interface to be able to add a subrouter to a
|
||||||
middleware []http.Handler
|
// chi router
|
||||||
|
type SubRouter interface {
|
||||||
|
MountTo(*cluster.Cluster, chi.Router) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new HTTP Server instance.
|
// Route defines a route that should be added to a chi router or
|
||||||
// Requires the IP and port number to bind to
|
// subrouter
|
||||||
func New(listen string, port int) *Server {
|
type Route struct {
|
||||||
s := &Server{bindAddr: fmt.Sprintf("%s:%d", listen, port)}
|
Method string
|
||||||
|
Path string
|
||||||
return s
|
Handler RouteHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the server and initializes the router and common middleware
|
// RouteHandler gets the active cluster for the server to inject into
|
||||||
func (s *Server) Start() {
|
// the http.HandlerFunc that is then returned
|
||||||
tstart := time.Now()
|
type RouteHandler func(*cluster.Cluster) http.HandlerFunc
|
||||||
defer func() {
|
|
||||||
log.Info("router.Server.Start").
|
|
||||||
Dur("upTime", time.Since(tstart)).
|
|
||||||
Msg("http server stopped")
|
|
||||||
}()
|
|
||||||
router := chi.NewRouter()
|
|
||||||
|
|
||||||
indev, _ := os.LookupEnv("CLUSTVIRT_DEV")
|
|
||||||
indev = strings.ToLower(indev)
|
|
||||||
switch indev {
|
|
||||||
case "true":
|
|
||||||
fallthrough
|
|
||||||
case "1":
|
|
||||||
fallthrough
|
|
||||||
case "yes":
|
|
||||||
fallthrough
|
|
||||||
case "on":
|
|
||||||
router.Use(middleware.NoCache)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) AddMiddleware(m http.Handler) {
|
|
||||||
s.middleware = append(s.middleware,
|
|
||||||
m)
|
|
||||||
}
|
|
||||||
|
21
router/server/root.go
Normal file
21
router/server/root.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/view"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/view/static"
|
||||||
|
"github.com/a-h/templ"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Root based routes for ClustVirt
|
||||||
|
|
||||||
|
func (s *Server) baseRoutes() {
|
||||||
|
// fileserver for static content
|
||||||
|
fs := http.StripPrefix("/static", http.FileServer(http.Dir("public")))
|
||||||
|
s.r.Get("/static/*", fs.ServeHTTP)
|
||||||
|
|
||||||
|
// Root defaults to the cluster view
|
||||||
|
s.r.Get("/", templ.Handler(view.ClusterInfo(s.c)).ServeHTTP)
|
||||||
|
s.r.Get("/about", templ.Handler(static.About()).ServeHTTP)
|
||||||
|
}
|
80
router/server/server.go
Normal file
80
router/server/server.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/router"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/router/htmx"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/router/middleware"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server represents an HTTP server that uses chi for routes
|
||||||
|
type Server struct {
|
||||||
|
bindAddr string
|
||||||
|
ssl bool
|
||||||
|
c *cluster.Cluster
|
||||||
|
r chi.Router
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new HTTP Server instance.
|
||||||
|
// Requires the IP and port number to bind to
|
||||||
|
func New(listen string, port int, cluster *cluster.Cluster) *Server {
|
||||||
|
s := &Server{bindAddr: fmt.Sprintf("%s:%d", listen, port), c: cluster}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start starts the server and initializes the router and common middleware
|
||||||
|
func (s *Server) Start() {
|
||||||
|
tstart := time.Now()
|
||||||
|
defer func() {
|
||||||
|
log.Info("router.Server.Start").
|
||||||
|
Dur("upTime", time.Since(tstart)).
|
||||||
|
Msg("http server stopped")
|
||||||
|
}()
|
||||||
|
s.r = chi.NewRouter()
|
||||||
|
|
||||||
|
indev, _ := os.LookupEnv("CLUSTVIRT_DEV")
|
||||||
|
indev = strings.ToLower(indev)
|
||||||
|
switch indev {
|
||||||
|
case "true":
|
||||||
|
fallthrough
|
||||||
|
case "1":
|
||||||
|
fallthrough
|
||||||
|
case "yes":
|
||||||
|
fallthrough
|
||||||
|
case "on":
|
||||||
|
s.AddMiddleware(middleware.NoCache)
|
||||||
|
s.r.Get("/_/debug", middleware.Profiler().ServeHTTP)
|
||||||
|
}
|
||||||
|
// Add routes
|
||||||
|
s.baseRoutes()
|
||||||
|
if err := s.AddSubRouter(htmx.Htmx); err != nil {
|
||||||
|
log.Error("server.Start").
|
||||||
|
Str("subroute", "htmx").
|
||||||
|
Err(err).Send()
|
||||||
|
}
|
||||||
|
// Start the server
|
||||||
|
if err := http.ListenAndServe(s.bindAddr, s.r); err != nil {
|
||||||
|
log.Error("router.Server.Start").
|
||||||
|
Str("bindaddr", s.bindAddr).
|
||||||
|
Err(err).Send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMiddleware appends middleware to the chi router
|
||||||
|
func (s *Server) AddMiddleware(m ...func(h http.Handler) http.Handler) {
|
||||||
|
s.r.Use(m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSubRouter attachs a SubRouter using it's MountTo method
|
||||||
|
func (s *Server) AddSubRouter(sr router.SubRouter) error {
|
||||||
|
return sr.MountTo(s.c, s.r)
|
||||||
|
}
|
@ -7,14 +7,18 @@ import (
|
|||||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||||
)
|
)
|
||||||
|
|
||||||
templ ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) {
|
templ ClusterInfo(c *cluster.Cluster) {
|
||||||
@layouts.Manager("ClustVirt", "Cluster Manager", navbar) {
|
@layouts.Manager("ClustVirt", "Cluster Manager", components.DefaultNavBar) {
|
||||||
<h3>Cluster Stats</h3>
|
<h3>Cluster Stats</h3>
|
||||||
@CPUStats(cs, diff)
|
@ClusterStats(cluster.InitStats(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
templ CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) {
|
templ ClusterStats(cs *cluster.ClusterStats) {
|
||||||
|
@CPUStats(cs.CPU, cs.Diff().CPU)
|
||||||
|
}
|
||||||
|
|
||||||
|
templ CPUStats(stats cluster.CPUStats, diff cluster.CPUDiff) {
|
||||||
<table class={ "table-auto", "w-full" }>
|
<table class={ "table-auto", "w-full" }>
|
||||||
<caption class={ "caption-top" }>
|
<caption class={ "caption-top" }>
|
||||||
CPU stats
|
CPU stats
|
||||||
@ -26,42 +30,25 @@ templ CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) {
|
|||||||
<th>Cores</th>
|
<th>Cores</th>
|
||||||
<th>Threads</th>
|
<th>Threads</th>
|
||||||
<th>Allocated</th>
|
<th>Allocated</th>
|
||||||
|
<th>MHz</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>Latest</td>
|
||||||
Latest
|
<td>{ fmt.Sprint(stats.Sockets) }</td>
|
||||||
</td>
|
<td>{ fmt.Sprint(stats.Cores) }</td>
|
||||||
<td>
|
<td>{ fmt.Sprint(stats.Threads) }</td>
|
||||||
{ fmt.Sprint(cs.CPU.Sockets) }
|
<td>{ fmt.Sprint(stats.Allocated) }</td>
|
||||||
</td>
|
<td>{ fmt.Sprint(stats.MHz) }</td>
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Cores) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Threads) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Allocated) }
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>Change</td>
|
||||||
Change
|
<td>{ fmt.Sprint(diff.Sockets) }</td>
|
||||||
</td>
|
<td>{ fmt.Sprint(diff.Cores) }</td>
|
||||||
<td>
|
<td>{ fmt.Sprint(diff.Threads) }</td>
|
||||||
{ fmt.Sprint(diff.CPU.Sockets) }
|
<td>{ fmt.Sprint(diff.Allocated) }</td>
|
||||||
</td>
|
<td>{ fmt.Sprint(diff.MHz) }</td>
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Cores) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Threads) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Allocated) }
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) templ.Component {
|
func ClusterInfo(c *cluster.Cluster) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -40,7 +40,7 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = CPUStats(cs, diff).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = ClusterStats(cluster.InitStats(c)).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
|||||||
}
|
}
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
templ_7745c5c3_Err = layouts.Manager("ClustVirt", "Cluster Manager", navbar).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = layouts.Manager("ClustVirt", "Cluster Manager", components.DefaultNavBar).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
func ClusterStats(cs *cluster.ClusterStats) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -73,8 +73,32 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
templ_7745c5c3_Var3 = templ.NopComponent
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
var templ_7745c5c3_Var4 = []any{"table-auto", "w-full"}
|
templ_7745c5c3_Err = CPUStats(cs.CPU, cs.Diff().CPU).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUStats(stats cluster.CPUStats, diff cluster.CPUDiff) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var4 == nil {
|
||||||
|
templ_7745c5c3_Var4 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
var templ_7745c5c3_Var5 = []any{"table-auto", "w-full"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -82,7 +106,7 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String()))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String()))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -90,8 +114,8 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var5 = []any{"caption-top"}
|
var templ_7745c5c3_Var6 = []any{"caption-top"}
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -99,31 +123,18 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String()))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var6).String()))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">CPU stats</caption> <thead><tr><th></th><th>Sockets</th><th>Cores</th><th>Threads</th><th>Allocated</th></tr></thead> <tbody><tr><td>Latest</td><td>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">CPU stats</caption> <thead><tr><th></th><th>Sockets</th><th>Cores</th><th>Threads</th><th>Allocated</th><th>MHz</th></tr></thead> <tbody><tr><td>Latest</td><td>")
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Sockets))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 36, Col: 33}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Cores))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Sockets))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 39, Col: 31}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 38, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -134,9 +145,9 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Threads))
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Cores))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 42, Col: 33}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 39, Col: 33}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -147,22 +158,22 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Allocated))
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Threads))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 45, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 40, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr><tr><td>Change</td><td>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var10 string
|
var templ_7745c5c3_Var10 string
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Sockets))
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Allocated))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 53, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 41, Col: 37}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -173,22 +184,22 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var11 string
|
var templ_7745c5c3_Var11 string
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Cores))
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.MHz))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 56, Col: 33}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 42, Col: 31}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr><tr><td>Change</td><td>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var12 string
|
var templ_7745c5c3_Var12 string
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Threads))
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Sockets))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 59, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 46, Col: 34}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -199,14 +210,53 @@ func CPUStats(cs *cluster.ClusterStats, diff cluster.StatDiff) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var13 string
|
var templ_7745c5c3_Var13 string
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Allocated))
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Cores))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 62, Col: 37}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 47, Col: 32}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var14 string
|
||||||
|
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Threads))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 48, Col: 34}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var15 string
|
||||||
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Allocated))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 49, Col: 36}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var16 string
|
||||||
|
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.MHz))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 50, Col: 30}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr></tbody></table>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr></tbody></table>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
|
7
view/components/defaults.go
Normal file
7
view/components/defaults.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
var DefaultNavBar = []NavItem{
|
||||||
|
{Name: "Cluster", Href: "/"},
|
||||||
|
{Name: "Configuration", Href: "/config"},
|
||||||
|
{Name: "About", Href: "/about"},
|
||||||
|
}
|
@ -123,11 +123,11 @@ templ HostInfo(h *host.Host) {
|
|||||||
<img class={ "h-6" , "px-2" , "htmx-indicator" , "inline-block" } src="/static/images/grid.svg"/>
|
<img class={ "h-6" , "px-2" , "htmx-indicator" , "inline-block" } src="/static/images/grid.svg"/>
|
||||||
</div>
|
</div>
|
||||||
<div class={ "flex" , "flex-row" , "flex-wrap" } id="sysInfo">
|
<div class={ "flex" , "flex-row" , "flex-wrap" } id="sysInfo">
|
||||||
@SysInfo(h)
|
@HostStats(h)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ SysInfo(h *host.Host) {
|
templ HostStats(h *host.Host) {
|
||||||
@MemChart(h)
|
@MemChart(h)
|
||||||
}
|
}
|
||||||
|
@ -505,7 +505,7 @@ func HostInfo(h *host.Host) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = SysInfo(h).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = HostStats(h).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -520,7 +520,7 @@ func HostInfo(h *host.Host) templ.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func SysInfo(h *host.Host) templ.Component {
|
func HostStats(h *host.Host) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||||
)
|
)
|
||||||
|
|
||||||
templ Home() {
|
templ About() {
|
||||||
@layouts.StaticPage("ClustVirt", "Libvirt, clustered and managed", []components.NavItem{
|
@layouts.StaticPage("ClustVirt", "Libvirt, clustered and managed", []components.NavItem{
|
||||||
{Name: "What", Href: "#"},
|
{Name: "What", Href: "#"},
|
||||||
{Name: "Why", Href: "#"},
|
{Name: "Why", Href: "#"},
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Home() templ.Component {
|
func About() templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
Loading…
Reference in New Issue
Block a user