From 8e62f7e271c26c67f0a433c394ff503dd8f25573 Mon Sep 17 00:00:00 2001 From: Matthew Stobbs Date: Sat, 23 Mar 2024 22:05:06 -0600 Subject: [PATCH] merge migrate_to_libvirtxml completed migration to libvirtxml --- cluster/builder.go | 20 +- cluster/cluster.go | 8 + cluster/errors.go | 8 + cluster/lock/lock.go | 19 + cluster/lock/volume.go | 1 + cluster/stats.go | 419 ++++++++++-------- go.mod | 24 +- go.sum | 111 +++-- lib/guest/lib.go | 6 +- lib/host/charts.go | 38 -- lib/host/errors.go | 12 + lib/host/lib.go | 617 ++++++++++---------------- lib/host/uri.go | 10 +- lib/log/logs.go | 30 ++ main.go | 74 +--- public/css/style.css | 12 + router/api/api.go | 3 + router/errors.go | 6 + router/htmx/htmx.go | 54 +++ router/htmx/routes.go | 83 ++++ router/middleware/fromchi.go | 22 + router/middleware/logger.go | 29 ++ router/router.go | 28 ++ router/server/root.go | 21 + router/server/server.go | 80 ++++ util/pcidb.go | 46 ++ view/cluster.templ | 92 ++-- view/cluster_templ.go | 381 +++++++++------- view/components/anchor_templ.go | 6 +- view/components/contentlist_templ.go | 17 +- view/components/contentp_templ.go | 2 +- view/components/defaults.go | 7 + view/components/flexrow_templ.go | 9 +- view/components/hero_templ.go | 2 +- view/components/hostbutton.templ | 46 ++ view/components/hostbutton_templ.go | 212 +++++++++ view/components/infobox_templ.go | 17 +- view/components/navbar_templ.go | 76 +++- view/hostinfo.templ | 58 +-- view/hostinfo_templ.go | 365 +++++----------- view/layouts/manager.templ | 13 +- view/layouts/manager_templ.go | 151 ++++++- view/layouts/staticpage_templ.go | 76 ++-- view/static/home.templ | 2 +- view/static/home_templ.go | 625 ++++++++++++++------------- 45 files changed, 2289 insertions(+), 1649 deletions(-) create mode 100644 cluster/errors.go create mode 100644 cluster/lock/lock.go create mode 100644 cluster/lock/volume.go delete mode 100644 lib/host/charts.go create mode 100644 lib/host/errors.go create mode 100644 lib/log/logs.go create mode 100644 router/api/api.go create mode 100644 router/errors.go create mode 100644 router/htmx/htmx.go create mode 100644 router/htmx/routes.go create mode 100644 router/middleware/fromchi.go create mode 100644 router/middleware/logger.go create mode 100644 router/router.go create mode 100644 router/server/root.go create mode 100644 router/server/server.go create mode 100644 util/pcidb.go create mode 100644 view/components/defaults.go create mode 100644 view/components/hostbutton.templ create mode 100644 view/components/hostbutton_templ.go diff --git a/cluster/builder.go b/cluster/builder.go index 3bb70c0..7b0a617 100644 --- a/cluster/builder.go +++ b/cluster/builder.go @@ -1,10 +1,10 @@ package cluster import ( - "log" "time" "git.staur.ca/stobbsm/clustvirt/lib/host" + "git.staur.ca/stobbsm/clustvirt/lib/log" ) // ClusterBuilder is used to build a Cluster object, which can then be used @@ -42,12 +42,17 @@ func (c *ClusterBuilder) DefaultHostURI(uri *host.URI) *ClusterBuilder { func (c *ClusterBuilder) AddHost(h string) *ClusterBuilder { if _, ok := c.cluster.hosts[h]; ok { - log.Println("warning: trying to add duplicate host") + log.Warn("cluster.AddHost"). + Str("hostname", h). + Msg("won't overwrite existing host") return c } hc, err := host.ConnectHost(c.cluster.defaultURI, h) if err != nil { - log.Printf("failed to connect to host: %s, %s", h, err) + log.Error("cluster.AddHost"). + Str("hostname", h). + Err(err). + Msg("failed to connect to host") return c } c.cluster.hosts[h] = hc @@ -56,12 +61,17 @@ func (c *ClusterBuilder) AddHost(h string) *ClusterBuilder { func (c *ClusterBuilder) AddHostWithURI(h string, uri *host.URI) *ClusterBuilder { if _, ok := c.cluster.hosts[h]; ok { - log.Println("warning: trying to add duplicate host") + log.Warn("cluster.AddHostWithURI"). + Str("hostname", h). + Msg("won't overwrite existing host") return c } hc, err := host.ConnectHost(uri, h) if err != nil { - log.Printf("failed to connect to host: %s, %s", h, err) + log.Error("cluster.AddHostWithURI"). + Str("hostname", h). + Err(err). + Msg("failed to connect to host") return c } c.cluster.hosts[h] = hc diff --git a/cluster/cluster.go b/cluster/cluster.go index d11cc9b..c3334d4 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -9,6 +9,7 @@ package cluster import ( + "fmt" "time" "git.staur.ca/stobbsm/clustvirt/lib/host" @@ -24,3 +25,10 @@ type Cluster struct { hosts map[string]*host.Host 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) +} diff --git a/cluster/errors.go b/cluster/errors.go new file mode 100644 index 0000000..5db7626 --- /dev/null +++ b/cluster/errors.go @@ -0,0 +1,8 @@ +package cluster + +import "errors" + +// Errors that can happen in the cluster +var ( + ErrHostNotFound = errors.New("host not found") +) diff --git a/cluster/lock/lock.go b/cluster/lock/lock.go new file mode 100644 index 0000000..ee8755a --- /dev/null +++ b/cluster/lock/lock.go @@ -0,0 +1,19 @@ +// Package lock implements a locking mechanism on shared resources to ensure +// they don't get used at the same time. There needs to be a lock for the following: +// - VM on Host: A VM must only exist on one host at a time +// - Storage attached to VM: Block storage can only be attached to one VM at a time +package lock + +// Locker interface used to lock and unlock Lockable resources +type Locker interface { + Lock(Lockable) error + Unlock(Lockable) error +} + +// Lockable interface must be attached to lockable resources, such as +// Virtual Machines, block devices, and host devices that can be attached +// to virtual machines. +type Lockable interface { + Locked() bool + HeldBy() Locker +} diff --git a/cluster/lock/volume.go b/cluster/lock/volume.go new file mode 100644 index 0000000..3716883 --- /dev/null +++ b/cluster/lock/volume.go @@ -0,0 +1 @@ +package lock diff --git a/cluster/stats.go b/cluster/stats.go index 672fc30..093118b 100644 --- a/cluster/stats.go +++ b/cluster/stats.go @@ -1,128 +1,215 @@ package cluster -// ClusterStats is used to gather stats for the entire cluster -type ClusterStats struct { - CPU struct { - Sockets uint32 - Cores uint32 - Threads uint32 - Allocated uint32 - } - Memory struct { - Total uint64 - Free uint64 - Buffers uint64 - Cached uint64 - Allocated uint64 - } - Storage struct { - Total uint64 - Used uint64 - Free uint64 - Active uint32 - Inactive uint32 - Pools uint32 +import ( + "git.staur.ca/stobbsm/clustvirt/lib/log" + "git.staur.ca/stobbsm/clustvirt/lib/storagepool" +) - Volumes struct { - Total uint32 - Active uint32 - Inactive uint32 - } - } - VM struct { - Count uint32 - Started uint32 - Stopped uint32 - } - Host struct { - Count uint32 - Available uint32 - } - Network struct { - Count uint32 - Active uint32 - Inactive uint32 - } +// ClusterStats is used to gather stats for the entire cluster +// Combined with StatsDiff, we can get some basic cluster wide stats tracking +type ClusterStats struct { + // CPU Statistics including number of CPUs + CPU CPUStats + // Memory provides information about the amount of memory, including free and + // allocated memory + Memory MemoryStats + // Storage provides information about storage pools, Only get's stats for active + // pools, and will not activate pools that are not already active. + // Trys to sort out shared file systems from local filesystems using the Type parameter + // of Host.StoragePoolInfo + Storage StorageStats + // Volume provides information on allocated volumes used in the cluster + Volume VolumeStats + // VM provides VM specific counters for the cluster + VM VMStats + // Host provides Host information for the cluster + Host HostStats + // Network provices available networks, and how many are shared between hosts + Network NetworkStats + // NetIF provides information about Libvirt allocated networks, usable by the + // libvirt cluster + NetIF NetIFStats old *ClusterStats c *Cluster } +// CPUStats provides information about the number of CPUs, Cores, +// Threads, and Speed available to the cluster. +type CPUStats struct { + Sockets uint32 + Cores uint32 + Threads uint32 + Allocated uint32 + MHz uint64 +} + +// MemoryStats provies information about the amount of memory, including free and +// allocated memory. Allocated is the total allocated to Guests +type MemoryStats struct { + Total uint64 + Free uint64 + Buffers uint64 + Cached uint64 + Allocated uint64 +} + +// StorageStats provides information about the available storage pools in the cluster, +// including the amount of space available, allocated, and how many pools are shared +// between hosts +// All sizes are in Bytes +type StorageStats struct { + Total uint64 + Used uint64 + Free uint64 + Active uint32 + Inactive uint32 + Pools uint32 +} + +// VolumeStats provides information about the number of volumes on the cluster. +// Counts volumes in shared storage (as detmermined by StorageStats) only once +type VolumeStats struct { + Total uint32 + Active uint32 + Inactive uint32 +} + +// VMStats provides information about the defined Virtual Machines on the cluster +type VMStats struct { + Count uint32 + Started uint32 + Stopped uint32 +} + +// 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 +type HostStats struct { + Available uint32 + Nodes uint32 +} + +// NetworkStats provides informatoin about the available Host network connections, +// including bridges and ethernet devices. +type NetworkStats struct { + Count uint32 + Active uint32 + Inactive uint32 +} + +// NetIFStats provides information about Libvirt defined networks +type NetIFStats struct { + Count uint32 + Common uint32 + Active uint32 + Inactive uint32 +} + +// DeviceStats provides information about the number of allocatable devices in the +// cluster. These are PCI and USB devices. +type DeviceStats struct { + Count uint32 +} + +// SecretStats provides the number of secrets defined throughout the cluster. +// Shared secrets are only counted once, and are recognized by their UUID +type SecretStats struct { + Count uint32 + Shared uint32 +} + // ClusterStats is used to gather stats for the entire cluster type StatDiff struct { - CPU struct { - Sockets int - Cores int - Threads int - Allocated int - } - Memory struct { - Total int - Free int - Buffers int - Cached int - Allocated int - } - Storage struct { - Total int - Used int - Free int - Active int - Inactive int - Pools int + CPU CPUDiff + Memory MemoryDiff + Storage StorageDiff + Volume VolumeDiff + VM VMDiff + Host HostDiff + Network NetworkDiff +} - Volumes struct { - Total int - Active int - Inactive int - } - } - VM struct { - Count int - Started int - Stopped int - } - Host struct { - Count int - Available int - } - Network struct { - Count int - Active int - Inactive int - } +type CPUDiff struct { + Sockets int + Cores int + Threads int + Allocated int + MHz int +} +type MemoryDiff struct { + Total int64 + Free int64 + Buffers int64 + Cached int64 + Allocated int64 +} +type StorageDiff struct { + Total int64 + Used int64 + Free int64 + Active int64 + Inactive int64 + Pools int +} +type VolumeDiff struct { + Total int + Active int + Inactive int +} +type VMDiff struct { + Count int + Started int + Stopped int +} +type HostDiff struct { + Count int + Available int +} +type NetworkDiff struct { + Count int + Active int + Inactive int } // InitStats is given a cluster, which it then uses to load the initial statistics // Does not close connections, but uses the host connections available to the // cluster to add statistics together. func InitStats(c *Cluster) *ClusterStats { + log.Info("stats.InitStats").Msg("intializing stats") cs := &ClusterStats{ c: c, } + cs.Update() return cs } // Update triggers the stats collector to refresh it's statistics func (cs *ClusterStats) Update() { + log.Info("ClusterStats.Update").Msg("copying existing stats") cs.old = cs.copy() + log.Info("ClusterStats.Update").Msg("reseting stats") cs.reset() // Start looping through each host in the cluster, adding to the total for _, h := range cs.c.hosts { - cs.Host.Count++ + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling stats") + cs.Host.Nodes++ cs.Host.Available++ - cs.CPU.Sockets += h.HostInfo.Sockets - cs.CPU.Cores += h.HostInfo.Cores - cs.CPU.Threads += h.HostInfo.Threads + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling host cpu stats") + cs.CPU.Sockets += uint32(h.HostInfo.CPU.Topology.Sockets) + cs.CPU.Cores += uint32(h.HostInfo.CPU.Topology.Cores) + cs.CPU.Threads += uint32(h.HostInfo.CPU.Topology.Threads * h.HostInfo.CPU.Topology.Cores) + cs.CPU.MHz += uint64(h.HostInfo.CPU.Counter.Frequency) + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling host memmory stats") cs.Memory.Total += h.NodeMemory.Total cs.Memory.Free += h.NodeMemory.Free cs.Memory.Buffers += h.NodeMemory.Buffers cs.Memory.Cached += h.NodeMemory.Cached + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling host storage pool stats") // Storage Pool counting cs.Storage.Pools += uint32(len(h.StoragePoolList)) countedSharedPools := map[string]struct{}{} @@ -132,128 +219,76 @@ func (cs *ClusterStats) Update() { // Already counted this shared pool, move on continue } - if sp.HAEnabled { + if isNetworkPool(sp.Type) { countedSharedPools[sp.Name] = struct{}{} } - if !sp.Active { - cs.Storage.Inactive++ - continue - } cs.Storage.Active++ - cs.Storage.Total += sp.Capacity - cs.Storage.Used += sp.Allocation - cs.Storage.Free += sp.Capacity - sp.Allocation - // Volumes in the pool - cs.Storage.Volumes.Total += uint32(len(sp.Volumes)) - for range sp.Volumes { - cs.Storage.Volumes.Active++ - } + cs.Storage.Total += sp.Capacity.Value + cs.Storage.Used += sp.Allocation.Value + cs.Storage.Free += sp.Capacity.Value - sp.Allocation.Value } + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling volume stats") + cs.Volume.Total += uint32(len(h.VolumeList)) + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling VM stats") // VM Count cs.VM.Count += uint32(len(h.VMList)) for _, vm := range h.VMList { - cs.CPU.Allocated += uint32(vm.VCPUs) - cs.Memory.Allocated += uint64(vm.Memory) - if vm.Active { - cs.VM.Started++ - continue - } - cs.VM.Stopped++ + log.Info("ClusterStats.Update").Str("hostname", h.HostName).Str("vmname", vm.Name).Msg("filling vm info") + cs.CPU.Allocated += uint32(vm.VCPU.Value) + cs.Memory.Allocated += uint64(vm.Memory.Value) } // Network count cs.Network.Count += uint32(len(h.NetworkList)) - for _, ni := range h.NetworkList { - if ni.Active { - cs.Network.Active++ - continue - } - cs.Network.Inactive++ - } + cs.Network.Inactive++ } } // Diff returns a map of all the field and how they changed func (cs *ClusterStats) Diff() StatDiff { return StatDiff{ - CPU: struct { - Sockets int - Cores int - Threads int - Allocated int - }{ + CPU: CPUDiff{ Sockets: int(cs.CPU.Sockets) - int(cs.old.CPU.Sockets), Cores: int(cs.CPU.Cores) - int(cs.old.CPU.Cores), Threads: int(cs.CPU.Threads) - int(cs.old.CPU.Threads), Allocated: int(cs.CPU.Allocated) - int(cs.old.CPU.Allocated), + MHz: int(cs.CPU.MHz) - int(cs.old.CPU.MHz), }, - Memory: struct { - Total int - Free int - Buffers int - Cached int - Allocated int - }{ - Total: int(cs.old.Memory.Total - cs.Memory.Total), - Free: int(cs.old.Memory.Free - cs.Memory.Free), - Buffers: int(cs.old.Memory.Buffers - cs.Memory.Buffers), - Cached: int(cs.old.Memory.Cached - cs.Memory.Cached), - Allocated: int(cs.old.Memory.Allocated - cs.Memory.Allocated), + Memory: MemoryDiff{ + Total: int64(cs.old.Memory.Total) - int64(cs.Memory.Total), + Free: int64(cs.old.Memory.Free) - int64(cs.Memory.Free), + Buffers: int64(cs.old.Memory.Buffers) - int64(cs.Memory.Buffers), + Cached: int64(cs.old.Memory.Cached) - int64(cs.Memory.Cached), + Allocated: int64(cs.old.Memory.Allocated) - int64(cs.Memory.Allocated), }, - Storage: struct { - Total int - Used int - Free int - Active int - Inactive int - Pools int - Volumes struct { - Total int - Active int - Inactive int - } - }{ - Total: int(cs.old.Storage.Total - cs.Storage.Total), - Used: int(cs.old.Storage.Used - cs.Storage.Used), - Free: int(cs.old.Storage.Free - cs.Storage.Free), - Active: int(cs.old.Storage.Active - cs.Storage.Active), - Inactive: int(cs.old.Storage.Inactive - cs.Storage.Inactive), - Pools: int(cs.old.Storage.Pools - cs.Storage.Pools), - Volumes: struct { - Total int - Active int - Inactive int - }{ - Total: int(cs.old.Storage.Volumes.Total - cs.Storage.Volumes.Total), - Active: int(cs.old.Storage.Volumes.Active - cs.Storage.Volumes.Active), - Inactive: int(cs.old.Storage.Volumes.Inactive - cs.Storage.Volumes.Inactive), - }, + Storage: StorageDiff{ + Total: int64(cs.old.Storage.Total) - int64(cs.Storage.Total), + Used: int64(cs.old.Storage.Used) - int64(cs.Storage.Used), + Free: int64(cs.old.Storage.Free) - int64(cs.Storage.Free), + Active: int64(cs.old.Storage.Active) - int64(cs.Storage.Active), + Inactive: int64(cs.old.Storage.Inactive) - int64(cs.Storage.Inactive), + Pools: int(cs.old.Storage.Pools) - int(cs.Storage.Pools), }, - VM: struct { - Count int - Started int - Stopped int - }{ - Count: int(cs.old.VM.Count - cs.VM.Count), - Started: int(cs.old.VM.Started - cs.VM.Started), - Stopped: int(cs.old.VM.Stopped - cs.VM.Stopped), + Volume: VolumeDiff{ + Total: int(cs.old.Volume.Total) - int(cs.Volume.Total), + Active: int(cs.old.Volume.Active) - int(cs.Volume.Active), + Inactive: int(cs.old.Volume.Inactive) - int(cs.Volume.Inactive), }, - Host: struct { - Count int - Available int - }{ - Count: int(cs.old.Host.Count - cs.Host.Count), - Available: int(cs.old.Host.Available - cs.Host.Available), + + VM: VMDiff{ + Count: int(cs.old.VM.Count) - int(cs.VM.Count), + Started: int(cs.old.VM.Started) - int(cs.VM.Started), + Stopped: int(cs.old.VM.Stopped) - int(cs.VM.Stopped), }, - Network: struct { - Count int - Active int - Inactive int - }{ - Count: int(cs.old.Network.Count - cs.Network.Count), - Active: int(cs.old.Network.Active - cs.Network.Active), - Inactive: int(cs.old.Network.Inactive - cs.Network.Inactive), + Host: HostDiff{ + Count: int(cs.old.Host.Nodes) - int(cs.Host.Nodes), + Available: int(cs.old.Host.Available) - int(cs.Host.Available), + }, + Network: NetworkDiff{ + Count: int(cs.old.Network.Count) - int(cs.Network.Count), + Active: int(cs.old.Network.Active) - int(cs.Network.Active), + Inactive: int(cs.old.Network.Inactive) - int(cs.Network.Inactive), }, } } @@ -270,11 +305,13 @@ func (cs *ClusterStats) reset() { cs.CPU.Cores = 0 cs.CPU.Threads = 0 cs.CPU.Allocated = 0 + cs.CPU.MHz = 0 cs.Memory.Total = 0 cs.Memory.Free = 0 cs.Memory.Buffers = 0 cs.Memory.Cached = 0 + cs.Memory.Allocated = 0 cs.Storage.Total = 0 cs.Storage.Used = 0 @@ -283,14 +320,32 @@ func (cs *ClusterStats) reset() { cs.Storage.Inactive = 0 cs.Storage.Pools = 0 + cs.Volume.Total = 0 + cs.Volume.Active = 0 + cs.Volume.Inactive = 0 + cs.VM.Count = 0 cs.VM.Started = 0 cs.VM.Stopped = 0 - cs.Host.Count = 0 cs.Host.Available = 0 + cs.Host.Nodes = 0 cs.Network.Count = 0 cs.Network.Active = 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 { + for _, t := range storagepool.NetTypes { + if t == pooltype { + return true + } + } + return false } diff --git a/go.mod b/go.mod index 5595d94..0e87644 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,28 @@ module git.staur.ca/stobbsm/clustvirt go 1.22.1 require ( - github.com/a-h/templ v0.2.598 + github.com/a-h/templ v0.2.646 github.com/go-chi/chi/v5 v5.0.12 - github.com/wcharczuk/go-chart/v2 v2.1.1 - gopkg.in/ffmt.v1 v1.5.6 + github.com/jaypipes/pcidb v1.0.0 + github.com/rs/zerolog v1.32.0 libvirt.org/go/libvirt v1.10001.0 libvirt.org/go/libvirtxml v1.10001.0 ) require ( - github.com/blend/go-sdk v1.20220411.3 // indirect - github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - golang.org/x/image v0.11.0 // indirect + 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-isatty v0.0.20 // 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 ) diff --git a/go.sum b/go.sum index 13dfa44..42e455f 100644 --- a/go.sum +++ b/go.sum @@ -1,50 +1,97 @@ 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/blend/go-sdk v1.20220411.3 h1:GFV4/FQX5UzXLPwWV03gP811pj7B8J2sbuq+GJQofXc= -github.com/blend/go-sdk v1.20220411.3/go.mod h1:7lnH8fTi6U4i1fArEXRyOIY2E1X4MALg09qsQqY1+ak= +github.com/a-h/templ v0.2.646 h1:F4+tGmPavtPMdWF3ofCDkPx/31qtInztsmUdzu6EzVU= +github.com/a-h/templ v0.2.646/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8= +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/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +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/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/wcharczuk/go-chart/v2 v2.1.1 h1:2u7na789qiD5WzccZsFz4MJWOJP72G+2kUuJoSNqWnE= -github.com/wcharczuk/go-chart/v2 v2.1.1/go.mod h1:CyCAUt2oqvfhCl6Q5ZvAZwItgpQKZOkCJGb+VGv6l14= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8= +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/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.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +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/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/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/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= -golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +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.6.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/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/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +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= -gopkg.in/ffmt.v1 v1.5.6 h1:4Bu3riZp5sAIXW2T/18JM9BkwJLodurXFR0f7PXp+cw= -gopkg.in/ffmt.v1 v1.5.6/go.mod h1:LssvGOZFiBGoBcobkTqnyh+uN1VzIRoibW+c0JI/Ha4= +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/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ= libvirt.org/go/libvirtxml v1.10001.0 h1:r9WBs24r3mxIG3/hAMRRwDMy4ZaPHmhHjw72o/ceXic= diff --git a/lib/guest/lib.go b/lib/guest/lib.go index dc52ec5..0f0f728 100644 --- a/lib/guest/lib.go +++ b/lib/guest/lib.go @@ -3,9 +3,9 @@ package guest import ( "errors" - "log" "time" + "git.staur.ca/stobbsm/clustvirt/lib/log" "git.staur.ca/stobbsm/clustvirt/util" "libvirt.org/go/libvirt" ) @@ -248,7 +248,7 @@ func GetGuest(name string, conn *libvirt.Connect) (*VM, error) { // Not errors, but still log the warnings when this happens if g.BackupXML, err = g.dom.BackupGetXMLDesc(0); err != nil { - log.Printf("WARNING: While loading backup information: %s", err) + log.Warn("guest.GetGuest").Str("guest", g.Name).Err(err).Send() } go func() { @@ -262,7 +262,7 @@ func GetGuest(name string, conn *libvirt.Connect) (*VM, error) { // Close closes an open connection func (g *VM) Close() error { - log.Println("Closing VM", g.Name) + log.Info("guest.Close").Str("guest", g.Name).Msg("closing vm") close(g.close) return <-g.closeErr } diff --git a/lib/host/charts.go b/lib/host/charts.go deleted file mode 100644 index 87b0c86..0000000 --- a/lib/host/charts.go +++ /dev/null @@ -1,38 +0,0 @@ -package host - -import ( - "fmt" - "log" - "strings" - - "github.com/wcharczuk/go-chart/v2" -) - -// This file contains utilities to create charts based on the different data -// 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") - memFree := float64(h.NodeMemory.Free) - memCached := float64(h.NodeMemory.Cached) - memBuffer := float64(h.NodeMemory.Buffers) - memTotal := float64(h.NodeMemory.Total) - - c := chart.PieChart{ - Title: fmt.Sprintf("Memory Info %s", h.SystemHostName), - Width: 256, - Height: 256, - Values: []chart.Value{ - {Value: memTotal - memFree, Label: fmt.Sprintf("%.2f%% Free", memFree/memTotal*100)}, - {Value: memTotal - memCached, Label: fmt.Sprintf("%.2f%% Cached", memCached/memTotal*100)}, - {Value: memTotal - memBuffer, Label: fmt.Sprintf("%.2f%% Buffers", memBuffer/memTotal*100)}, - }, - } - sb := new(strings.Builder) - log.Println("Rendering chart") - if err := c.Render(chart.SVG, sb); err != nil { - return err.Error() - } - return sb.String() -} diff --git a/lib/host/errors.go b/lib/host/errors.go new file mode 100644 index 0000000..8237498 --- /dev/null +++ b/lib/host/errors.go @@ -0,0 +1,12 @@ +package host + +import "errors" + +var ( + // XML errors + ErrGetXML = errors.New("error getting XML") + ErrParseXML = errors.New("error parsing XML") + + // Hostinfo errors + ErrHostInfo = errors.New("error processing HostInfo") +) diff --git a/lib/host/lib.go b/lib/host/lib.go index 4ef75f0..a370b22 100644 --- a/lib/host/lib.go +++ b/lib/host/lib.go @@ -7,14 +7,10 @@ package host import ( - "log" "sync" "git.staur.ca/stobbsm/clustvirt/lib/guest" - "git.staur.ca/stobbsm/clustvirt/lib/secret" - "git.staur.ca/stobbsm/clustvirt/lib/storagepool" - "git.staur.ca/stobbsm/clustvirt/lib/storagevol" - "git.staur.ca/stobbsm/clustvirt/util" + "git.staur.ca/stobbsm/clustvirt/lib/log" "libvirt.org/go/libvirt" "libvirt.org/go/libvirtxml" ) @@ -27,20 +23,8 @@ type Host struct { HostName string // SystemHostName is the hostname as reported by the system itself SystemHostName string - // FreeMemory is the available free memory - FreeMemory uint64 // LibVersion is the version of Libvirt on the host LibVersion uint32 - // HostInfo provides basic HW information about a host - HostInfo NodeInfo - // HostSEVInfo provides informatoin about AMD SEV extentions available on the host - HostSEVInfo SEVInfo - // AvailableCPUTypes are the available types of CPUs that can be used for VM creation - AvailableCPUTypes []string - // NodeMemory provides basic memory information about the Host - NodeMemory NodeMemoryInfo - // StorageCapabilities is the XML representation of the hosts storage capabilities - StorageCapabilities string // SysInfo is the XML representation of the host system information SysInfo string // Alive indicates if the connection is alive @@ -49,18 +33,24 @@ type Host struct { Encrypted bool // Secure indicates if the connection is secure Secure bool + // HostInfo provides basic HW information about a host + HostInfo *libvirtxml.CapsHost + // NodeMemory provides basic memory information about the Host + NodeMemory *NodeMemoryInfo // VMList is the list of virtual machines available to the host - VMList []VMInfo + VMList []*libvirtxml.Domain // NetIfList is the list of network interfaces on the host - NetIfFList []NetIfInfo + NetIfFList []*libvirtxml.Interface // NetworkList is the list of defined networks on the host - NetworkList []NetworkInfo + NetworkList []*libvirtxml.Network // DeviceList is the list of devices on the host - DeviceList []DeviceInfo + DeviceList []*libvirtxml.NodeDevice // SecretList provides a list of secrets available to the host - SecretList []SecretInfo + SecretList []*libvirtxml.Secret // StoragePoolList provides the list of stoarge ppols available to the host - StoragePoolList []StoragePoolInfo + StoragePoolList []*libvirtxml.StoragePool + // VolumeList is the list of volumes available on the host + VolumeList []*libvirtxml.StorageVolume uri *URI conn *libvirt.Connect @@ -68,108 +58,6 @@ type Host struct { closeErr chan error } -// DeviceInfo holds basic information for host devices -type DeviceInfo struct { - Name string - Capabilities []string - XML string -} - -// VMInfo holds basic VM information, like the name and ID -type VMInfo struct { - Name string - ID uint - UUID []byte - XML string - Active bool - VCPUs uint - Memory uint - // States are the current states active on the host - States []guest.VMState -} - -// SecretInfo doesn't let you see the contents of secrets, but does let you see what secrets have -// been defined in a simple format. -type SecretInfo struct { - UUID string - XML string - Type string -} - -// StoragePoolInfo holds basic information on storage pools -type StoragePoolInfo struct { - Name string - UUID []byte - Type string - XML string - Active bool - Persistent bool - AutoStart bool - State string - Capacity uint64 - Allocation uint64 - Available uint64 - IsNet bool - // HAEnabled indicates if the storage pool has High Availability - HAEnabled bool - // Volumes defined in the storage pool - Volumes []VolumeInfo -} - -// VolumeInfo holds basic information about Volumes available in storage pools -type VolumeInfo struct { - Name string - Key string - Path string - Type string - Capacity uint64 - Allocation uint64 - XML string -} - -// NetIfInfo holds basic information about available network interfaces (not their connections, the devices themselves) -type NetIfInfo struct { - Name string - MacAddr string - XML string -} - -// NetworkInfo holds basic information about network connections -type NetworkInfo struct { - Name string - UUID []byte - XML string - Active bool - // NetIf is the network interface this connection is applied to - NetIf NetIfInfo -} - -// NodeInfo represents the basic HW info for a host node -type NodeInfo struct { - // livirt.NodeInfo section - Model string - Memory uint64 - Cpus uint - MHz uint - Nodes uint32 - Sockets uint32 - Cores uint32 - Threads uint32 -} - -// SEVInfo provides information about AMD SEV support -type SEVInfo struct { - // livirt.NodeSEVParameters section - SEVEnabled bool - PDH string - CertChain string - CBitPos uint - ReducedPhysBits uint - MaxGuests uint - MaxEsGuests uint - CPU0ID string -} - // NodeMemoryInfo provides statistis about node memory usage from libvirt.NodeMemoryStats type NodeMemoryInfo struct { Total uint64 @@ -226,7 +114,7 @@ func (h *Host) GetGuestByName(name string) (*guest.VM, error) { // Close triggers closing the host connection func (h *Host) Close() error { - log.Println("Closing Host", h.HostName) + log.Info("Host.Close").Str("hostname", h.HostName).Msg("closing connection") close(h.close) return <-h.closeErr } @@ -234,17 +122,18 @@ func (h *Host) Close() error { // private methods that load the different informational parts func (h *Host) getInfo() { - var wg = new(sync.WaitGroup) + wg := new(sync.WaitGroup) + log.Info("host.getInfo").Str("hostname", h.HostName).Msg("collecting host information") infoFuncs := []func(){ - h.getDevicesInfo, - // h.getDomainInfo, - h.getIfaceInfo, + h.hostInfo, + h.memoryInfo, + h.getStoragePools, h.getNetsInfo, - h.getNodeInfo, - // h.getSEVInfo, - // h.getSecretsInfo, - // h.getStoragePools, + h.getIfaceInfo, + h.getDevicesInfo, + h.getDomainInfo, + h.getSecretsInfo, } for _, f := range infoFuncs { @@ -258,298 +147,242 @@ func (h *Host) getInfo() { wg.Wait() } +func (h *Host) hostInfo() { + log.Info("host.hostInfo").Str("hostname", h.HostName).Msg("collecting hostinfo") + var err error + + rawxml, err := h.conn.GetCapabilities() + if err != nil { + log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + } + xmldoc := &libvirtxml.Caps{} + if err = xmldoc.Unmarshal(rawxml); err != nil { + log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + } + h.HostInfo = &xmldoc.Host + h.SystemHostName, err = h.conn.GetHostname() + if err != nil { + log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(err).Msg("unable to set SystemHostName") + } + if h.SystemHostName == "" { + h.SystemHostName = h.HostName + } + log.Info("Host.hostInfo").Str("hostname", h.HostName).Str("system hostname", h.SystemHostName).Msg("set system hostname") + h.LibVersion, err = h.conn.GetLibVersion() + if err != nil { + log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(err).Msg("unable to get libversion") + return + } + log.Info("Host.hostInfo").Str("hostname", h.HostName).Uint32("libversion", h.LibVersion).Send() +} + +func (h *Host) memoryInfo() { + mi, err := h.conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0) + if err != nil { + log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Send() + } + h.NodeMemory = &NodeMemoryInfo{ + Total: mi.Total, + Free: mi.Free, + Buffers: mi.Buffers, + Cached: mi.Cached, + } + + h.SysInfo, err = h.conn.GetSysinfo(0) + if err != nil { + log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed to GetSysInfo") + } + + h.Alive, err = h.conn.IsAlive() + if err != nil { + log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed check to IsAlive") + } + h.Encrypted, err = h.conn.IsEncrypted() + if err != nil { + log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed to check IsEncrypted") + } + h.Secure, err = h.conn.IsSecure() + if err != nil { + log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed to check IsSecure") + } +} + func (h *Host) getStoragePools() { + log.Info("host.getStoragePools").Str("hostname", h.HostName).Msg("collection storage pool information") + // Get list of all storage pools on the host spools, err := h.conn.ListAllStoragePools(0) if err != nil { - log.Println(err) + log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(err).Msg("failed to ListAllStoragePools") } if len(spools) > 0 { - h.StoragePoolList = make([]StoragePoolInfo, len(spools)) + h.StoragePoolList = make([]*libvirtxml.StoragePool, len(spools)) for i, s := range spools { - if h.StoragePoolList[i].XML, err = s.GetXMLDesc(0); err != nil { - log.Println(err) - } - if h.StoragePoolList[i].Name, err = s.GetName(); err != nil { - log.Println(err) - } - if h.StoragePoolList[i].UUID, err = s.GetUUID(); err != nil { - log.Println(err) - } - if h.StoragePoolList[i].Active, err = s.IsActive(); err != nil { - log.Println(err) - } - if h.StoragePoolList[i].Persistent, err = s.IsPersistent(); err != nil { - log.Println(err) - } - if h.StoragePoolList[i].AutoStart, err = s.GetAutostart(); err != nil { - log.Println(err) - } - spInfo, err := s.GetInfo() - if err != nil { - log.Println(err) - } - h.StoragePoolList[i].State = storagepool.StoragePoolStateMap[spInfo.State] - h.StoragePoolList[i].Capacity = spInfo.Capacity - h.StoragePoolList[i].Allocation = spInfo.Allocation - h.StoragePoolList[i].Available = spInfo.Available - - spoolXML := &libvirtxml.StoragePool{} - if err = spoolXML.Unmarshal(h.StoragePoolList[i].XML); err != nil { - log.Println(err) - } - h.StoragePoolList[i].Type = spoolXML.Type - for _, t := range storagepool.NetTypes { - if h.StoragePoolList[i].Type == t { - h.StoragePoolList[i].IsNet = true - h.StoragePoolList[i].HAEnabled = true - continue - } - } - - svols, err := s.ListAllStorageVolumes(0) - if err != nil { - log.Println(err) - } - if len(svols) > 0 { - h.StoragePoolList[i].Volumes = make([]VolumeInfo, len(svols)) - for j, sv := range svols { - 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 { - log.Println(err) - } - if h.StoragePoolList[i].Volumes[j].Path, err = sv.GetPath(); err != nil { - log.Println(err) - } - svInfo, err := sv.GetInfo() // Type, Capacity, Allocation - if err != nil { - log.Println(err) - } - h.StoragePoolList[i].Volumes[j].Type = storagevol.StorageVolTypeMap[svInfo.Type] - h.StoragePoolList[i].Volumes[j].Capacity = svInfo.Capacity - h.StoragePoolList[i].Volumes[j].Allocation = svInfo.Allocation - if h.StoragePoolList[i].Volumes[j].XML, err = sv.GetXMLDesc(0); err != nil { - log.Println(err) - } - - sv.Free() + // run in a function to allow defer s.Free() + func() { + defer s.Free() + // Get the XML represenation of each storage pool, parse it with libvirtxml + rawxml, err := s.GetXMLDesc(0) + if err != nil { + log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + return } - } + xmldoc := &libvirtxml.StoragePool{} + err = xmldoc.Unmarshal(rawxml) + if err != nil { + log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + return + } + h.StoragePoolList[i] = xmldoc - s.Free() + // Get list of all storage volumes in the current storage pool + svols, err := s.ListAllStorageVolumes(0) + if err != nil { + log.Error("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Err(err).Msg("failed to ListAllStorageVolumes") + } + if len(svols) > 0 { + // define temporary variable to hold slice of StorageVolume, that can + // either be appended to the existing slice, or used in place of the newly + // defined slice + tvl := make([]*libvirtxml.StorageVolume, len(svols)) + for j, sv := range svols { + // run in a function so I can defer the sv.Free() call + func() { + defer sv.Free() + rawxml, err = sv.GetXMLDesc(0) + if err != nil { + log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + return + } + xmldoc := &libvirtxml.StorageVolume{} + err = xmldoc.Unmarshal(rawxml) + if err != nil { + log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + return + } + tvl[j] = xmldoc + log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("added volume", tvl[j].Name).Send() + }() + } + // Append the contents of tvl to h.VolumeList + if h.VolumeList == nil { + log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Msg("initializing VolumeList") + h.VolumeList = []*libvirtxml.StorageVolume{} + } + // Only append if the temporary storage volume isn't nil + log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Int("VolumeList count", len(h.VolumeList)).Msg("before filter") + for _, tsv := range tvl { + if tsv != nil { + h.VolumeList = append(h.VolumeList, tsv) + } + } + log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Int("VolumeList count", len(h.VolumeList)).Msg("after filter") + } + }() } } } func (h *Host) getSecretsInfo() { + log.Info("host.getSecretsInfo").Str("hostname", h.HostName).Msg("collecting secret information") nsecrets, err := h.conn.ListAllSecrets(0) if err != nil { - log.Println(err) + log.Error("Host.getSecretsInfo").Str("hostname", h.HostName).Err(err).Send() } if len(nsecrets) > 0 { - h.SecretList = make([]SecretInfo, len(nsecrets)) + h.SecretList = make([]*libvirtxml.Secret, len(nsecrets)) for i, s := range nsecrets { - if h.SecretList[i].XML, err = s.GetXMLDesc(0); err != nil { - log.Println(err) - } - stype, err := s.GetUsageType() - if err != nil { - log.Println(err) - } - h.SecretList[i].Type = secret.SecretUsageTypeMap[stype] - - s.Free() + func() { + defer s.Free() + rawxml, err := s.GetXMLDesc(0) + if err != nil { + log.Error("Host.getSecretsInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + } + xmldoc := &libvirtxml.Secret{} + if err = xmldoc.Unmarshal(rawxml); err != nil { + log.Error("Host.getSecretsInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + } + h.SecretList[i] = xmldoc + }() } } } -func (h *Host) getNodeInfo() { - var err error - h.AvailableCPUTypes, err = h.conn.GetCPUModelNames("x86_64", 0) - if err != nil { - log.Println("Error getting cpu model names", err) - } - - ni, err := h.conn.GetNodeInfo() - if err != nil { - log.Println(err) - } - h.HostInfo.Model = ni.Model - h.HostInfo.Memory = ni.Memory - h.HostInfo.Cpus = ni.Cpus - h.HostInfo.MHz = ni.MHz - h.HostInfo.Nodes = ni.Nodes - h.HostInfo.Sockets = ni.Sockets - h.HostInfo.Cores = ni.Cores - h.HostInfo.Threads = ni.Threads - h.SystemHostName, err = h.conn.GetHostname() - if err != nil { - log.Println(err) - } - if h.SystemHostName == "" { - h.SystemHostName = h.HostName - } - h.LibVersion, err = h.conn.GetLibVersion() - if err != nil { - log.Println(err) - } - h.FreeMemory, err = h.conn.GetFreeMemory() - if err != nil { - log.Println(err) - } - - mi, err := h.conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0) - if err != nil { - log.Println(err) - } - h.NodeMemory.Total = mi.Total - h.NodeMemory.Free = mi.Free - h.NodeMemory.Buffers = mi.Buffers - h.NodeMemory.Cached = mi.Cached - - h.StorageCapabilities, err = h.conn.GetStoragePoolCapabilities(0) - if err != nil { - log.Println(err) - } - - h.SysInfo, err = h.conn.GetSysinfo(0) - if err != nil { - log.Println(err) - } - - h.Alive, err = h.conn.IsAlive() - if err != nil { - log.Println(err) - } - h.Encrypted, err = h.conn.IsEncrypted() - if err != nil { - log.Println(err) - } - h.Secure, err = h.conn.IsSecure() - if err != nil { - log.Println(err) - } -} - -func (h *Host) getSEVInfo() { - // getSEVInfo - h.HostSEVInfo.SEVEnabled = true - ns, err := h.conn.GetSEVInfo(0) - if err != nil { - log.Println(err) - lverr, ok := err.(libvirt.Error) - if ok { - switch lverr.Code { - case 84: - log.Println("SEV functions not supported") - h.HostSEVInfo.SEVEnabled = false - default: - log.Println("Error encountered", lverr.Error()) - } - } - } - if h.HostSEVInfo.SEVEnabled { - h.HostSEVInfo.PDH = util.SetNotSet(ns.PDH, ns.PDHSet) - h.HostSEVInfo.CertChain = util.SetNotSet(ns.CertChain, ns.CertChainSet) - h.HostSEVInfo.CBitPos = ns.CBitPos - h.HostSEVInfo.ReducedPhysBits = ns.ReducedPhysBits - h.HostSEVInfo.MaxGuests = ns.MaxGuests - h.HostSEVInfo.MaxEsGuests = ns.MaxEsGuests - h.HostSEVInfo.CPU0ID = util.SetNotSet(ns.CPU0ID, ns.CPU0IDSet) - } -} - func (h *Host) getDomainInfo() { + log.Info("host.getDomainInfo").Str("hostname", h.HostName).Msg("collecting domain (vm) information") // getDomainInfo doms, err := h.conn.ListAllDomains(0) if err != nil { - log.Println(err) + log.Error("Host.getDomainInfo").Str("hostname", h.HostName).Err(err).Send() + return } if len(doms) > 0 { - h.VMList = make([]VMInfo, len(doms)) + h.VMList = make([]*libvirtxml.Domain, len(doms)) for i, d := range doms { - // Just going to log errors here, and free the dom after getting what we can - if h.VMList[i].Name, err = d.GetName(); err != nil { - log.Println(err) - } - if h.VMList[i].UUID, err = d.GetUUID(); err != nil { - log.Println(err) - } - if h.VMList[i].ID, err = d.GetID(); err != nil { - log.Println(err) - } - if h.VMList[i].XML, err = d.GetXMLDesc(0); err != nil { - log.Println(err) - } - vmXML := &libvirtxml.Domain{} - if err = vmXML.Unmarshal(h.VMList[i].XML); err != nil { - log.Println(err) - } - h.VMList[i].VCPUs = vmXML.VCPU.Value - h.VMList[i].Memory = vmXML.CurrentMemory.Value - if h.VMList[i].Active, err = d.IsActive(); err != nil { - log.Println(err) - } - - d.Free() + func() { + defer d.Free() + rawxml, err := d.GetXMLDesc(0) + if err != nil { + log.Error("Host.getDomainInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + return + } + h.VMList[i] = &libvirtxml.Domain{} + if err = h.VMList[i].Unmarshal(rawxml); err != nil { + log.Error("Host.getDomainInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + return + } + }() } } } func (h *Host) getIfaceInfo() { // getIfaceInfo - ifaces, err := h.conn.ListInterfaces() + ifaces, err := h.conn.ListAllInterfaces(0) if err != nil { - log.Println(err) + log.Error("Host.getIfaceInfo").Str("hostname", h.HostName).Err(err).Send() } if len(ifaces) > 0 { - h.NetIfFList = make([]NetIfInfo, len(ifaces)) + h.NetIfFList = make([]*libvirtxml.Interface, len(ifaces)) for i, ni := range ifaces { - h.NetIfFList[i].Name = ni - iface, err := h.conn.LookupInterfaceByName(ni) - if err != nil { - log.Println(err) - } - if h.NetIfFList[i].MacAddr, err = iface.GetMACString(); err != nil { - log.Println(err) - } - if h.NetIfFList[i].XML, err = iface.GetXMLDesc(0); err != nil { - log.Println(err) - } - - iface.Free() + func() { + defer ni.Free() + rawxml, err := ni.GetXMLDesc(0) + if err != nil { + log.Error("Host.getIfaceInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + return + } + h.NetIfFList[i] = &libvirtxml.Interface{} + if err = h.NetIfFList[i].Unmarshal(rawxml); err != nil { + log.Error("Host.getIfaceInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + return + } + }() } } } func (h *Host) getNetsInfo() { // getNetsInfo - nets, err := h.conn.ListNetworks() + nets, err := h.conn.ListAllNetworks(0) if err != nil { - log.Println(err) + log.Error("Host.getNetsInfo").Str("hostname", h.HostName).Err(err).Send() } if len(nets) > 0 { - h.NetworkList = make([]NetworkInfo, len(nets)) - for i, netName := range nets { - net, err := h.conn.LookupNetworkByName(netName) - if err != nil { - log.Println(err) - } - if h.NetworkList[i].Name, err = net.GetName(); err != nil { - log.Println(err) - } - if h.NetworkList[i].UUID, err = net.GetUUID(); err != nil { - log.Println(err) - } - if h.NetworkList[i].XML, err = net.GetXMLDesc(0); err != nil { - log.Println(err) - } - if h.NetworkList[i].Active, err = net.IsActive(); err != nil { - log.Println(err) - } - - net.Free() + h.NetworkList = make([]*libvirtxml.Network, len(nets)) + for i, net := range nets { + func() { + defer net.Free() + rawxml, err := net.GetXMLDesc(0) + if err != nil { + log.Error("Host.getNetsInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + return + } + h.NetworkList[i] = &libvirtxml.Network{} + if err = h.NetworkList[i].Unmarshal(rawxml); err != nil { + log.Error("Host.getNetsInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + return + } + }() } } } @@ -557,22 +390,24 @@ func (h *Host) getNetsInfo() { func (h *Host) getDevicesInfo() { ndevs, err := h.conn.ListAllNodeDevices(0) if err != nil { - log.Println(err) + log.Error("Host.getDevicesInfo").Str("hostname", h.HostName).Err(err).Send() } if len(ndevs) > 0 { - h.DeviceList = make([]DeviceInfo, len(ndevs)) + h.DeviceList = make([]*libvirtxml.NodeDevice, len(ndevs)) for i, dev := range ndevs { - if h.DeviceList[i].Name, err = dev.GetName(); err != nil { - log.Println(err) - } - if h.DeviceList[i].Capabilities, err = dev.ListCaps(); err != nil { - log.Println(err) - } - if h.DeviceList[i].XML, err = dev.GetXMLDesc(0); err != nil { - log.Println(err) - } - - dev.Free() + func() { + defer dev.Free() + rawxml, err := dev.GetXMLDesc(0) + if err != nil { + log.Error("Host.getDevicesInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send() + return + } + h.DeviceList[i] = &libvirtxml.NodeDevice{} + if err = h.DeviceList[i].Unmarshal(rawxml); err != nil { + log.Error("Host.getDevicesInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send() + return + } + }() } } } diff --git a/lib/host/uri.go b/lib/host/uri.go index 1abdc65..109344e 100644 --- a/lib/host/uri.go +++ b/lib/host/uri.go @@ -1,8 +1,9 @@ package host import ( - "log" "strings" + + "git.staur.ca/stobbsm/clustvirt/lib/log" ) // URI is a string type, accessed via the pre-defined variables, and represent @@ -72,7 +73,12 @@ func (u *URI) ConnectionString(h string) string { } } } - log.Printf("Connection URI: %s", sb.String()) + log.Info("Host.ConnectionString"). + Str("uri.Driver", u.Driver). + Str("uri.Transport", u.Transport). + Str("uri.Path", u.Path). + Strs("uri.Options", u.Options). + Str("builtUri", sb.String()).Send() return sb.String() } diff --git a/lib/log/logs.go b/lib/log/logs.go new file mode 100644 index 0000000..8b58f28 --- /dev/null +++ b/lib/log/logs.go @@ -0,0 +1,30 @@ +// Package logs provides a central location for ClustVirt logging, wrapping a Zerolog +// instance to do the job. +// This will standarize logging throughout ClustVirt, and make it easier to debug +// issues. +// The default is to log to Stderr +// TODO: enable logging to syslog through configuration +package log + +import ( + "os" + + "github.com/rs/zerolog" +) + +var defaultLogger zerolog.Logger + +func init() { + defaultLogger = zerolog.New(zerolog.ConsoleWriter{ + Out: os.Stderr, + TimeFormat: zerolog.TimeFormatUnix, + }) +} + +func Trace(method string) *zerolog.Event { return defaultLogger.Trace().Str("method", method) } +func Debug(method string) *zerolog.Event { return defaultLogger.Debug().Str("method", method) } +func Info(method string) *zerolog.Event { return defaultLogger.Info().Str("method", method) } +func Warn(method string) *zerolog.Event { return defaultLogger.Warn().Str("method", method) } +func Error(method string) *zerolog.Event { return defaultLogger.Error().Str("method", method) } +func Fatal(method string) *zerolog.Event { return defaultLogger.Fatal().Str("method", method) } +func Panic(method string) *zerolog.Event { return defaultLogger.Panic().Str("method", method) } diff --git a/main.go b/main.go index 9fa5b64..f603846 100644 --- a/main.go +++ b/main.go @@ -1,83 +1,21 @@ package main import ( - "context" - "fmt" - "log" - "net/http" - "git.staur.ca/stobbsm/clustvirt/cluster" - "git.staur.ca/stobbsm/clustvirt/lib/host" - "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" + "git.staur.ca/stobbsm/clustvirt/lib/log" + "git.staur.ca/stobbsm/clustvirt/router/server" ) -const DEBUG bool = true - func main() { - log.Println("Starting clustvirt, the libvirt cluster manager") + log.Info("main").Msg("Starting clustvirt, the libvirt cluster manager") clst := cluster.New(). AddHost("earth.staur.ca"). AddHost("venus.staur.ca"). AddHost("mars.staur.ca"). Build() - - initStats := cluster.InitStats(clst) // Start webserver and serve homepage - defaultNavBar := []components.NavItem{ - {Name: "Cluster", Href: "/"}, - {Name: "Configuration", Href: "/config"}, - {Name: "About", Href: "/about"}, - } - fs := http.StripPrefix("/static/", http.FileServer(http.Dir("public"))) - - r := chi.NewRouter() - r.Use(middleware.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)) + log.Info("main").Msg("starting web server") + r := server.New("127.0.0.1", 3000, clst) + r.Start() } diff --git a/public/css/style.css b/public/css/style.css index d7cee66..c11cd8a 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -962,6 +962,10 @@ span>a:visited { flex-wrap: nowrap; } +.items-end { + align-items: flex-end; +} + .items-center { align-items: center; } @@ -138643,6 +138647,10 @@ span>a:visited { padding-right: 1rem; } +.text-right { + text-align: right; +} + .text-2xl { font-size: 1.5rem; line-height: 2rem; @@ -220221,6 +220229,10 @@ span>a:visited { --tw-ring-offset-color: rgb(51 51 30 / 0.95); } +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + .hover\:border-uipurple-400:hover { --tw-border-opacity: 1; border-color: rgb(227 116 229 / var(--tw-border-opacity)); diff --git a/router/api/api.go b/router/api/api.go new file mode 100644 index 0000000..505e5b6 --- /dev/null +++ b/router/api/api.go @@ -0,0 +1,3 @@ +// Package api defines the routes for the REST API +package api + diff --git a/router/errors.go b/router/errors.go new file mode 100644 index 0000000..6e5ac9a --- /dev/null +++ b/router/errors.go @@ -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") diff --git a/router/htmx/htmx.go b/router/htmx/htmx.go new file mode 100644 index 0000000..3a480e7 --- /dev/null +++ b/router/htmx/htmx.go @@ -0,0 +1,54 @@ +// Package htmx contains the routes for the WebUI 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...) +} diff --git a/router/htmx/routes.go b/router/htmx/routes.go new file mode 100644 index 0000000..cad477c --- /dev/null +++ b/router/htmx/routes.go @@ -0,0 +1,83 @@ +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{ + { + Method: http.MethodGet, + Path: "/cluster", + Handler: func(c *cluster.Cluster) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if err := view.ClusterInfo(c).Render(context.Background(), w); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Error("htmx.Handler"). + Str("uri", r.RequestURI). + Err(err). + Int("statusCode", http.StatusBadRequest).Send() + } + } + }, + }, + { + 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() + } + } + }, + }, + { + 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() + } + } + }, + }, + }, +} diff --git a/router/middleware/fromchi.go b/router/middleware/fromchi.go new file mode 100644 index 0000000..3297203 --- /dev/null +++ b/router/middleware/fromchi.go @@ -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 +) diff --git a/router/middleware/logger.go b/router/middleware/logger.go new file mode 100644 index 0000000..e8a517c --- /dev/null +++ b/router/middleware/logger.go @@ -0,0 +1,29 @@ +package middleware + +import ( + "net/http" + "time" + + "git.staur.ca/stobbsm/clustvirt/lib/log" +) + +// Logger uses the in package log module to handle route logging +func Logger(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + defer func() { + log.Info("router.middleware.Logger"). + Str("httpMethod", r.Method). + Str("host", r.Host). + Str("uri", r.URL.RequestURI()). + Str("user_agent", r.UserAgent()). + Str("referer", r.Referer()). + Strs("transfer-encoding", r.TransferEncoding). + Int64("length", r.ContentLength). + Dur("elasped_ms", time.Since(start)). + Msg("incoming connection") + }() + + next.ServeHTTP(w, r) + }) +} diff --git a/router/router.go b/router/router.go new file mode 100644 index 0000000..1f81aa0 --- /dev/null +++ b/router/router.go @@ -0,0 +1,28 @@ +package router + +import ( + "net/http" + + "git.staur.ca/stobbsm/clustvirt/cluster" + "github.com/go-chi/chi/v5" +) + +// Types that are shared among routers + +// SubRouter defines an interface to be able to add a subrouter to a +// chi router +type SubRouter interface { + MountTo(*cluster.Cluster, chi.Router) error +} + +// Route defines a route that should be added to a chi router or +// subrouter +type Route struct { + Method string + Path string + Handler RouteHandler +} + +// RouteHandler gets the active cluster for the server to inject into +// the http.HandlerFunc that is then returned +type RouteHandler func(*cluster.Cluster) http.HandlerFunc diff --git a/router/server/root.go b/router/server/root.go new file mode 100644 index 0000000..f1d4ed7 --- /dev/null +++ b/router/server/root.go @@ -0,0 +1,21 @@ +package server + +import ( + "net/http" + + "git.staur.ca/stobbsm/clustvirt/view/layouts" + "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(layouts.Manager("ClustVirt", "libvirt made simple")).ServeHTTP) + s.r.Get("/about", templ.Handler(static.About()).ServeHTTP) +} diff --git a/router/server/server.go b/router/server/server.go new file mode 100644 index 0000000..8ac34c8 --- /dev/null +++ b/router/server/server.go @@ -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) +} diff --git a/util/pcidb.go b/util/pcidb.go new file mode 100644 index 0000000..0681701 --- /dev/null +++ b/util/pcidb.go @@ -0,0 +1,46 @@ +package util + +import ( + "git.staur.ca/stobbsm/clustvirt/lib/log" + "github.com/jaypipes/pcidb" +) + +var ( + pcidbInitDone = false + db *pcidb.PCIDB +) + +const ( + pcidbNOTFOUND string = `NOTFOUND` + pcidbNODB string = `NODBFOUND` +) + +func initPCIDB() { + var err error + + // Attempt to use local sources first, fallback to network if + // local sources aren't found + db, err = pcidb.New() + if err != nil { + log.Warn("util.initPCIDB").Err(err).Msg("fallback to downloading pcidb") + db, err = pcidb.New(pcidb.WithEnableNetworkFetch()) + if err != nil { + log.Error("util.initPCIDB").Err(err).Msg("no more fallbacks available") + } + } + pcidbInitDone = true +} + +func GetPCIClass(id string) string { + if !pcidbInitDone { + initPCIDB() + } + if pcidbInitDone && db == nil { + log.Warn("util.GetPCIClass").Msg("no pcidb to do lookup") + return pcidbNODB + } + if class, ok := db.Classes[id]; ok { + return class.Name + } + return pcidbNOTFOUND +} diff --git a/view/cluster.templ b/view/cluster.templ index fcf0904..0a4ef3b 100644 --- a/view/cluster.templ +++ b/view/cluster.templ @@ -3,55 +3,49 @@ package view import ( "fmt" "git.staur.ca/stobbsm/clustvirt/cluster" - "git.staur.ca/stobbsm/clustvirt/view/components" - "git.staur.ca/stobbsm/clustvirt/view/layouts" ) -templ ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) { - @layouts.Manager("ClustVirt", "Cluster Manager", navbar) { -

