mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-29 16:30:44 +01:00
admin: warn on dashboard when cluster nodes run mixed versions (#12196)
* admin: warn on dashboard when cluster nodes run mixed versions
A partially-finished upgrade leaves servers on different releases, and
nothing surfaces that drift today. The dashboard now compares the
binary version reported by every node:
- volume servers are asked directly via VolumeServerStatus (the
heartbeat topology carries no version), fanned out with bounded
concurrency and a 60s cache since versions only change on restart
- filers, S3 servers, and message brokers already report their version
over KeepConnected; ListClusterNodes returns it, the dashboard just
never read the field
- masters are excluded: raft membership does not carry versions
When every node matches, the Cluster panel shows the shared version.
When they differ, a warning banner calls out the mixed cluster and the
panel lists each node type with its count grouped by version, e.g.
"31x 4.39, 24x 4.44". Version columns on the volume server, filer, and
S3 tables (and the dedicated volume servers page) identify which nodes
are stale. Versions are compared without the volume-size-limit prefix
("8000GB 4.44 abc123" -> "4.44 abc123") so capacity config does not
masquerade as version drift; nodes reporting nothing count as
"unknown".
* admin: run the volume version queries concurrently, not under the map lock
The per-server VolumeServerStatus call ran while holding the versions
mutex, so the semaphore-bounded fan-out was fully serialized: every
server's RPC waited for the previous one, up to the 3s timeout each.
* admin: export the volume server table's real columns
The new Version cell shifted every later column, so the CSV read the
version as Rack and dropped Max Volumes, EC Shards and Usage a slot
early. Map the cells the table actually renders and add Version to the
export.
* admin: warn on mixed versions only when nodes report versions
An empty or master-only cluster produced a non-uniform summary with an
empty node list, which rendered the "Mixed cluster versions detected"
banner and warning icon over nothing. Mixed() requires reported nodes,
and the version card shows a dash when none answered.
This commit is contained in:
1 parent
e9c280e095
commit
8f6db360da
10 files changed
+1342
-696
No files matched your search
@@ -48,6 +48,10 @@ type AdminData struct {
|
||||
// TierStats breaks volumes and EC shards down by storage tier: local
|
||||
// disk types plus one entry per remote storage holding tiered volumes.
|
||||
TierStats []TierStats `json:"tier_stats"`
|
||||
|
||||
// VersionSummary reports whether all cluster nodes run the same binary
|
||||
// version, so the dashboard can warn about partially upgraded clusters.
|
||||
VersionSummary ClusterVersionSummary `json:"version_summary"`
|
||||
}
|
||||
|
||||
// Object Store Users management structures
|
||||
@@ -145,6 +149,7 @@ type FilerNode struct {
|
||||
Address string `json:"address"`
|
||||
DataCenter string `json:"datacenter"`
|
||||
Rack string `json:"rack"`
|
||||
Version string `json:"version"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
}
|
||||
|
||||
@@ -152,12 +157,14 @@ type MessageBrokerNode struct {
|
||||
Address string `json:"address"`
|
||||
DataCenter string `json:"datacenter"`
|
||||
Rack string `json:"rack"`
|
||||
Version string `json:"version"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
}
|
||||
|
||||
type S3Node struct {
|
||||
Address string `json:"address"`
|
||||
DataCenter string `json:"datacenter"`
|
||||
Version string `json:"version"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
}
|
||||
|
||||
@@ -246,6 +253,7 @@ func (s *AdminServer) GetAdminData(username string) (AdminData, error) {
|
||||
TotalMountClients: totalMountClients,
|
||||
Trends: s.GetDashboardTrends(),
|
||||
TierStats: topology.TierStats,
|
||||
VersionSummary: buildClusterVersionSummary(volumeServersData.VolumeServers, filerNodes, s3Nodes, messageBrokers),
|
||||
}
|
||||
|
||||
return adminData, nil
|
||||
@@ -359,6 +367,7 @@ func (s *AdminServer) getFilerNodesStatus() []FilerNode {
|
||||
Address: pb.ServerAddress(node.Address).ToHttpAddress(),
|
||||
DataCenter: node.DataCenter,
|
||||
Rack: node.Rack,
|
||||
Version: node.Version,
|
||||
LastUpdated: time.Now(),
|
||||
})
|
||||
}
|
||||
@@ -398,6 +407,7 @@ func (s *AdminServer) getMessageBrokerNodesStatus() []MessageBrokerNode {
|
||||
Address: node.Address,
|
||||
DataCenter: node.DataCenter,
|
||||
Rack: node.Rack,
|
||||
Version: node.Version,
|
||||
LastUpdated: time.Now(),
|
||||
})
|
||||
}
|
||||
@@ -436,6 +446,7 @@ func (s *AdminServer) getS3NodesStatus() []S3Node {
|
||||
s3Nodes = append(s3Nodes, S3Node{
|
||||
Address: pb.ServerAddress(node.Address).ToHttpAddress(),
|
||||
DataCenter: node.DataCenter,
|
||||
Version: node.Version,
|
||||
LastUpdated: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -132,6 +132,13 @@ type AdminServer struct {
|
||||
lastFilerUpdate time.Time
|
||||
filerCacheExpiration time.Duration
|
||||
|
||||
// Volume server version reporting: the heartbeat topology carries no
|
||||
// version, so versions are collected per server over VolumeServerStatus
|
||||
// and cached briefly (they only change when a server restarts).
|
||||
volumeVersionCache map[string]string
|
||||
lastVersionFetch time.Time
|
||||
volumeVersionMu sync.Mutex
|
||||
|
||||
// Credential management
|
||||
credentialManager *credential.CredentialManager
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
package dash
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
|
||||
)
|
||||
|
||||
const (
|
||||
// versionCacheTimeout bounds how old the per-server version map can get.
|
||||
// Versions only change on process restart, so a longish window is safe.
|
||||
versionCacheTimeout = 60 * time.Second
|
||||
// volumeVersionConcurrency bounds the VolumeServerStatus fan-out.
|
||||
volumeVersionConcurrency = 8
|
||||
volumeVersionRPCTimeout = 3 * time.Second
|
||||
)
|
||||
|
||||
// ShortVersion strips the volume-size-limit prefix from a version.Version()
|
||||
// string ("8000GB 4.44 abc123" -> "4.44 abc123") so version comparisons and
|
||||
// displays reflect the binary, not the node's configured volume size cap.
|
||||
// Nodes reporting nothing show up as "unknown", which itself is a useful
|
||||
// signal: very old servers may not report a version at all.
|
||||
func ShortVersion(v string) string {
|
||||
v = strings.TrimSpace(v)
|
||||
if i := strings.IndexByte(v, ' '); i > 0 && isSizeLimitToken(v[:i]) {
|
||||
v = strings.TrimSpace(v[i+1:])
|
||||
}
|
||||
if v == "" {
|
||||
return "unknown"
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// isSizeLimitToken reports whether tok looks like the volume size limit that
|
||||
// prefixes version.Version() output, e.g. "30GB" or "8000GB".
|
||||
func isSizeLimitToken(tok string) bool {
|
||||
for _, suffix := range []string{"TB", "GB", "MB", "KB", "B"} {
|
||||
rest, ok := strings.CutSuffix(tok, suffix)
|
||||
if !ok || rest == "" {
|
||||
continue
|
||||
}
|
||||
for _, r := range rest {
|
||||
if r != '.' && (r < '0' || r > '9') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fillVolumeServerVersions populates VolumeServer.Version by asking each
|
||||
// server for its VolumeServerStatus, since heartbeat-derived topology carries
|
||||
// no version. Servers that cannot be reached get "" (rendered "unknown").
|
||||
func (s *AdminServer) fillVolumeServerVersions(servers map[string]*VolumeServer, nodes []*master_pb.DataNodeInfo) {
|
||||
s.volumeVersionMu.Lock()
|
||||
defer s.volumeVersionMu.Unlock()
|
||||
|
||||
if s.volumeVersionCache != nil && time.Since(s.lastVersionFetch) < versionCacheTimeout {
|
||||
for id, vs := range servers {
|
||||
vs.Version = s.volumeVersionCache[id]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
versions := make(map[string]string, len(nodes))
|
||||
var mu sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
sem := make(chan struct{}, volumeVersionConcurrency)
|
||||
for _, node := range nodes {
|
||||
wg.Add(1)
|
||||
go func(node *master_pb.DataNodeInfo) {
|
||||
defer wg.Done()
|
||||
sem <- struct{}{}
|
||||
defer func() { <-sem }()
|
||||
version := s.queryVolumeServerVersion(node)
|
||||
mu.Lock()
|
||||
versions[node.Id] = version
|
||||
mu.Unlock()
|
||||
}(node)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
s.volumeVersionCache = versions
|
||||
s.lastVersionFetch = time.Now()
|
||||
for id, vs := range servers {
|
||||
vs.Version = versions[id]
|
||||
}
|
||||
}
|
||||
|
||||
// queryVolumeServerVersion asks one volume server for its version string.
|
||||
func (s *AdminServer) queryVolumeServerVersion(node *master_pb.DataNodeInfo) (version string) {
|
||||
err := s.WithVolumeServerClient(pb.NewServerAddressFromDataNode(node), func(client volume_server_pb.VolumeServerClient) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), volumeVersionRPCTimeout)
|
||||
defer cancel()
|
||||
resp, err := client.VolumeServerStatus(ctx, &volume_server_pb.VolumeServerStatusRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
version = resp.Version
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
glog.V(1).Infof("Failed to get version from volume server %s: %v", node.Id, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// buildClusterVersionSummary groups reported node versions per node type.
|
||||
// Masters are excluded: they are only enumerable via raft membership, which
|
||||
// does not carry versions.
|
||||
func buildClusterVersionSummary(volumeServers []VolumeServer, filers []FilerNode, s3Nodes []S3Node, brokers []MessageBrokerNode) ClusterVersionSummary {
|
||||
summary := ClusterVersionSummary{Uniform: true}
|
||||
for _, group := range []struct {
|
||||
label string
|
||||
versions []string
|
||||
}{
|
||||
{"Volume Servers", collectVersions(len(volumeServers), func(i int) string { return volumeServers[i].Version })},
|
||||
{"Filers", collectVersions(len(filers), func(i int) string { return filers[i].Version })},
|
||||
{"S3 Servers", collectVersions(len(s3Nodes), func(i int) string { return s3Nodes[i].Version })},
|
||||
{"Message Brokers", collectVersions(len(brokers), func(i int) string { return brokers[i].Version })},
|
||||
} {
|
||||
nt := summarizeVersions(group.label, group.versions)
|
||||
if nt.Total == 0 {
|
||||
continue
|
||||
}
|
||||
summary.NodeTypes = append(summary.NodeTypes, nt)
|
||||
}
|
||||
|
||||
// Uniform means every reported node is on the same single version.
|
||||
seen := ""
|
||||
for _, nt := range summary.NodeTypes {
|
||||
for _, vc := range nt.Versions {
|
||||
if seen == "" {
|
||||
seen = vc.Version
|
||||
} else if vc.Version != seen {
|
||||
summary.Uniform = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(summary.NodeTypes) == 0 {
|
||||
summary.Uniform = false
|
||||
}
|
||||
if summary.Uniform {
|
||||
summary.Version = seen
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
// collectVersions maps node indexes to their normalized version strings.
|
||||
func collectVersions(n int, versionOf func(i int) string) []string {
|
||||
versions := make([]string, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
versions = append(versions, ShortVersion(versionOf(i)))
|
||||
}
|
||||
return versions
|
||||
}
|
||||
|
||||
// summarizeVersions counts nodes per distinct version.
|
||||
func summarizeVersions(label string, versions []string) NodeTypeVersions {
|
||||
counts := make(map[string]int)
|
||||
for _, v := range versions {
|
||||
counts[v]++
|
||||
}
|
||||
nt := NodeTypeVersions{Type: label, Total: len(versions)}
|
||||
for v, count := range counts {
|
||||
nt.Versions = append(nt.Versions, VersionCount{Version: v, Count: count})
|
||||
}
|
||||
sort.Slice(nt.Versions, func(i, j int) bool {
|
||||
if nt.Versions[i].Count != nt.Versions[j].Count {
|
||||
return nt.Versions[i].Count > nt.Versions[j].Count
|
||||
}
|
||||
return nt.Versions[i].Version < nt.Versions[j].Version
|
||||
})
|
||||
return nt
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package dash
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestShortVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{"8000GB 4.44-enterprise 192465e6", "4.44-enterprise 192465e6"},
|
||||
{"30GB 4.51", "4.51"},
|
||||
{"4.51 abc123", "4.51 abc123"},
|
||||
{"4.51", "4.51"},
|
||||
{"", "unknown"},
|
||||
{" ", "unknown"},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
if got := ShortVersion(tc.in); got != tc.want {
|
||||
t.Errorf("ShortVersion(%q) = %q, want %q", tc.in, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildClusterVersionSummary(t *testing.T) {
|
||||
vs := func(version string, n int) (out []VolumeServer) {
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, VolumeServer{Version: version})
|
||||
}
|
||||
return
|
||||
}
|
||||
filers := func(version string, n int) (out []FilerNode) {
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, FilerNode{Version: version})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
t.Run("uniform across types", func(t *testing.T) {
|
||||
s := buildClusterVersionSummary(
|
||||
vs("8000GB 4.44 aaa", 3),
|
||||
filers("30GB 4.44 aaa", 2), // different size-limit prefix, same binary
|
||||
nil, nil,
|
||||
)
|
||||
if !s.Uniform || s.Version != "4.44 aaa" {
|
||||
t.Fatalf("expected uniform 4.44 aaa, got %+v", s)
|
||||
}
|
||||
if len(s.NodeTypes) != 2 {
|
||||
t.Fatalf("expected 2 node types, got %+v", s.NodeTypes)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("mixed volume server versions", func(t *testing.T) {
|
||||
servers := append(vs("8000GB 4.44 aaa", 24), vs("8000GB 4.39 bbb", 31)...)
|
||||
s := buildClusterVersionSummary(servers, nil, nil, nil)
|
||||
if s.Uniform {
|
||||
t.Fatalf("expected non-uniform summary, got %+v", s)
|
||||
}
|
||||
if len(s.NodeTypes) != 1 {
|
||||
t.Fatalf("expected 1 node type, got %+v", s.NodeTypes)
|
||||
}
|
||||
nt := s.NodeTypes[0]
|
||||
if nt.Type != "Volume Servers" || nt.Total != 55 {
|
||||
t.Fatalf("unexpected node type summary: %+v", nt)
|
||||
}
|
||||
// sorted by count desc: 31x 4.39 first, then 24x 4.44
|
||||
if len(nt.Versions) != 2 || nt.Versions[0].Version != "4.39 bbb" || nt.Versions[0].Count != 31 {
|
||||
t.Fatalf("unexpected versions: %+v", nt.Versions)
|
||||
}
|
||||
if nt.Spread() != "31× 4.39 bbb, 24× 4.44 aaa" {
|
||||
t.Fatalf("unexpected spread: %q", nt.Spread())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("unreported versions count as unknown", func(t *testing.T) {
|
||||
s := buildClusterVersionSummary(vs("", 2), nil, nil, nil)
|
||||
// all empty -> a single "unknown" group, uniform but not a real version
|
||||
if !s.Uniform || s.Version != "unknown" {
|
||||
t.Fatalf("expected uniform unknown, got %+v", s)
|
||||
}
|
||||
if s.NodeTypes[0].Versions[0].Version != "unknown" || s.NodeTypes[0].Versions[0].Count != 2 {
|
||||
t.Fatalf("expected unknown group, got %+v", s.NodeTypes[0].Versions)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("unknown mixed with real versions is not uniform", func(t *testing.T) {
|
||||
servers := append(vs("8000GB 4.44 aaa", 1), vs("", 1)...)
|
||||
s := buildClusterVersionSummary(servers, nil, nil, nil)
|
||||
if s.Uniform {
|
||||
t.Fatalf("expected non-uniform summary, got %+v", s)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no nodes is not uniform", func(t *testing.T) {
|
||||
s := buildClusterVersionSummary(nil, nil, nil, nil)
|
||||
if s.Uniform {
|
||||
t.Fatal("empty cluster should not report a uniform version")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package dash
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/admin/maintenance"
|
||||
@@ -45,6 +47,7 @@ type VolumeServer struct {
|
||||
DataCenter string `json:"datacenter"`
|
||||
Rack string `json:"rack"`
|
||||
PublicURL string `json:"public_url"`
|
||||
Version string `json:"version"`
|
||||
Volumes int `json:"volumes"`
|
||||
MaxVolumes int `json:"max_volumes"`
|
||||
DiskUsage int64 `json:"disk_usage"`
|
||||
@@ -789,3 +792,39 @@ type IcebergTableDetailsData struct {
|
||||
ObservedBy string `json:"observed_by,omitempty"`
|
||||
ObservedAt time.Time `json:"observed_at,omitempty"`
|
||||
}
|
||||
|
||||
// VersionCount tallies the nodes of one type running the same binary version.
|
||||
type VersionCount struct {
|
||||
Version string `json:"version"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// NodeTypeVersions is the version spread of one kind of cluster node.
|
||||
type NodeTypeVersions struct {
|
||||
Type string `json:"type"`
|
||||
Total int `json:"total"`
|
||||
Versions []VersionCount `json:"versions"` // sorted by count desc, then version
|
||||
}
|
||||
|
||||
// Spread renders the per-version counts, e.g. "24× 4.44 abc123, 31× 4.39 def456".
|
||||
func (n NodeTypeVersions) Spread() string {
|
||||
parts := make([]string, 0, len(n.Versions))
|
||||
for _, vc := range n.Versions {
|
||||
parts = append(parts, fmt.Sprintf("%d× %s", vc.Count, vc.Version))
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// ClusterVersionSummary reports whether every cluster node runs the same
|
||||
// binary version, and the per-type spread when they do not.
|
||||
type ClusterVersionSummary struct {
|
||||
Uniform bool `json:"uniform"`
|
||||
Version string `json:"version,omitempty"` // set when Uniform
|
||||
NodeTypes []NodeTypeVersions `json:"node_types"`
|
||||
}
|
||||
|
||||
// Mixed reports a real version split: non-uniform with nodes on record,
|
||||
// unlike an empty cluster that reports no versions at all.
|
||||
func (v ClusterVersionSummary) Mixed() bool {
|
||||
return !v.Uniform && len(v.NodeTypes) > 0
|
||||
}
|
||||
@@ -477,6 +477,7 @@ func (s *AdminServer) GetClusterVolumeServers() (*ClusterVolumeServersData, erro
|
||||
publicUrls := s.fetchPublicUrlMap()
|
||||
|
||||
// Make only ONE VolumeList call and use it for both topology building AND EC shard processing
|
||||
var dataNodes []*master_pb.DataNodeInfo
|
||||
err := s.WithMasterClient(func(client master_pb.SeaweedClient) error {
|
||||
resp, err := pb.CollectVolumeList(context.Background(), client, &master_pb.VolumeListRequest{})
|
||||
if err != nil {
|
||||
@@ -497,6 +498,7 @@ func (s *AdminServer) GetClusterVolumeServers() (*ClusterVolumeServersData, erro
|
||||
for _, dc := range resp.TopologyInfo.DataCenterInfos {
|
||||
for _, rack := range dc.RackInfos {
|
||||
for _, node := range rack.DataNodeInfos {
|
||||
dataNodes = append(dataNodes, node)
|
||||
// Initialize volume server if not exists
|
||||
if volumeServerMap[node.Id] == nil {
|
||||
// Look up PublicUrl from master HTTP API
|
||||
@@ -623,6 +625,9 @@ func (s *AdminServer) GetClusterVolumeServers() (*ClusterVolumeServersData, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Versions are not in the heartbeat topology; ask each server directly.
|
||||
s.fillVolumeServerVersions(volumeServerMap, dataNodes)
|
||||
|
||||
// Convert map back to slice
|
||||
var volumeServers []VolumeServer
|
||||
for _, vs := range volumeServerMap {
|
||||
|
||||
@@ -21,6 +21,23 @@ templ Admin(data dash.AdminData) {
|
||||
</div>
|
||||
|
||||
<div id="dashboard-content">
|
||||
<!-- Version mismatch warning: nodes reporting different binary versions
|
||||
usually means an upgrade did not reach every server. -->
|
||||
if data.VersionSummary.Mixed() {
|
||||
<div class="alert alert-warning d-flex align-items-start" role="alert">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2 mt-1"></i>
|
||||
<div>
|
||||
<strong>Mixed cluster versions detected.</strong>
|
||||
Not all servers are running the same SeaweedFS version — some servers may not have been upgraded.
|
||||
<ul class="mb-0 mt-1">
|
||||
for _, nt := range data.VersionSummary.NodeTypes {
|
||||
<li>{nt.Type}: {nt.Spread()}</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Summary Cards — each carries an inline sparkline of recent history
|
||||
from the admin's own snapshots (no Prometheus required). -->
|
||||
<div class="row mb-4">
|
||||
@@ -395,7 +412,38 @@ templ Admin(data dash.AdminData) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card bg-light">
|
||||
<div class="card-body">
|
||||
if data.VersionSummary.Uniform {
|
||||
<h5 class="text-truncate" title={data.VersionSummary.Version}>{data.VersionSummary.Version}</h5>
|
||||
<small class="text-muted">Version</small>
|
||||
} else if data.VersionSummary.Mixed() {
|
||||
<h5 class="text-warning">
|
||||
<i class="bi bi-exclamation-triangle-fill"></i>
|
||||
</h5>
|
||||
<small class="text-muted">Mixed Versions</small>
|
||||
} else {
|
||||
<h5 class="text-truncate">—</h5>
|
||||
<small class="text-muted">Version</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
if data.VersionSummary.Mixed() {
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 text-start">
|
||||
<small class="text-muted text-uppercase fw-bold">Node Versions</small>
|
||||
for _, nt := range data.VersionSummary.NodeTypes {
|
||||
<div class="d-flex justify-content-between border-bottom py-1">
|
||||
<span>{nt.Type}</span>
|
||||
<span>{nt.Spread()}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -429,6 +477,7 @@ templ Admin(data dash.AdminData) {
|
||||
<th>Address</th>
|
||||
<th>Data Center</th>
|
||||
<th>Rack</th>
|
||||
<th>Version</th>
|
||||
<th>Volumes</th>
|
||||
<th>EC Shards</th>
|
||||
<th>Usage / Capacity</th>
|
||||
@@ -446,6 +495,7 @@ templ Admin(data dash.AdminData) {
|
||||
</td>
|
||||
<td>{vs.DataCenter}</td>
|
||||
<td>{vs.Rack}</td>
|
||||
<td title={vs.Version}>{dash.ShortVersion(vs.Version)}</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="progress flex-grow-1" style="height: 20px; min-width: 48px;">
|
||||
@@ -477,7 +527,7 @@ templ Admin(data dash.AdminData) {
|
||||
}
|
||||
if len(data.VolumeServers) == 0 {
|
||||
<tr>
|
||||
<td colspan="7" class="text-center text-muted py-4">
|
||||
<td colspan="8" class="text-center text-muted py-4">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
No volume servers found
|
||||
</td>
|
||||
@@ -518,6 +568,7 @@ templ Admin(data dash.AdminData) {
|
||||
<th>Address</th>
|
||||
<th>Data Center</th>
|
||||
<th>Rack</th>
|
||||
<th>Version</th>
|
||||
<th>Last Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -532,12 +583,13 @@ templ Admin(data dash.AdminData) {
|
||||
</td>
|
||||
<td>{filer.DataCenter}</td>
|
||||
<td>{filer.Rack}</td>
|
||||
<td title={filer.Version}>{dash.ShortVersion(filer.Version)}</td>
|
||||
<td>{filer.LastUpdated.Format("2006-01-02 15:04:05")}</td>
|
||||
</tr>
|
||||
}
|
||||
if len(data.FilerNodes) == 0 {
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-muted py-4">
|
||||
<td colspan="5" class="text-center text-muted py-4">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
No filer nodes found
|
||||
</td>
|
||||
@@ -576,6 +628,7 @@ templ Admin(data dash.AdminData) {
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Data Center</th>
|
||||
<th>Version</th>
|
||||
<th>Last Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -584,12 +637,13 @@ templ Admin(data dash.AdminData) {
|
||||
<tr>
|
||||
<td>{s3Node.Address}</td>
|
||||
<td>{s3Node.DataCenter}</td>
|
||||
<td title={s3Node.Version}>{dash.ShortVersion(s3Node.Version)}</td>
|
||||
<td>{s3Node.LastUpdated.Format("2006-01-02 15:04:05")}</td>
|
||||
</tr>
|
||||
}
|
||||
if len(data.S3Nodes) == 0 {
|
||||
<tr>
|
||||
<td colspan="3" class="text-center text-muted py-4">
|
||||
<td colspan="4" class="text-center text-muted py-4">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
No S3 servers found
|
||||
</td>
|
||||
|
||||
+714
-498
File diff suppressed because it is too large.
Load diff
@@ -101,6 +101,7 @@ templ ClusterVolumeServers(data dash.ClusterVolumeServersData) {
|
||||
<th>Address</th>
|
||||
<th>Data Center</th>
|
||||
<th>Rack</th>
|
||||
<th>Version</th>
|
||||
<th>Volumes</th>
|
||||
<th>Max Volumes</th>
|
||||
<th>EC Shards</th>
|
||||
@@ -131,6 +132,9 @@ templ ClusterVolumeServers(data dash.ClusterVolumeServersData) {
|
||||
<td>
|
||||
<span class="badge bg-light text-dark">{host.Rack}</span>
|
||||
</td>
|
||||
<td title={host.Version}>
|
||||
{dash.ShortVersion(host.Version)}
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="progress me-2" style="width: 60px; height: 16px;">
|
||||
@@ -393,20 +397,20 @@ templ ClusterVolumeServers(data dash.ClusterVolumeServersData) {
|
||||
if (cells.length > 1) {
|
||||
return {
|
||||
id: cells[0].textContent.trim(),
|
||||
address: cells[1].textContent.trim(),
|
||||
datacenter: cells[2].textContent.trim(),
|
||||
rack: cells[3].textContent.trim(),
|
||||
datacenter: cells[1].textContent.trim(),
|
||||
rack: cells[2].textContent.trim(),
|
||||
version: cells[3].textContent.trim(),
|
||||
volumes: cells[4].textContent.trim(),
|
||||
capacity: cells[5].textContent.trim(),
|
||||
usage: cells[6].textContent.trim()
|
||||
capacity: cells[7].textContent.trim(),
|
||||
usage: cells[8].textContent.trim()
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}).filter(row => row !== null);
|
||||
|
||||
const csvContent = "data:text/csv;charset=utf-8," +
|
||||
"Server ID,Address,Data Center,Rack,Volumes,Capacity,Usage\n" +
|
||||
rows.map(r => '"' + r.id + '","' + r.address + '","' + r.datacenter + '","' + r.rack + '","' + r.volumes + '","' + r.capacity + '","' + r.usage + '"').join("\n");
|
||||
"Server ID,Data Center,Rack,Version,Volumes,Capacity,Usage\n" +
|
||||
rows.map(r => '"' + r.id + '","' + r.datacenter + '","' + r.rack + '","' + r.version + '","' + r.volumes + '","' + r.capacity + '","' + r.usage + '"').join("\n");
|
||||
|
||||
const encodedUri = encodeURI(csvContent);
|
||||
const link = document.createElement("a");
|
||||
|
||||
@@ -75,7 +75,7 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if len(data.VolumeServers) > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"table-responsive\"><table class=\"table table-hover\" id=\"hostsTable\"><thead><tr><th>Address</th><th>Data Center</th><th>Rack</th><th>Volumes</th><th>Max Volumes</th><th>EC Shards</th><th>Capacity</th><th>Usage</th><th>Actions</th></tr></thead> <tbody>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"table-responsive\"><table class=\"table table-hover\" id=\"hostsTable\"><thead><tr><th>Address</th><th>Data Center</th><th>Rack</th><th>Version</th><th>Volumes</th><th>Max Volumes</th><th>EC Shards</th><th>Capacity</th><th>Usage</th><th>Actions</th></tr></thead> <tbody>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templruntime.NewAttributeExpression(templ.SafeURL(fmt.Sprintf("//%s/ui/index.html", host.PublicURL))).ResolveURL(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 117, Col: 121}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 118, Col: 121}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -105,7 +105,7 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(host.Address)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 118, Col: 65}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 119, Col: 65}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -123,7 +123,7 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templruntime.NewAttributeExpression(templ.SafeURL(fmt.Sprintf("//%s/ui/index.html", host.Address))).ResolveURL(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 122, Col: 119}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 123, Col: 119}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -136,7 +136,7 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(host.Address)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 123, Col: 65}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 124, Col: 65}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -154,7 +154,7 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(host.DataCenter)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 129, Col: 99}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 130, Col: 99}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -167,542 +167,568 @@ func ClusterVolumeServers(data dash.ClusterVolumeServersData) templ.Component {
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(host.Rack)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 132, Col: 93}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 133, Col: 93}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</span></td><td><div class=\"d-flex align-items-center\"><div class=\"progress me-2\" style=\"width: 60px; height: 16px;\"><div class=\"progress-bar\" role=\"progressbar\" style=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</span></td><td title=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %d%%", calculatePercent(host.Volumes, host.MaxVolumes)))
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Version).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 138, Col: 139}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 135, Col: 63}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"></div></div><span class=\"badge bg-primary\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", host.Volumes))
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(dash.ShortVersion(host.Version))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 141, Col: 111}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 136, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</span></div></td><td><span class=\"badge bg-secondary\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</td><td><div class=\"d-flex align-items-center\"><div class=\"progress me-2\" style=\"width: 60px; height: 16px;\"><div class=\"progress-bar\" role=\"progressbar\" style=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", host.MaxVolumes))
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %d%%", calculatePercent(host.Volumes, host.MaxVolumes)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 145, Col: 112}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 142, Col: 139}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</span></td><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\"></div></div><span class=\"badge bg-primary\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", host.Volumes))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 145, Col: 111}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</span></div></td><td><span class=\"badge bg-secondary\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", host.MaxVolumes))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 149, Col: 112}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</span></td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if host.EcShards > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"d-flex align-items-center\"><i class=\"bi bi-layers me-1 text-info\"></i> <span class=\"badge bg-info text-white me-1\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"d-flex align-items-center\"><i class=\"bi bi-layers me-1 text-info\"></i> <span class=\"badge bg-info text-white me-1\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", host.EcShards))
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", host.EcShards))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 151, Col: 129}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 155, Col: 129}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</span> <small class=\"text-muted\">shards</small></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</span> <small class=\"text-muted\">shards</small></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if host.EcVolumes > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"mt-1\"><small class=\"text-muted\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<div class=\"mt-1\"><small class=\"text-muted\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d EC volumes", host.EcVolumes))
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d EC volumes", host.EcVolumes))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 156, Col: 127}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 160, Col: 127}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</small></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</small></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<span class=\"text-muted\">-</span>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<span class=\"text-muted\">-</span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(host.DiskCapacity))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 163, Col: 75}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</td><td><div class=\"d-flex align-items-center\"><div class=\"progress me-2\" style=\"width: 60px; height: 16px;\"><div class=\"progress-bar\" role=\"progressbar\" style=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %d%%", calculatePercent(int(host.DiskUsage), int(host.DiskCapacity))))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 168, Col: 153}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\"></div></div><small>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var18 string
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(host.DiskUsage))
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(host.DiskCapacity))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 171, Col: 83}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 167, Col: 75}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</small></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</td><td><div class=\"d-flex align-items-center\"><div class=\"progress me-2\" style=\"width: 60px; height: 16px;\"><div class=\"progress-bar\" role=\"progressbar\" style=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %d%%", calculatePercent(int(host.DiskUsage), int(host.DiskCapacity))))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 172, Col: 153}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\"></div></div><small>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var20 string
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(host.DiskUsage))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 175, Col: 83}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</small></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if host.RemoteSize > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"mt-1\"><small class=\"text-muted\"><i class=\"bi bi-cloud me-1\"></i>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(host.RemoteSize))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 175, Col: 139}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " remote</small></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if host.PublicURL != "" {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"View Details\" data-action=\"view-details\" data-id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var20 string
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.ID).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 185, Col: 72}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" data-address=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<div class=\"mt-1\"><small class=\"text-muted\"><i class=\"bi bi-cloud me-1\"></i>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var21 string
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Address).Resolve(ctx)
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(host.RemoteSize))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 186, Col: 82}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 179, Col: 139}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var21)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" data-public-url=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, " remote</small></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if host.PublicURL != "" {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"View Details\" data-action=\"view-details\" data-id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var22 string
|
||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.PublicURL).ResolveURL(ctx)
|
||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.ID).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 187, Col: 87}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 189, Col: 72}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\" data-datacenter=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\" data-address=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var23 string
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.DataCenter).Resolve(ctx)
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Address).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 188, Col: 88}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 190, Col: 82}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var23)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\" data-rack=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\" data-public-url=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var24 string
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Rack).Resolve(ctx)
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.PublicURL).ResolveURL(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 189, Col: 76}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 191, Col: 87}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "\" data-volumes=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "\" data-datacenter=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var25 string
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.Volumes)).Resolve(ctx)
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.DataCenter).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 190, Col: 101}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 192, Col: 88}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var25)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" data-max-volumes=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" data-rack=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var26 string
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.MaxVolumes)).Resolve(ctx)
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Rack).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 191, Col: 108}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 193, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var26)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" data-disk-usage=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" data-volumes=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var27 string
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskUsage)).Resolve(ctx)
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.Volumes)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 192, Col: 106}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 194, Col: 101}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var27)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\" data-disk-capacity=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\" data-max-volumes=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var28 string
|
||||
templ_7745c5c3_Var28, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskCapacity)).Resolve(ctx)
|
||||
templ_7745c5c3_Var28, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.MaxVolumes)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 193, Col: 112}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 195, Col: 108}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\" data-remote-size=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\" data-disk-usage=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var29 string
|
||||
templ_7745c5c3_Var29, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.RemoteSize)).Resolve(ctx)
|
||||
templ_7745c5c3_Var29, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskUsage)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 194, Col: 108}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 196, Col: 106}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var29)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\" data-ec-volumes=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\" data-disk-capacity=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var30 string
|
||||
templ_7745c5c3_Var30, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcVolumes)).Resolve(ctx)
|
||||
templ_7745c5c3_Var30, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskCapacity)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 195, Col: 106}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 197, Col: 112}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var30)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "\" data-ec-shards=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "\" data-remote-size=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var31 string
|
||||
templ_7745c5c3_Var31, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcShards)).Resolve(ctx)
|
||||
templ_7745c5c3_Var31, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.RemoteSize)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 196, Col: 104}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 198, Col: 108}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var31)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "\" data-last-heartbeat=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "\" data-ec-volumes=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var32 string
|
||||
templ_7745c5c3_Var32, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.LastHeartbeat.Format("2006-01-02 15:04:05")).Resolve(ctx)
|
||||
templ_7745c5c3_Var32, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcVolumes)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 197, Col: 125}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 199, Col: 106}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var32)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\"><i class=\"bi bi-eye\"></i></button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"View Details\" data-action=\"view-details\" data-id=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\" data-ec-shards=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var33 string
|
||||
templ_7745c5c3_Var33, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.ID).Resolve(ctx)
|
||||
templ_7745c5c3_Var33, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcShards)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 205, Col: 72}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 200, Col: 104}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var33)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\" data-address=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "\" data-last-heartbeat=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var34 string
|
||||
templ_7745c5c3_Var34, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Address).Resolve(ctx)
|
||||
templ_7745c5c3_Var34, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.LastHeartbeat.Format("2006-01-02 15:04:05")).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 206, Col: 82}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 201, Col: 125}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var34)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\" data-public-url=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\"><i class=\"bi bi-eye\"></i></button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"View Details\" data-action=\"view-details\" data-id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var35 string
|
||||
templ_7745c5c3_Var35, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Address).ResolveURL(ctx)
|
||||
templ_7745c5c3_Var35, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.ID).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 207, Col: 85}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 209, Col: 72}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\" data-datacenter=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\" data-address=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var36 string
|
||||
templ_7745c5c3_Var36, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.DataCenter).Resolve(ctx)
|
||||
templ_7745c5c3_Var36, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Address).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 208, Col: 88}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 210, Col: 82}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var36)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "\" data-rack=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "\" data-public-url=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var37 string
|
||||
templ_7745c5c3_Var37, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Rack).Resolve(ctx)
|
||||
templ_7745c5c3_Var37, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Address).ResolveURL(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 209, Col: 76}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 211, Col: 85}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var37)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "\" data-volumes=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "\" data-datacenter=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var38 string
|
||||
templ_7745c5c3_Var38, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.Volumes)).Resolve(ctx)
|
||||
templ_7745c5c3_Var38, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.DataCenter).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 210, Col: 101}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 212, Col: 88}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var38)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "\" data-max-volumes=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "\" data-rack=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var39 string
|
||||
templ_7745c5c3_Var39, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.MaxVolumes)).Resolve(ctx)
|
||||
templ_7745c5c3_Var39, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.Rack).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 211, Col: 108}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 213, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var39)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\" data-disk-usage=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\" data-volumes=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var40 string
|
||||
templ_7745c5c3_Var40, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskUsage)).Resolve(ctx)
|
||||
templ_7745c5c3_Var40, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.Volumes)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 212, Col: 106}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 214, Col: 101}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var40)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" data-disk-capacity=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" data-max-volumes=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var41 string
|
||||
templ_7745c5c3_Var41, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskCapacity)).Resolve(ctx)
|
||||
templ_7745c5c3_Var41, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.MaxVolumes)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 213, Col: 112}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 215, Col: 108}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var41)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\" data-remote-size=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\" data-disk-usage=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var42 string
|
||||
templ_7745c5c3_Var42, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.RemoteSize)).Resolve(ctx)
|
||||
templ_7745c5c3_Var42, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskUsage)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 214, Col: 108}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 216, Col: 106}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var42)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\" data-ec-volumes=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\" data-disk-capacity=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var43 string
|
||||
templ_7745c5c3_Var43, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcVolumes)).Resolve(ctx)
|
||||
templ_7745c5c3_Var43, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.DiskCapacity)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 215, Col: 106}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 217, Col: 112}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var43)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" data-ec-shards=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" data-remote-size=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var44 string
|
||||
templ_7745c5c3_Var44, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcShards)).Resolve(ctx)
|
||||
templ_7745c5c3_Var44, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.RemoteSize)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 216, Col: 104}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 218, Col: 108}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var44)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" data-last-heartbeat=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" data-ec-volumes=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var45 string
|
||||
templ_7745c5c3_Var45, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.LastHeartbeat.Format("2006-01-02 15:04:05")).Resolve(ctx)
|
||||
templ_7745c5c3_Var45, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcVolumes)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 217, Col: 125}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 219, Col: 106}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var45)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "\"><i class=\"bi bi-eye\"></i></button>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "\" data-ec-shards=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var46 string
|
||||
templ_7745c5c3_Var46, templ_7745c5c3_Err = templruntime.NewAttributeExpression(fmt.Sprintf("%d", host.EcShards)).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 220, Col: 104}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var46)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "\" data-last-heartbeat=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var47 string
|
||||
templ_7745c5c3_Var47, templ_7745c5c3_Err = templruntime.NewAttributeExpression(host.LastHeartbeat.Format("2006-01-02 15:04:05")).Resolve(ctx)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 221, Col: 125}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var47)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "\"><i class=\"bi bi-eye\"></i></button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</td></tr>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "</td></tr>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</tbody></table></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "</tbody></table></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "<div class=\"text-center py-5\"><i class=\"bi bi-server icon-3x text-muted mb-3\"></i><h5 class=\"text-muted\">No Volume Servers Found</h5><p class=\"text-muted\">No volume servers are currently available in the cluster.</p></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "<div class=\"text-center py-5\"><i class=\"bi bi-server icon-3x text-muted mb-3\"></i><h5 class=\"text-muted\">No Volume Servers Found</h5><p class=\"text-muted\">No volume servers are currently available in the cluster.</p></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "</div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"bi bi-clock me-1\"></i> Last updated: ")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</div></div><!-- Last Updated --><div class=\"row\"><div class=\"col-12\"><small class=\"text-muted\"><i class=\"bi bi-clock me-1\"></i> Last updated: ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var46 string
|
||||
templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
|
||||
var templ_7745c5c3_Var48 string
|
||||
templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05"))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 242, Col: 81}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_volume_servers.templ`, Line: 246, Col: 81}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "</small></div></div></div><!-- JavaScript for cluster volume servers functionality --><script>\n document.addEventListener('DOMContentLoaded', function() {\n // Handle volume server action buttons\n document.addEventListener('click', function(e) {\n const button = e.target.closest('[data-action]');\n if (!button) return;\n \n const action = button.getAttribute('data-action');\n \n switch(action) {\n case 'view-details':\n const serverData = {\n id: button.getAttribute('data-id'),\n address: button.getAttribute('data-address'),\n publicUrl: button.getAttribute('data-public-url'),\n datacenter: button.getAttribute('data-datacenter'),\n rack: button.getAttribute('data-rack'),\n volumes: parseInt(button.getAttribute('data-volumes')),\n maxVolumes: parseInt(button.getAttribute('data-max-volumes')),\n diskUsage: parseInt(button.getAttribute('data-disk-usage')),\n diskCapacity: parseInt(button.getAttribute('data-disk-capacity')),\n remoteSize: parseInt(button.getAttribute('data-remote-size')) || 0,\n ecVolumes: parseInt(button.getAttribute('data-ec-volumes')),\n ecShards: parseInt(button.getAttribute('data-ec-shards')),\n lastHeartbeat: button.getAttribute('data-last-heartbeat')\n };\n showVolumeServerDetails(serverData);\n break;\n }\n });\n });\n \n function showVolumeServerDetails(server) {\n const volumePercent = server.maxVolumes > 0 ? Math.round((server.volumes / server.maxVolumes) * 100) : 0;\n const diskPercent = server.diskCapacity > 0 ? Math.round((server.diskUsage / server.diskCapacity) * 100) : 0;\n \n const modalHtml = '<div class=\"modal fade\" id=\"volumeServerDetailsModal\" tabindex=\"-1\">' +\n '<div class=\"modal-dialog modal-lg\">' +\n '<div class=\"modal-content\">' +\n '<div class=\"modal-header\">' +\n '<h5 class=\"modal-title\"><i class=\"bi bi-server me-2\"></i>Volume Server Details: ' + server.address + '</h5>' +\n '<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button>' +\n '</div>' +\n '<div class=\"modal-body\">' +\n '<div class=\"row\">' +\n '<div class=\"col-md-6\">' +\n '<h6 class=\"text-primary\"><i class=\"bi bi-info-circle me-1\"></i>Basic Information</h6>' +\n '<table class=\"table table-sm\">' +\n '<tr><td><strong>Server ID:</strong></td><td><code>' + server.id + '</code></td></tr>' +\n '<tr><td><strong>Address:</strong></td><td>' + server.address + '</td></tr>' +\n '<tr><td><strong>Public URL:</strong></td><td>' + server.publicUrl + '</td></tr>' +\n '<tr><td><strong>Data Center:</strong></td><td><span class=\"badge bg-light text-dark\">' + server.datacenter + '</span></td></tr>' +\n '<tr><td><strong>Rack:</strong></td><td><span class=\"badge bg-light text-dark\">' + server.rack + '</span></td></tr>' +\n '<tr><td><strong>Last Heartbeat:</strong></td><td>' + server.lastHeartbeat + '</td></tr>' +\n '</table>' +\n '</div>' +\n '<div class=\"col-md-6\">' +\n '<h6 class=\"text-primary\"><i class=\"bi bi-bar-chart me-1\"></i>Usage Statistics</h6>' +\n '<table class=\"table table-sm\">' +\n '<tr><td><strong>Volumes:</strong></td><td>' +\n '<div class=\"d-flex align-items-center\">' +\n '<div class=\"progress me-2\" style=\"width: 100px; height: 20px;\">' +\n '<div class=\"progress-bar\" role=\"progressbar\" style=\"width: ' + volumePercent + '%\"></div>' +\n '</div>' +\n '<span>' + server.volumes + '/' + server.maxVolumes + ' (' + volumePercent + '%)</span>' +\n '</div>' +\n '</td></tr>' +\n '<tr><td><strong>Disk Usage:</strong></td><td>' +\n '<div class=\"d-flex align-items-center\">' +\n '<div class=\"progress me-2\" style=\"width: 100px; height: 20px;\">' +\n '<div class=\"progress-bar\" role=\"progressbar\" style=\"width: ' + diskPercent + '%\"></div>' +\n '</div>' +\n '<span>' + formatBytes(server.diskUsage) + '/' + formatBytes(server.diskCapacity) + ' (' + diskPercent + '%)</span>' +\n '</div>' +\n '</td></tr>' +\n '<tr><td><strong>Available Space:</strong></td><td>' + formatBytes(server.diskCapacity - server.diskUsage) + '</td></tr>' +\n Line truncated
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "</small></div></div></div><!-- JavaScript for cluster volume servers functionality --><script>\n document.addEventListener('DOMContentLoaded', function() {\n // Handle volume server action buttons\n document.addEventListener('click', function(e) {\n const button = e.target.closest('[data-action]');\n if (!button) return;\n \n const action = button.getAttribute('data-action');\n \n switch(action) {\n case 'view-details':\n const serverData = {\n id: button.getAttribute('data-id'),\n address: button.getAttribute('data-address'),\n publicUrl: button.getAttribute('data-public-url'),\n datacenter: button.getAttribute('data-datacenter'),\n rack: button.getAttribute('data-rack'),\n volumes: parseInt(button.getAttribute('data-volumes')),\n maxVolumes: parseInt(button.getAttribute('data-max-volumes')),\n diskUsage: parseInt(button.getAttribute('data-disk-usage')),\n diskCapacity: parseInt(button.getAttribute('data-disk-capacity')),\n remoteSize: parseInt(button.getAttribute('data-remote-size')) || 0,\n ecVolumes: parseInt(button.getAttribute('data-ec-volumes')),\n ecShards: parseInt(button.getAttribute('data-ec-shards')),\n lastHeartbeat: button.getAttribute('data-last-heartbeat')\n };\n showVolumeServerDetails(serverData);\n break;\n }\n });\n });\n \n function showVolumeServerDetails(server) {\n const volumePercent = server.maxVolumes > 0 ? Math.round((server.volumes / server.maxVolumes) * 100) : 0;\n const diskPercent = server.diskCapacity > 0 ? Math.round((server.diskUsage / server.diskCapacity) * 100) : 0;\n \n const modalHtml = '<div class=\"modal fade\" id=\"volumeServerDetailsModal\" tabindex=\"-1\">' +\n '<div class=\"modal-dialog modal-lg\">' +\n '<div class=\"modal-content\">' +\n '<div class=\"modal-header\">' +\n '<h5 class=\"modal-title\"><i class=\"bi bi-server me-2\"></i>Volume Server Details: ' + server.address + '</h5>' +\n '<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\"></button>' +\n '</div>' +\n '<div class=\"modal-body\">' +\n '<div class=\"row\">' +\n '<div class=\"col-md-6\">' +\n '<h6 class=\"text-primary\"><i class=\"bi bi-info-circle me-1\"></i>Basic Information</h6>' +\n '<table class=\"table table-sm\">' +\n '<tr><td><strong>Server ID:</strong></td><td><code>' + server.id + '</code></td></tr>' +\n '<tr><td><strong>Address:</strong></td><td>' + server.address + '</td></tr>' +\n '<tr><td><strong>Public URL:</strong></td><td>' + server.publicUrl + '</td></tr>' +\n '<tr><td><strong>Data Center:</strong></td><td><span class=\"badge bg-light text-dark\">' + server.datacenter + '</span></td></tr>' +\n '<tr><td><strong>Rack:</strong></td><td><span class=\"badge bg-light text-dark\">' + server.rack + '</span></td></tr>' +\n '<tr><td><strong>Last Heartbeat:</strong></td><td>' + server.lastHeartbeat + '</td></tr>' +\n '</table>' +\n '</div>' +\n '<div class=\"col-md-6\">' +\n '<h6 class=\"text-primary\"><i class=\"bi bi-bar-chart me-1\"></i>Usage Statistics</h6>' +\n '<table class=\"table table-sm\">' +\n '<tr><td><strong>Volumes:</strong></td><td>' +\n '<div class=\"d-flex align-items-center\">' +\n '<div class=\"progress me-2\" style=\"width: 100px; height: 20px;\">' +\n '<div class=\"progress-bar\" role=\"progressbar\" style=\"width: ' + volumePercent + '%\"></div>' +\n '</div>' +\n '<span>' + server.volumes + '/' + server.maxVolumes + ' (' + volumePercent + '%)</span>' +\n '</div>' +\n '</td></tr>' +\n '<tr><td><strong>Disk Usage:</strong></td><td>' +\n '<div class=\"d-flex align-items-center\">' +\n '<div class=\"progress me-2\" style=\"width: 100px; height: 20px;\">' +\n '<div class=\"progress-bar\" role=\"progressbar\" style=\"width: ' + diskPercent + '%\"></div>' +\n '</div>' +\n '<span>' + formatBytes(server.diskUsage) + '/' + formatBytes(server.diskCapacity) + ' (' + diskPercent + '%)</span>' +\n '</div>' +\n '</td></tr>' +\n '<tr><td><strong>Available Space:</strong></td><td>' + formatBytes(server.diskCapacity - server.diskUsage) + '</td></tr>' +\n Line truncated
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user