Cluster Stats

- - - - - - - - - - - - - - - - - - - - - - - - -
- CPU stats -
SocketsCoresThreadsAllocated
- { fmt.Sprint(cs.CPU.Sockets) } - - { fmt.Sprint(cs.CPU.Cores) } - - { fmt.Sprint(cs.CPU.Threads) } - - { fmt.Sprint(cs.CPU.Allocated) } -
- { fmt.Sprint(diff.CPU.Sockets) } - - { fmt.Sprint(diff.CPU.Cores) } - - { fmt.Sprint(diff.CPU.Threads) } - - { fmt.Sprint(diff.CPU.Allocated) } -
- } +templ ClusterInfo(c *cluster.Cluster) { +

Cluster Stats

+ @ClusterStats(cluster.InitStats(c)) +} + +templ ClusterStats(cs *cluster.ClusterStats) { + @CPUStats(cs.CPU, cs.Diff().CPU) +} + +templ CPUStats(stats cluster.CPUStats, diff cluster.CPUDiff) { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ CPU stats +
SocketsCoresThreadsAllocatedMHz
Latest{ fmt.Sprint(stats.Sockets) }{ fmt.Sprint(stats.Cores) }{ fmt.Sprint(stats.Threads) }{ fmt.Sprint(stats.Allocated) }{ fmt.Sprint(stats.MHz) }
Change{ fmt.Sprint(diff.Sockets) }{ fmt.Sprint(diff.Cores) }{ fmt.Sprint(diff.Threads) }{ fmt.Sprint(diff.Allocated) }{ fmt.Sprint(diff.MHz) }
} diff --git a/view/cluster_templ.go b/view/cluster_templ.go index 7caa7de..ba651be 100644 --- a/view/cluster_templ.go +++ b/view/cluster_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package view //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -13,11 +13,9 @@ import "bytes" import ( "fmt" "git.staur.ca/stobbsm/clustvirt/cluster" - "git.staur.ca/stobbsm/clustvirt/view/components" - "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) { templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) if !templ_7745c5c3_IsBuffer { @@ -30,160 +28,229 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Cluster Stats

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 = []any{"table-auto", "w-full"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) - 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 - } - var templ_7745c5c3_Var4 = []any{"caption-top"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
CPU stats
SocketsCoresThreadsAllocated
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, 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: 27, Col: 35} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - 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 - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Cores)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 30, 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("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Threads)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 33, Col: 35} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) - 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 - } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Allocated)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 36, Col: 37} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - 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 - } - var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Sockets)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 41, Col: 42} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) - 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 - } - var templ_7745c5c3_Var10 string - templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Cores)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 44, Col: 40} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) - 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 - } - var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Threads)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 47, Col: 42} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) - 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 - } - var templ_7745c5c3_Var12 string - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Allocated)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 50, Col: 44} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) - 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 - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Cluster Stats

") + if templ_7745c5c3_Err != nil { 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 = ClusterStats(cluster.InitStats(c)).Render(ctx, templ_7745c5c3_Buffer) + 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 ClusterStats(cs *cluster.ClusterStats) 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_Var2 := templ.GetChildren(ctx) + if templ_7745c5c3_Var2 == nil { + templ_7745c5c3_Var2 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = CPUStats(cs.CPU, cs.Diff().CPU).Render(ctx, templ_7745c5c3_Buffer) + 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_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + var templ_7745c5c3_Var4 = []any{"table-auto", "w-full", "text-right"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) + 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 + } + var templ_7745c5c3_Var6 = []any{"caption-top"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
CPU stats
SocketsCoresThreadsAllocatedMHz
Latest") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Sockets)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 35, Col: 35} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + 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 + } + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Cores)) + 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_Var9)) + 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 + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Threads)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 37, Col: 35} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) + 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 + } + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Allocated)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 38, Col: 37} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) + 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 + } + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.MHz)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 39, Col: 31} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Change") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Sockets)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 43, Col: 34} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) + 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 + } + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Cores)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 44, Col: 32} + } + _, 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("") + 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.Threads)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 45, Col: 34} + } + _, 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("") + 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.Allocated)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 46, Col: 36} + } + _, 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("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var17 string + templ_7745c5c3_Var17, 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: 47, Col: 30} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) + 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 } diff --git a/view/components/anchor_templ.go b/view/components/anchor_templ.go index 503c026..a7292c5 100644 --- a/view/components/anchor_templ.go +++ b/view/components/anchor_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -39,7 +39,7 @@ func A(href string, text string) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(text) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 4, Col: 10} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 5, Col: 10} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -85,7 +85,7 @@ func ANewTab(href string, text string) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(text) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 10, Col: 10} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 11, Col: 10} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { diff --git a/view/components/contentlist_templ.go b/view/components/contentlist_templ.go index 04b8d82..30af8cf 100644 --- a/view/components/contentlist_templ.go +++ b/view/components/contentlist_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -36,7 +36,12 @@ func List(listImage string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/contentlist.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -67,16 +72,16 @@ func ListItem() templ.Component { defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templ.GetChildren(ctx) - if templ_7745c5c3_Var3 == nil { - templ_7745c5c3_Var3 = templ.NopComponent + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = templ_7745c5c3_Var4.Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/components/contentp_templ.go b/view/components/contentp_templ.go index 17a6802..3751a00 100644 --- a/view/components/contentp_templ.go +++ b/view/components/contentp_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/view/components/defaults.go b/view/components/defaults.go new file mode 100644 index 0000000..23d9039 --- /dev/null +++ b/view/components/defaults.go @@ -0,0 +1,7 @@ +package components + +var DefaultNavBar = []NavItem{ + {Name: "Cluster", Href: "/"}, + {Name: "Configuration", Href: "/config"}, + {Name: "About", Href: "/about"}, +} diff --git a/view/components/flexrow_templ.go b/view/components/flexrow_templ.go index c0534a3..f3e8d6b 100644 --- a/view/components/flexrow_templ.go +++ b/view/components/flexrow_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -36,7 +36,12 @@ func FlexRow(wrap bool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/flexrow.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/components/hero_templ.go b/view/components/hero_templ.go index 30f35c8..1ad40df 100644 --- a/view/components/hero_templ.go +++ b/view/components/hero_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/view/components/hostbutton.templ b/view/components/hostbutton.templ new file mode 100644 index 0000000..e1c86b7 --- /dev/null +++ b/view/components/hostbutton.templ @@ -0,0 +1,46 @@ +package components + +templ HostButton(hostname string, path string) { + +} + +templ HostNav() { +
    +
      +
    • + @HostButton("Cluster View", "/htmx/cluster") +
    • +
    • + @HostButton("venus.staur.ca", "/htmx/host/venus.staur.ca") +
    • +
    • + @HostButton("earth.staur.ca", "/htmx/host/earth.staur.ca") +
    • +
    • + @HostButton("mars.staur.ca", "/htmx/host/mars.staur.ca") +
    • +
    +
    +} diff --git a/view/components/hostbutton_templ.go b/view/components/hostbutton_templ.go new file mode 100644 index 0000000..bae11d2 --- /dev/null +++ b/view/components/hostbutton_templ.go @@ -0,0 +1,212 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.646 +package components + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +func HostButton(hostname string, path string) 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_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + var templ_7745c5c3_Var2 = []any{"rounded", + "border", + "border-solid", + "border-uiblue-700", + "text-uigrey-200", + "bg-uiblue-800", + "hover:border-uipurple-400", + "hover:text-ui-grey-800", + "hover:bg-uipurple-600", + "gap-2", + "p-1", + "my-1", + "w-full", + "flex", + "flex-row", + "justify-between"} + 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 + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func HostNav() 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_Var10 := templ.GetChildren(ctx) + if templ_7745c5c3_Var10 == nil { + templ_7745c5c3_Var10 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + var templ_7745c5c3_Var11 = []any{"w-1/6", "border-uigrey-600", "border", "rounded", "border-dotted", "p-2"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...) + 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 = HostButton("Cluster View", "/htmx/cluster").Render(ctx, templ_7745c5c3_Buffer) + 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 = HostButton("venus.staur.ca", "/htmx/host/venus.staur.ca").Render(ctx, templ_7745c5c3_Buffer) + 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 = HostButton("earth.staur.ca", "/htmx/host/earth.staur.ca").Render(ctx, templ_7745c5c3_Buffer) + 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 = HostButton("mars.staur.ca", "/htmx/host/mars.staur.ca").Render(ctx, templ_7745c5c3_Buffer) + 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 + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} diff --git a/view/components/infobox_templ.go b/view/components/infobox_templ.go index e501b8d..16b8027 100644 --- a/view/components/infobox_templ.go +++ b/view/components/infobox_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -48,7 +48,12 @@ func InfoBox(title string, colour string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -56,12 +61,12 @@ func InfoBox(title string, colour string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title) + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 20, Col: 43} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 21, Col: 43} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/components/navbar_templ.go b/view/components/navbar_templ.go index 46f63cf..afe5c09 100644 --- a/view/components/navbar_templ.go +++ b/view/components/navbar_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package components //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -38,7 +38,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -46,7 +51,7 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 = []any{"md:h-16", + var templ_7745c5c3_Var4 = []any{"md:h-16", "h-28", "mx-auto", "md:px-4", @@ -56,7 +61,7 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { "justify-between", "flex-wrap", "md:flex-nowrap"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -64,7 +69,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String())) + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -80,8 +90,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 = []any{"text-uigrey-200", "font-semibold", "md:w-auto", "md:order-2", "order-3"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) + var templ_7745c5c3_Var6 = []any{"text-uigrey-200", "font-semibold", "md:w-auto", "md:order-2", "order-3"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -89,7 +99,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String())) + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -97,8 +112,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var5 = []any{"flex", "justify-between", "sm:w-full", "md:w-auto"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) + var templ_7745c5c3_Var8 = []any{"flex", "justify-between", "sm:w-full", "md:w-auto"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -106,7 +121,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String())) + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -115,8 +135,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { return templ_7745c5c3_Err } for _, ni := range navItems { - var templ_7745c5c3_Var6 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) + var templ_7745c5c3_Var10 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -124,7 +144,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var6).String())) + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var10).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -132,8 +157,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 templ.SafeURL = templ.URL(ni.Href) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7))) + var templ_7745c5c3_Var12 templ.SafeURL = templ.URL(ni.Href) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12))) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -141,12 +166,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(ni.Name) + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(ni.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 31, Col: 47} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 32, Col: 47} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -159,8 +184,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 = []any{"order-2", "md:order-3"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...) + var templ_7745c5c3_Var14 = []any{"order-2", "md:order-3"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -168,7 +193,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var9).String())) + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var14).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/hostinfo.templ b/view/hostinfo.templ index 9d9e052..48ad152 100644 --- a/view/hostinfo.templ +++ b/view/hostinfo.templ @@ -3,8 +3,6 @@ package view import ( "fmt" "git.staur.ca/stobbsm/clustvirt/lib/host" - "git.staur.ca/stobbsm/clustvirt/view/components" - "git.staur.ca/stobbsm/clustvirt/view/layouts" ) script memchart(used uint64, free uint64, buf uint64, cache uint64) { @@ -56,58 +54,8 @@ templ MemChart(h *host.Host) { h.NodeMemory.Buffers, h.NodeMemory.Cached) } -templ hostButton(hostname string) { - -} - // HostConnect is the page that allows us to select a host to get information from -templ HostMain(navBarItems []components.NavItem) { - @layouts.Manager("ClustVirt", "Cluster Manager", navBarItems) { -
    -
    -
      -
    • - @hostButton("venus.staur.ca") -
    • -
    • - @hostButton("earth.staur.ca") -
    • -
    • - @hostButton("mars.staur.ca") -
    • -
    -
    -
    -

    This is where you can see a system overview of all available hosts

    -

    - For now, there is just this simple box to choose a host to connect to - and push the button to load the system information via HTMX -

    -
    -
    - } +templ HostMain() { } // HostInfo is meant to be an HTMX response @@ -123,11 +71,11 @@ templ HostInfo(h *host.Host) {
    - @SysInfo(h) + @HostStats(h)
    } -templ SysInfo(h *host.Host) { +templ HostStats(h *host.Host) { @MemChart(h) } diff --git a/view/hostinfo_templ.go b/view/hostinfo_templ.go index 3bb5d56..06e7c21 100644 --- a/view/hostinfo_templ.go +++ b/view/hostinfo_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package view //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -13,8 +13,6 @@ import "bytes" import ( "fmt" "git.staur.ca/stobbsm/clustvirt/lib/host" - "git.staur.ca/stobbsm/clustvirt/view/components" - "git.staur.ca/stobbsm/clustvirt/view/layouts" ) func memchart(used uint64, free uint64, buf uint64, cache uint64) templ.ComponentScript { @@ -78,24 +76,12 @@ func MemChart(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 = []any{"size-40", "md:size-80"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) - 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 + } + var templ_7745c5c3_Var6 = []any{"size-40", "md:size-80"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) + 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 - } - var templ_7745c5c3_Var11 = []any{"px-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...) - 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 - } - var templ_7745c5c3_Var12 string - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(hostname) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 79, Col: 35} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) - 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 - } - var templ_7745c5c3_Var13 = []any{"htmx-indicator", "inline-block", "h-6", "px-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var13...) - 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 - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) - } - return templ_7745c5c3_Err - }) -} - // HostConnect is the page that allows us to select a host to get information from -func HostMain(navBarItems []components.NavItem) templ.Component { +func HostMain() 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 { @@ -300,101 +206,11 @@ func HostMain(navBarItems []components.NavItem) templ.Component { defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var14 := templ.GetChildren(ctx) - if templ_7745c5c3_Var14 == nil { - templ_7745c5c3_Var14 = templ.NopComponent + templ_7745c5c3_Var12 := templ.GetChildren(ctx) + if templ_7745c5c3_Var12 == nil { + templ_7745c5c3_Var12 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var15 := 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) - } - var templ_7745c5c3_Var16 = []any{"flex", "flex-row", "h-full", "mt-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...) - 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 - } - var templ_7745c5c3_Var17 = []any{"w-1/6", "border-uigrey-600", "border", "rounded", "border-dotted", "p-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var17...) - 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 = hostButton("venus.staur.ca").Render(ctx, templ_7745c5c3_Buffer) - 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 = hostButton("earth.staur.ca").Render(ctx, templ_7745c5c3_Buffer) - 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 = hostButton("mars.staur.ca").Render(ctx, templ_7745c5c3_Buffer) - 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 - } - var templ_7745c5c3_Var18 = []any{"w-3/4", "px-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

    This is where you can see a system overview of all available hosts

    For now, there is just this simple box to choose a host to connect to and push the button to load the system information via HTMX

    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = layouts.Manager("ClustVirt", "Cluster Manager", navBarItems).Render(templ.WithChildren(ctx, templ_7745c5c3_Var15), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } if !templ_7745c5c3_IsBuffer { _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) } @@ -411,13 +227,13 @@ func HostInfo(h *host.Host) templ.Component { defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var19 := templ.GetChildren(ctx) - if templ_7745c5c3_Var19 == nil { - templ_7745c5c3_Var19 = templ.NopComponent + templ_7745c5c3_Var13 := templ.GetChildren(ctx) + if templ_7745c5c3_Var13 == nil { + templ_7745c5c3_Var13 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var20 = []any{"flex", "flex-col"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...) + var templ_7745c5c3_Var14 = []any{"flex", "flex-col"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -425,7 +241,12 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var20).String())) + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var14).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -433,8 +254,8 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var21 = []any{"flex", "flex-row", "justify-start", "px-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var21...) + var templ_7745c5c3_Var16 = []any{"flex", "flex-row", "justify-start", "px-2"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -442,7 +263,12 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var21).String())) + var templ_7745c5c3_Var17 string + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var16).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -450,7 +276,12 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(fmt.Sprintf("/htmx/host/%s/stats", h.HostName))) + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/htmx/host/%s/stats", h.HostName)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 67, Col: 58} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -458,12 +289,12 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var22 string - templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(h.HostName) + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(h.HostName) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 121, Col: 19} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 70, Col: 19} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -471,8 +302,8 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var23 = []any{"h-6", "px-2", "htmx-indicator", "inline-block"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var23...) + var templ_7745c5c3_Var20 = []any{"h-6", "px-2", "htmx-indicator", "inline-block"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -480,7 +311,12 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var23).String())) + var templ_7745c5c3_Var21 string + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var20).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -488,8 +324,8 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var24 = []any{"flex", "flex-row", "flex-wrap"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var24...) + var templ_7745c5c3_Var22 = []any{"flex", "flex-row", "flex-wrap"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var22...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -497,7 +333,12 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var24).String())) + var templ_7745c5c3_Var23 string + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var22).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -505,7 +346,7 @@ func HostInfo(h *host.Host) templ.Component { if templ_7745c5c3_Err != nil { 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 { return templ_7745c5c3_Err } @@ -520,7 +361,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) { templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) if !templ_7745c5c3_IsBuffer { @@ -528,9 +369,9 @@ func SysInfo(h *host.Host) templ.Component { defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var25 := templ.GetChildren(ctx) - if templ_7745c5c3_Var25 == nil { - templ_7745c5c3_Var25 = templ.NopComponent + templ_7745c5c3_Var24 := templ.GetChildren(ctx) + if templ_7745c5c3_Var24 == nil { + templ_7745c5c3_Var24 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = MemChart(h).Render(ctx, templ_7745c5c3_Buffer) diff --git a/view/layouts/manager.templ b/view/layouts/manager.templ index 0c294f0..cbaee2b 100644 --- a/view/layouts/manager.templ +++ b/view/layouts/manager.templ @@ -2,20 +2,25 @@ package layouts import "git.staur.ca/stobbsm/clustvirt/view/components" -templ Manager(title string, subtitle string, navBarItem []components.NavItem) { +templ Manager(title string, subtitle string) { - ClustVirt + { title } - { subtitle }
    - @header(title, subtitle, navBarItem) + @header(title, subtitle, components.DefaultNavBar)
    - { children... } +
    + @components.HostNav() +
    + +
    +
    @footer() diff --git a/view/layouts/manager_templ.go b/view/layouts/manager_templ.go index e47d6b3..7bf0f4a 100644 --- a/view/layouts/manager_templ.go +++ b/view/layouts/manager_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package layouts //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -12,7 +12,7 @@ import "bytes" import "git.staur.ca/stobbsm/clustvirt/view/components" -func Manager(title string, subtitle string, navBarItem []components.NavItem) templ.Component { +func Manager(title string, subtitle string) 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 { @@ -38,16 +38,47 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">ClustVirt") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 = []any{"flex", "flex-col", "h-screen"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 9, Col: 17} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + 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 + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 9, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + 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 + } + var templ_7745c5c3_Var6 = []any{"flex", "flex-col", "h-screen"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -55,7 +86,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String())) + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -63,8 +99,8 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 = []any{"px-4"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) + var templ_7745c5c3_Var8 = []any{"px-4"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -72,7 +108,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String())) + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -80,7 +121,7 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = header(title, subtitle, navBarItem).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = header(title, subtitle, components.DefaultNavBar).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -88,8 +129,8 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var5 = []any{"px-4", "h-full"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) + var templ_7745c5c3_Var10 = []any{"px-4", "h-full"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -97,7 +138,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String())) + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var10).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -105,16 +151,78 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) + var templ_7745c5c3_Var12 = []any{"flex", "flex-row", "h-full", "mt-2"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...) 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 + } + templ_7745c5c3_Err = components.HostNav().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var14 = []any{"w-3/4", "px-2"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...) + 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 + } + var templ_7745c5c3_Var16 = []any{"inline-block"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...) + 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 + } + var templ_7745c5c3_Var18 = []any{"px-4", "bottom-0", "w-full", "justify-self-end"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -122,7 +230,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var6).String())) + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var18).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/layouts/staticpage_templ.go b/view/layouts/staticpage_templ.go index 5b30e19..8c8032c 100644 --- a/view/layouts/staticpage_templ.go +++ b/view/layouts/staticpage_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package layouts //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -38,7 +38,12 @@ func StaticPage(title string, subtitle string, navBarItems []components.NavItem) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String())) + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -54,8 +59,8 @@ func StaticPage(title string, subtitle string, navBarItems []components.NavItem) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var3 = []any{"flex", "flex-col", "gap-2"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) + var templ_7745c5c3_Var4 = []any{"flex", "flex-col", "gap-2"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -63,7 +68,12 @@ func StaticPage(title string, subtitle string, navBarItems []components.NavItem) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String())) + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -102,13 +112,13 @@ func hero(title string) templ.Component { 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 + templ_7745c5c3_Var6 := templ.GetChildren(ctx) + if templ_7745c5c3_Var6 == nil { + templ_7745c5c3_Var6 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var5 = []any{"text-2xl", "font-bold", "text-uiblue-200", "md:order-1"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) + var templ_7745c5c3_Var7 = []any{"text-2xl", "font-bold", "text-uiblue-200", "md:order-1"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -116,7 +126,12 @@ func hero(title string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String())) + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var7).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -124,12 +139,12 @@ func hero(title string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(title) + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 26, Col: 80} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 27, Col: 80} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -152,13 +167,13 @@ func header(title string, subtitle string, navBarItems []components.NavItem) tem defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var7 := templ.GetChildren(ctx) - if templ_7745c5c3_Var7 == nil { - templ_7745c5c3_Var7 = templ.NopComponent + templ_7745c5c3_Var10 := templ.GetChildren(ctx) + if templ_7745c5c3_Var10 == nil { + templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var8 = []any{"text-lg", "font-semibold", "italic", "h-6"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) + var templ_7745c5c3_Var11 = []any{"text-lg", "font-semibold", "italic", "h-6"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -166,7 +181,12 @@ func header(title string, subtitle string, navBarItems []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var8).String())) + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -174,12 +194,12 @@ func header(title string, subtitle string, navBarItems []components.NavItem) tem if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle) + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 30, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 31, Col: 72} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -206,9 +226,9 @@ func footer() templ.Component { defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var10 := templ.GetChildren(ctx) - if templ_7745c5c3_Var10 == nil { - templ_7745c5c3_Var10 = templ.NopComponent + templ_7745c5c3_Var14 := templ.GetChildren(ctx) + if templ_7745c5c3_Var14 == nil { + templ_7745c5c3_Var14 = templ.NopComponent } ctx = templ.ClearChildren(ctx) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
    Left
    Middle
    Right
    ") diff --git a/view/static/home.templ b/view/static/home.templ index 5575c48..ee4faeb 100644 --- a/view/static/home.templ +++ b/view/static/home.templ @@ -5,7 +5,7 @@ import ( "git.staur.ca/stobbsm/clustvirt/view/components" ) -templ Home() { +templ About() { @layouts.StaticPage("ClustVirt", "Libvirt, clustered and managed", []components.NavItem{ {Name: "What", Href: "#"}, {Name: "Why", Href: "#"}, diff --git a/view/static/home_templ.go b/view/static/home_templ.go index 13c3c03..bd93566 100644 --- a/view/static/home_templ.go +++ b/view/static/home_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.2.598 +// templ: version: v0.2.646 package static //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -15,7 +15,7 @@ import ( "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) { templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) if !templ_7745c5c3_IsBuffer { @@ -53,7 +53,12 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String())) + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/static/home.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -61,7 +66,7 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Var5 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var6 := 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() @@ -76,7 +81,7 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -97,48 +102,25 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Var6 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var7 := 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) } - templ_7745c5c3_Var7 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var8 := 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) } - templ_7745c5c3_Var8 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Broadcom buying VMWare, and VMWare losing a free teir for homelabbers pissed me off") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer) - 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_Var9 := 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) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Vendor lock-in pisses me off") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Broadcom buying VMWare, and VMWare losing a free teir for homelabbers pissed me off") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -161,7 +143,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Even good open source Hyperconverged systems (Proxmox, as an example) exhibit a form of vendor lock-in") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Vendor lock-in pisses me off") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -184,7 +166,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Libvirt is terrific, has the functionality for everything those other providers do, but there really is not a great option for those dipping their toes into Open Source") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Even good open source Hyperconverged systems (Proxmox, as an example) exhibit a form of vendor lock-in") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -207,7 +189,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Its fun to build things that solve a need") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Libvirt is terrific, has the functionality for everything those other providers do, but there really is not a great option for those dipping their toes into Open Source") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -230,7 +212,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("I really want to do it") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Its fun to build things that solve a need") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -243,47 +225,17 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.List("informational").Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.InfoBox("Why?", "uiblue").Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) - 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_Var14 := 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) - } - templ_7745c5c3_Var15 := 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) - } - templ_7745c5c3_Var16 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var14 := 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) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Open source, currently on the MIT license") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("I really want to do it") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -292,13 +244,43 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var16), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var14), templ_7745c5c3_Buffer) 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 + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.List("informational").Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.InfoBox("Why?", "uiblue").Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer) + 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_Var15 := 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) + } + templ_7745c5c3_Var16 := 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) } templ_7745c5c3_Var17 := 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) @@ -306,7 +288,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Base OS Agnostic. If it can run libvirtd, this should be able to control it on some level") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Open source, currently on the MIT license") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -329,7 +311,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Control the Virtual Machine life cycle on one or more libvirtd hosts") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Base OS Agnostic. If it can run libvirtd, this should be able to control it on some level") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -352,7 +334,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Add clusting capabilities to libvirtd host, including;") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Control the Virtual Machine life cycle on one or more libvirtd hosts") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -375,7 +357,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Migration of VMs") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Add clusting capabilities to libvirtd host, including;") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -398,7 +380,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Syncronizing secrets") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Migration of VMs") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -421,7 +403,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Syncronizing VLANs, bridges, host only networking") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Syncronizing secrets") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -444,7 +426,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Sharing HA storage availability") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Syncronizing VLANs, bridges, host only networking") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -467,7 +449,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Locking shared resources like disks") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Sharing HA storage availability") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -490,7 +472,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Starting VMs marked for HA on another host when one goes down") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Locking shared resources like disks") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -513,7 +495,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Manage a library of Cloud-init resources and templates to build new VMs quickly") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Starting VMs marked for HA on another host when one goes down") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -536,7 +518,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Local Storage management, including local directory, lvm, zfs (if installed)") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Manage a library of Cloud-init resources and templates to build new VMs quickly") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -559,7 +541,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Advanced Storage management, such as Ceph, glusterfs, drbd, iscsi, nfs") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Local Storage management, including local directory, lvm, zfs (if installed)") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -582,7 +564,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Storage syncronization of local disks between hosts (zfs snapshots, lvm snapshots, rsync)") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Advanced Storage management, such as Ceph, glusterfs, drbd, iscsi, nfs") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -605,7 +587,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Backup scheduling, creation, restoration") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Storage syncronization of local disks between hosts (zfs snapshots, lvm snapshots, rsync)") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -618,47 +600,17 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.List("accepted").Render(templ.WithChildren(ctx, templ_7745c5c3_Var15), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.InfoBox("Project Goals", "uigreen").Render(templ.WithChildren(ctx, templ_7745c5c3_Var14), templ_7745c5c3_Buffer) - 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_Var31 := 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) - } - templ_7745c5c3_Var32 := 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) - } - templ_7745c5c3_Var33 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var31 := 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) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Install the OS which libvirtd is running on") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Backup scheduling, creation, restoration") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -667,13 +619,43 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var33), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var31), templ_7745c5c3_Buffer) 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 + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.List("accepted").Render(templ.WithChildren(ctx, templ_7745c5c3_Var16), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.InfoBox("Project Goals", "uigreen").Render(templ.WithChildren(ctx, templ_7745c5c3_Var15), templ_7745c5c3_Buffer) + 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_Var32 := 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) + } + templ_7745c5c3_Var33 := 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) } templ_7745c5c3_Var34 := 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) @@ -681,7 +663,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Install/provision libvirtd on a host that does not have it installed") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Install the OS which libvirtd is running on") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -704,7 +686,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Tools to move from one vendor to clustvirt/libvirtd") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Install/provision libvirtd on a host that does not have it installed") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -727,7 +709,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("VM templates for common aspects of VM creation and management, like appliances") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Tools to move from one vendor to clustvirt/libvirtd") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -750,7 +732,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("External tool access that can be used to manage things that are not managed here (cephadm dashboard, for instance)") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("VM templates for common aspects of VM creation and management, like appliances") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -763,47 +745,17 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.List("possible").Render(templ.WithChildren(ctx, templ_7745c5c3_Var32), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.InfoBox("Stretch Goals", "uipurple").Render(templ.WithChildren(ctx, templ_7745c5c3_Var31), templ_7745c5c3_Buffer) - 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_Var38 := 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) - } - templ_7745c5c3_Var39 := 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) - } - templ_7745c5c3_Var40 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var38 := 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) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Search/Filter on hosts/vms - @Lopsided_Speaker_553") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("External tool access that can be used to manage things that are not managed here (cephadm dashboard, for instance)") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -812,13 +764,43 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var40), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var38), templ_7745c5c3_Buffer) 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 + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.List("possible").Render(templ.WithChildren(ctx, templ_7745c5c3_Var33), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.InfoBox("Stretch Goals", "uipurple").Render(templ.WithChildren(ctx, templ_7745c5c3_Var32), templ_7745c5c3_Buffer) + 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_Var39 := 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) + } + templ_7745c5c3_Var40 := 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) } templ_7745c5c3_Var41 := 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) @@ -826,7 +808,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Balance on resource usage per host/Automattically migrate to least used host - @Lopsided_Speaker_553") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Search/Filter on hosts/vms - @Lopsided_Speaker_553") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -849,7 +831,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Support inter-vm only commmunication (VxLAN style) - @Lopsided_Speaker_553") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Balance on resource usage per host/Automattically migrate to least used host - @Lopsided_Speaker_553") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -872,7 +854,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Deploy VMs using only API - @Lopsided_Speaker_553") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Support inter-vm only commmunication (VxLAN style) - @Lopsided_Speaker_553") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -895,7 +877,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Well documented, first class API - @kasperlitheater") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Deploy VMs using only API - @Lopsided_Speaker_553") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -918,7 +900,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Bootstrap service to configure a new server - @phatpappa_") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Well documented, first class API - @kasperlitheater") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -941,7 +923,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("For the love of kitten, don't use XML as configuration files - @pascalbrax") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Bootstrap service to configure a new server - @phatpappa_") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -964,7 +946,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Expose the Cluster Manager functionalities as API - @raven2611") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("For the love of kitten, don't use XML as configuration files - @pascalbrax") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -987,7 +969,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("CPU architecture awareness for migrations - @raven2611") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Expose the Cluster Manager functionalities as API - @raven2611") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1010,7 +992,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Inter VM Communications via VXLAN/EVPN - @raven2611") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("CPU architecture awareness for migrations - @raven2611") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1023,12 +1005,35 @@ func Home() templ.Component { 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_Var50 := 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) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Inter VM Communications via VXLAN/EVPN - @raven2611") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var50), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } if !templ_7745c5c3_IsBuffer { _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.List("possible").Render(templ.WithChildren(ctx, templ_7745c5c3_Var39), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.List("possible").Render(templ.WithChildren(ctx, templ_7745c5c3_Var40), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1037,7 +1042,7 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.InfoBox("Reddit Requested Feature", "uiyellow").Render(templ.WithChildren(ctx, templ_7745c5c3_Var38), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.InfoBox("Reddit Requested Feature", "uiyellow").Render(templ.WithChildren(ctx, templ_7745c5c3_Var39), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1045,8 +1050,8 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var50 = []any{} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var50...) + var templ_7745c5c3_Var51 = []any{} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var51...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1054,7 +1059,12 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var50).String())) + var templ_7745c5c3_Var52 string + templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var51).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/static/home.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1062,71 +1072,25 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Var51 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var53 := 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) } - templ_7745c5c3_Var52 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var54 := 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) } - templ_7745c5c3_Var53 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Kubernetes") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var53), templ_7745c5c3_Buffer) - 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_Var54 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Application container management (docker, podman, etc)") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var54), templ_7745c5c3_Buffer) - 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_Var55 := 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) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Become an OS") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Kubernetes") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1149,7 +1113,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Have a paywall") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Application container management (docker, podman, etc)") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1172,7 +1136,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Vendor lock-in") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Become an OS") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1195,7 +1159,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Become a commercial entity (even indirectly)") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Have a paywall") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1218,7 +1182,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Anything that does not have an Open Source standard behind it") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Vendor lock-in") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1241,7 +1205,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Directly control a guest Operating System") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Become a commercial entity (even indirectly)") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1254,12 +1218,58 @@ func Home() templ.Component { 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_Var61 := 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) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Anything that does not have an Open Source standard behind it") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var61), templ_7745c5c3_Buffer) + 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_Var62 := 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) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Directly control a guest Operating System") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.ListItem().Render(templ.WithChildren(ctx, templ_7745c5c3_Var62), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } if !templ_7745c5c3_IsBuffer { _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.List("never").Render(templ.WithChildren(ctx, templ_7745c5c3_Var52), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.List("never").Render(templ.WithChildren(ctx, templ_7745c5c3_Var54), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1268,7 +1278,7 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.InfoBox("Never Going to Happen", "uired").Render(templ.WithChildren(ctx, templ_7745c5c3_Var51), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.InfoBox("Never Going to Happen", "uired").Render(templ.WithChildren(ctx, templ_7745c5c3_Var53), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1276,14 +1286,14 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Var61 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var63 := 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) } - var templ_7745c5c3_Var62 = []any{"flex", "flex-col", "gap-4", "mx-4"} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var62...) + var templ_7745c5c3_Var64 = []any{"flex", "flex-col", "gap-4", "mx-4"} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var64...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1291,7 +1301,12 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var62).String())) + var templ_7745c5c3_Var65 string + templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var64).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/static/home.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1299,7 +1314,7 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Var63 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var66 := 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() @@ -1322,63 +1337,6 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var63), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Var64 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Besides the list above about why this exists, I wanted to clarify a few things those individuals did not seeem to get: This is not a rebuild of Proxmox, Cloudstack, VMWare, Harvester or any of the other \"Hyper-converged/Single-solution/turnkey/Operating System\" offerings out there. This will not take over your base operating system on your machine, just act as a cluster manager and interface to access the existing libvirtd instances on those machines, nor will it prescribe a set of requirements that make it hard to move your own infrastructure around.") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var64), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Var65 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("At the heart of this project is that I hate the enshitifiation of Open Source that has been going on, where its just another way to make money and control the eco system. RedHat tried to do it by locking down their source code, Proxmox does it by making sure anything you do on Proxmox is tied to Proxmox (no offense to Proxmox), and even Hashicorp, who I loved so dearly, changed from a pure Open Source licensing model to one that protects the business over the community") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) - templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var65), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Var66 := 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) - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("I will not let that happen here.") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) - } - return templ_7745c5c3_Err - }) templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var66), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -1389,7 +1347,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("This project will seek to use the Unix philosophy, of building off of existing standards, combining tools, and having one tool do one job well. This does not mean there will be one application for each aspect of the job, but that this application stack will manage Libvirtd well, and have individual and configurable paths to manage each sub-aspect of the libvirt stack. This stack will not create a Ceph cluster for you, it leaves you to do that. It will not even talk to a ceph cluster. It will, however, let you add that cluster via configuration options to define it as a storage pool that libvirt can use.") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Besides the list above about why this exists, I wanted to clarify a few things those individuals did not seeem to get: This is not a rebuild of Proxmox, Cloudstack, VMWare, Harvester or any of the other \"Hyper-converged/Single-solution/turnkey/Operating System\" offerings out there. This will not take over your base operating system on your machine, just act as a cluster manager and interface to access the existing libvirtd instances on those machines, nor will it prescribe a set of requirements that make it hard to move your own infrastructure around.") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1408,7 +1366,7 @@ func Home() templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("If you want something that will allow you to use a single interface to create all sub aspects that can be used by libvirt (managing all firewall rules, creating a ceph cluster, etc.), use something like Proxmox which includes that builtin functionality. This isn't the stack for you.") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("At the heart of this project is that I hate the enshitifiation of Open Source that has been going on, where its just another way to make money and control the eco system. RedHat tried to do it by locking down their source code, Proxmox does it by making sure anything you do on Proxmox is tied to Proxmox (no offense to Proxmox), and even Hashicorp, who I loved so dearly, changed from a pure Open Source licensing model to one that protects the business over the community") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1421,6 +1379,63 @@ func Home() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + templ_7745c5c3_Var69 := 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) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("I will not let that happen here.") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var69), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var70 := 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) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("This project will seek to use the Unix philosophy, of building off of existing standards, combining tools, and having one tool do one job well. This does not mean there will be one application for each aspect of the job, but that this application stack will manage Libvirtd well, and have individual and configurable paths to manage each sub-aspect of the libvirt stack. This stack will not create a Ceph cluster for you, it leaves you to do that. It will not even talk to a ceph cluster. It will, however, let you add that cluster via configuration options to define it as a storage pool that libvirt can use.") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var70), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var71 := 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) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("If you want something that will allow you to use a single interface to create all sub aspects that can be used by libvirt (managing all firewall rules, creating a ceph cluster, etc.), use something like Proxmox which includes that builtin functionality. This isn't the stack for you.") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = components.ContentP().Render(templ.WithChildren(ctx, templ_7745c5c3_Var71), templ_7745c5c3_Buffer) + 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 @@ -1430,7 +1445,7 @@ func Home() templ.Component { } return templ_7745c5c3_Err }) - templ_7745c5c3_Err = components.InfoBox("Other things to note", "uipink").Render(templ.WithChildren(ctx, templ_7745c5c3_Var61), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.InfoBox("Other things to note", "uipink").Render(templ.WithChildren(ctx, templ_7745c5c3_Var63), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }