diff --git a/weed/admin/dash/admin_data.go b/weed/admin/dash/admin_data.go index 71abedaad..fef922058 100644 --- a/weed/admin/dash/admin_data.go +++ b/weed/admin/dash/admin_data.go @@ -30,6 +30,7 @@ type AdminData struct { VolumeServers []VolumeServer `json:"volume_servers"` FilerNodes []FilerNode `json:"filer_nodes"` MessageBrokers []MessageBrokerNode `json:"message_brokers"` + S3Nodes []S3Node `json:"s3_nodes"` DataCenters []DataCenter `json:"datacenters"` LastUpdated time.Time `json:"last_updated"` @@ -115,6 +116,12 @@ type MessageBrokerNode struct { LastUpdated time.Time `json:"last_updated"` } +type S3Node struct { + Address string `json:"address"` + DataCenter string `json:"datacenter"` + LastUpdated time.Time `json:"last_updated"` +} + // GetAdminData retrieves admin data as a struct (for reuse by both JSON and HTML handlers) func (s *AdminServer) GetAdminData(username string) (AdminData, error) { if username == "" { @@ -144,6 +151,9 @@ func (s *AdminServer) GetAdminData(username string) (AdminData, error) { // Get message broker nodes status messageBrokers := s.getMessageBrokerNodesStatus() + // Get S3 nodes status + s3Nodes := s.getS3NodesStatus() + // Get volume size limit from master configuration var volumeSizeLimitMB uint64 = 30000 // Default to 30GB err = s.WithMasterClient(func(client master_pb.SeaweedClient) error { @@ -183,6 +193,7 @@ func (s *AdminServer) GetAdminData(username string) (AdminData, error) { VolumeServers: volumeServersData.VolumeServers, FilerNodes: filerNodes, MessageBrokers: messageBrokers, + S3Nodes: s3Nodes, DataCenters: topology.DataCenters, LastUpdated: topology.UpdatedAt, TotalEcVolumes: totalEcVolumes, @@ -360,3 +371,43 @@ func (s *AdminServer) getMessageBrokerNodesStatus() []MessageBrokerNode { return messageBrokers } + +// getS3NodesStatus checks status of all S3 nodes using master's ListClusterNodes +func (s *AdminServer) getS3NodesStatus() []S3Node { + var s3Nodes []S3Node + + // Get S3 nodes from master using ListClusterNodes + err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { + resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ + ClientType: cluster.S3Type, + }) + if err != nil { + return err + } + + // Process each S3 node + for _, node := range resp.ClusterNodes { + s3Nodes = append(s3Nodes, S3Node{ + Address: pb.ServerAddress(node.Address).ToHttpAddress(), + DataCenter: node.DataCenter, + LastUpdated: time.Now(), + }) + } + + return nil + }) + + if err != nil { + currentMaster := s.masterClient.GetMaster(context.Background()) + glog.Errorf("Failed to get S3 nodes from master %s: %v", currentMaster, err) + // Return empty list if we can't get S3 info from master + return []S3Node{} + } + + // Sort S3 nodes by address for consistent ordering on page refresh + sort.Slice(s3Nodes, func(i, j int) bool { + return s3Nodes[i].Address < s3Nodes[j].Address + }) + + return s3Nodes +} diff --git a/weed/admin/dash/admin_server.go b/weed/admin/dash/admin_server.go index 492705d4c..e8fb2bcdf 100644 --- a/weed/admin/dash/admin_server.go +++ b/weed/admin/dash/admin_server.go @@ -1189,6 +1189,52 @@ func (s *AdminServer) GetClusterBrokers() (*ClusterBrokersData, error) { }, nil } +// GetClusterS3Servers retrieves cluster S3 servers data +func (s *AdminServer) GetClusterS3Servers() (*ClusterS3ServersData, error) { + var s3Servers []S3ServerInfo + + // Get S3 server information from master using ListClusterNodes + err := s.WithMasterClient(func(client master_pb.SeaweedClient) error { + resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{ + ClientType: cluster.S3Type, + }) + if err != nil { + return err + } + + // Process each S3 server node + for _, node := range resp.ClusterNodes { + createdAt := time.Unix(0, node.CreatedAtNs) + + s3ServerInfo := S3ServerInfo{ + Address: pb.ServerAddress(node.Address).ToHttpAddress(), + DataCenter: node.DataCenter, + Version: node.Version, + CreatedAt: createdAt, + } + + s3Servers = append(s3Servers, s3ServerInfo) + } + + return nil + }) + + if err != nil { + return nil, fmt.Errorf("failed to get S3 server nodes from master: %w", err) + } + + // Sort S3 servers by address for consistent ordering on page refresh + sort.Slice(s3Servers, func(i, j int) bool { + return s3Servers[i].Address < s3Servers[j].Address + }) + + return &ClusterS3ServersData{ + S3Servers: s3Servers, + TotalS3Servers: len(s3Servers), + LastUpdated: time.Now(), + }, nil +} + // GetAllFilers method moved to client_management.go // GetVolumeDetails method moved to volume_management.go diff --git a/weed/admin/dash/types.go b/weed/admin/dash/types.go index 90af7a3af..e4212347d 100644 --- a/weed/admin/dash/types.go +++ b/weed/admin/dash/types.go @@ -310,6 +310,20 @@ type ClusterBrokersData struct { LastUpdated time.Time `json:"last_updated"` } +type S3ServerInfo struct { + Address string `json:"address"` + DataCenter string `json:"datacenter"` + Version string `json:"version"` + CreatedAt time.Time `json:"created_at"` +} + +type ClusterS3ServersData struct { + Username string `json:"username"` + S3Servers []S3ServerInfo `json:"s3_servers"` + TotalS3Servers int `json:"total_s3_servers"` + LastUpdated time.Time `json:"last_updated"` +} + type TopicInfo struct { Name string `json:"name"` Partitions int `json:"partitions"` diff --git a/weed/admin/handlers/admin_handlers.go b/weed/admin/handlers/admin_handlers.go index e8cf46721..4ac8f717f 100644 --- a/weed/admin/handlers/admin_handlers.go +++ b/weed/admin/handlers/admin_handlers.go @@ -125,6 +125,7 @@ func (h *AdminHandlers) registerUIRoutes(r *mux.Router) { // Cluster management routes r.HandleFunc("/cluster/masters", h.clusterHandlers.ShowClusterMasters).Methods(http.MethodGet) r.HandleFunc("/cluster/filers", h.clusterHandlers.ShowClusterFilers).Methods(http.MethodGet) + r.HandleFunc("/cluster/s3", h.clusterHandlers.ShowClusterS3Servers).Methods(http.MethodGet) r.HandleFunc("/cluster/volume-servers", h.clusterHandlers.ShowClusterVolumeServers).Methods(http.MethodGet) // Storage management routes diff --git a/weed/admin/handlers/cluster_handlers.go b/weed/admin/handlers/cluster_handlers.go index b3bcc4fe3..ae454b1a0 100644 --- a/weed/admin/handlers/cluster_handlers.go +++ b/weed/admin/handlers/cluster_handlers.go @@ -312,6 +312,29 @@ func (h *ClusterHandlers) ShowClusterFilers(w http.ResponseWriter, r *http.Reque } } +// ShowClusterS3Servers renders the cluster S3 servers page +func (h *ClusterHandlers) ShowClusterS3Servers(w http.ResponseWriter, r *http.Request) { + // Get cluster S3 servers data + s3ServersData, err := h.adminServer.GetClusterS3Servers() + if err != nil { + writeJSONError(w, http.StatusInternalServerError, "Failed to get cluster S3 servers: "+err.Error()) + return + } + + username := usernameOrDefault(r) + s3ServersData.Username = username + + // Render HTML template + w.Header().Set("Content-Type", "text/html") + s3ServersComponent := app.ClusterS3Servers(*s3ServersData) + viewCtx := layout.NewViewContext(r, username, dash.CSRFTokenFromContext(r.Context())) + layoutComponent := layout.Layout(viewCtx, s3ServersComponent) + if err := layoutComponent.Render(r.Context(), w); err != nil { + writeJSONError(w, http.StatusInternalServerError, "Failed to render template: "+err.Error()) + return + } +} + // GetClusterTopology returns the cluster topology as JSON func (h *ClusterHandlers) GetClusterTopology(w http.ResponseWriter, r *http.Request) { topology, err := h.adminServer.GetClusterTopology() diff --git a/weed/admin/view/app/admin.templ b/weed/admin/view/app/admin.templ index 27e72719f..fa2c1fe19 100644 --- a/weed/admin/view/app/admin.templ +++ b/weed/admin/view/app/admin.templ @@ -204,7 +204,7 @@ templ Admin(data dash.AdminData) {
-
+
{fmt.Sprintf("%d", len(data.MasterNodes))}
@@ -212,7 +212,7 @@ templ Admin(data dash.AdminData) {
-
+
{fmt.Sprintf("%d", len(data.VolumeServers))}
@@ -220,7 +220,7 @@ templ Admin(data dash.AdminData) {
-
+
{fmt.Sprintf("%d", len(data.FilerNodes))}
@@ -228,7 +228,15 @@ templ Admin(data dash.AdminData) {
-
+
+
+
+
{fmt.Sprintf("%d", len(data.S3Nodes))}
+ S3 Servers +
+
+
+
{fmt.Sprintf("%d", len(data.MessageBrokers))}
@@ -384,6 +392,58 @@ templ Admin(data dash.AdminData) {
+ +
+
+
+
+
+ S3 Servers +
+ +
+
+
+ + + + + + + + + + for _, s3Node := range data.S3Nodes { + + + + + + } + if len(data.S3Nodes) == 0 { + + + + } + +
AddressData CenterLast Updated
{s3Node.Address}{s3Node.DataCenter}{s3Node.LastUpdated.Format("2006-01-02 15:04:05")}
+ + No S3 servers found +
+
+
+
+
+
+
diff --git a/weed/admin/view/app/admin_templ.go b/weed/admin/view/app/admin_templ.go index 217b519d9..596473e9a 100644 --- a/weed/admin/view/app/admin_templ.go +++ b/weed/admin/view/app/admin_templ.go @@ -176,7 +176,7 @@ func Admin(data dash.AdminData) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
Cluster
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
Cluster
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -189,7 +189,7 @@ func Admin(data dash.AdminData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
Masters
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
Masters
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -202,7 +202,7 @@ func Admin(data dash.AdminData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
Volume Servers
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
Volume Servers
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -215,303 +215,303 @@ func Admin(data dash.AdminData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
Filers
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
Filers
") 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", len(data.MessageBrokers))) + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(data.S3Nodes))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 234, Col: 88} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 234, Col: 81} } _, 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, "
Message Brokers
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\">View DetailsTopology View
IDAddressData CenterRackVolumesEC ShardsCapacity
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, vs := range data.VolumeServers { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, " / ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var28 string + templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(vs.DiskCapacity)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 316, Col: 107} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(data.VolumeServers) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "
IDAddressData CenterRackVolumesEC ShardsCapacity
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var17 string - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(vs.ID) + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(vs.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 281, Col: 54} - } - _, 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, 23, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" target=\"_blank\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var20 string - templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(vs.DataCenter) + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(vs.GetDisplayAddress()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 288, Col: 62} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 292, Col: 75} } _, 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, 26, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var21 string - templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(vs.Rack) + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(vs.DataCenter) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 289, Col: 56} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 296, Col: 62} } _, 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, 27, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var22 string - templ_7745c5c3_Var22, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("width: %d%%", calculatePercent(vs.Volumes, vs.MaxVolumes))) + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(vs.Rack) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 293, Col: 135} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 297, Col: 56} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var24 string + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/%d", vs.Volumes, vs.MaxVolumes)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 302, Col: 104} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if vs.EcShards > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var24 string - templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", vs.EcShards)) + var templ_7745c5c3_Var25 string + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", vs.EcShards)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 300, Col: 127} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 308, Col: 127} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if vs.EcVolumes > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "(") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "(") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var25 string - templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d vol", vs.EcVolumes)) + var templ_7745c5c3_Var26 string + templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d vol", vs.EcVolumes)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 302, Col: 119} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 310, Col: 119} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, ")") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, ")") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "-") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "-") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var26 string - templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(vs.DiskUsage)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 308, Col: 74} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, " / ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var27 string - templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(vs.DiskCapacity)) + templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(vs.DiskUsage)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 308, Col: 107} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 316, Col: 74} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "
No volume servers found
No volume servers found
Filer Nodes
Actions:
File Browser
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\">File BrowserTopology View
AddressData CenterRackLast Updated
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, filer := range data.FilerNodes { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(data.FilerNodes) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "
AddressData CenterRackLast Updated
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var31 string - templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(filer.Address) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 362, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 369, Col: 106} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\" target=\"_blank\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var32 string - templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(filer.DataCenter) + templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(filer.Address) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 366, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 370, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var33 string - templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(filer.Rack) + templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(filer.DataCenter) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 367, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 374, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { @@ -522,39 +522,120 @@ func Admin(data dash.AdminData) templ.Component { return templ_7745c5c3_Err } var templ_7745c5c3_Var34 string - templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(filer.LastUpdated.Format("2006-01-02 15:04:05")) + templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(filer.Rack) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 368, Col: 96} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 375, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var35 string + templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(filer.LastUpdated.Format("2006-01-02 15:04:05")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 376, Col: 96} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "
No filer nodes found
No filer nodes found
Last updated: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, s3Node := range data.S3Nodes { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if len(data.S3Nodes) == 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
AddressData CenterLast Updated
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var37 string + templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(s3Node.Address) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 426, Col: 63} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var38 string + templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(s3Node.DataCenter) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 427, Col: 66} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var39 string + templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(s3Node.LastUpdated.Format("2006-01-02 15:04:05")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/admin.templ`, Line: 428, Col: 97} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "
No S3 servers found
Last updated: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var40 string + templ_7745c5c3_Var40, 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/admin.templ`, Line: 452, Col: 81} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/cluster_s3_servers.templ b/weed/admin/view/app/cluster_s3_servers.templ new file mode 100644 index 000000000..2b464c535 --- /dev/null +++ b/weed/admin/view/app/cluster_s3_servers.templ @@ -0,0 +1,139 @@ +package app + +import ( + "fmt" + "github.com/seaweedfs/seaweedfs/weed/admin/dash" +) + +templ ClusterS3Servers(data dash.ClusterS3ServersData) { +
+

+ S3 Servers +

+
+
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+ Total S3 Servers +
+
+ { fmt.Sprintf("%d", data.TotalS3Servers) } +
+
+
+ +
+
+
+
+
+
+ + +
+
+
+ S3 Servers +
+
+
+ if len(data.S3Servers) > 0 { +
+ + + + + + + + + + + for _, s3Server := range data.S3Servers { + + + + + + + } + +
AddressVersionData CenterCreated At
+ { s3Server.Address } + + { s3Server.Version } + + { s3Server.DataCenter } + + if !s3Server.CreatedAt.IsZero() { + { s3Server.CreatedAt.Format("2006-01-02 15:04:05") } + } else { + N/A + } +
+
+ } else { +
+ +
No S3 Servers Found
+

No S3 servers are currently available in the cluster.

+
+ } +
+
+ + +
+
+ + + Last updated: { data.LastUpdated.Format("2006-01-02 15:04:05") } + +
+
+
+ + +} diff --git a/weed/admin/view/app/cluster_s3_servers_templ.go b/weed/admin/view/app/cluster_s3_servers_templ.go new file mode 100644 index 000000000..9fcf7ae07 --- /dev/null +++ b/weed/admin/view/app/cluster_s3_servers_templ.go @@ -0,0 +1,155 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.3.1001 +package app + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +import ( + "fmt" + "github.com/seaweedfs/seaweedfs/weed/admin/dash" +) + +func ClusterS3Servers(data dash.ClusterS3ServersData) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

S3 Servers

Total S3 Servers
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalS3Servers)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_s3_servers.templ`, Line: 34, Col: 49} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
S3 Servers
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if len(data.S3Servers) > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, s3Server := range data.S3Servers { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
AddressVersionData CenterCreated At
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(s3Server.Address) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_s3_servers.templ`, Line: 69, Col: 29} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(s3Server.Version) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_s3_servers.templ`, Line: 72, Col: 68} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(s3Server.DataCenter) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_s3_servers.templ`, Line: 75, Col: 71} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !s3Server.CreatedAt.IsZero() { + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(s3Server.CreatedAt.Format("2006-01-02 15:04:05")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/cluster_s3_servers.templ`, Line: 79, Col: 62} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "N/A") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
No S3 Servers Found

No S3 servers are currently available in the cluster.

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
Last updated: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, 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_s3_servers.templ`, Line: 104, Col: 67} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/weed/admin/view/layout/layout.templ b/weed/admin/view/layout/layout.templ index d013ed099..6ebc09336 100644 --- a/weed/admin/view/layout/layout.templ +++ b/weed/admin/view/layout/layout.templ @@ -32,7 +32,7 @@ templ Layout(view ViewContext, content templ.Component) { isStoragePage := strings.HasPrefix(currentPath, "/storage/volumes") || strings.HasPrefix(currentPath, "/storage/ec-shards") || strings.HasPrefix(currentPath, "/storage/collections") // Detect if we're on a cluster page (but not storage page) to keep submenu expanded - isClusterPage := (strings.HasPrefix(currentPath, "/cluster/masters") || strings.HasPrefix(currentPath, "/cluster/volume-servers") || strings.HasPrefix(currentPath, "/cluster/filers")) + isClusterPage := (strings.HasPrefix(currentPath, "/cluster/masters") || strings.HasPrefix(currentPath, "/cluster/volume-servers") || strings.HasPrefix(currentPath, "/cluster/filers") || strings.HasPrefix(currentPath, "/cluster/s3")) isDefaultWorkerPage := currentPath == "/plugin" || strings.HasPrefix(currentPath, "/plugin/configuration") || @@ -134,6 +134,11 @@ templ Layout(view ViewContext, content templ.Component) { Filers + diff --git a/weed/admin/view/layout/layout_templ.go b/weed/admin/view/layout/layout_templ.go index cc4053f83..3354d2ffb 100644 --- a/weed/admin/view/layout/layout_templ.go +++ b/weed/admin/view/layout/layout_templ.go @@ -65,7 +65,7 @@ func Layout(view ViewContext, content templ.Component) templ.Component { isStoragePage := strings.HasPrefix(currentPath, "/storage/volumes") || strings.HasPrefix(currentPath, "/storage/ec-shards") || strings.HasPrefix(currentPath, "/storage/collections") // Detect if we're on a cluster page (but not storage page) to keep submenu expanded - isClusterPage := (strings.HasPrefix(currentPath, "/cluster/masters") || strings.HasPrefix(currentPath, "/cluster/volume-servers") || strings.HasPrefix(currentPath, "/cluster/filers")) + isClusterPage := (strings.HasPrefix(currentPath, "/cluster/masters") || strings.HasPrefix(currentPath, "/cluster/volume-servers") || strings.HasPrefix(currentPath, "/cluster/filers") || strings.HasPrefix(currentPath, "/cluster/s3")) isDefaultWorkerPage := currentPath == "/plugin" || strings.HasPrefix(currentPath, "/plugin/configuration") || @@ -311,451 +311,464 @@ func Layout(view ViewContext, content templ.Component) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\">Filers
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\">Filers
  • S3 Servers
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - 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/layout/layout.templ`, Line: 1, Col: 0} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) + var templ_7745c5c3_Var21 = []any{"nav-link", templ.KV("collapsed", !isStoragePage)} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var21...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" href=\"#\" data-bs-toggle=\"collapse\" data-bs-target=\"#storageSubmenu\" aria-expanded=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "Storage ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" href=\"#\" data-bs-toggle=\"collapse\" data-bs-target=\"#storageSubmenu\" aria-expanded=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var23 = []any{"collapse", templ.KV("show", isStoragePage)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var23...) + var templ_7745c5c3_Var23 string + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%t", isStoragePage)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 146, Col: 207} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
    Storage ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var24 string - templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var23).String()) + var templ_7745c5c3_Var24 = []any{"collapse", templ.KV("show", isStoragePage)} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var24...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
  • OBJECT STORE
    OBJECT STORE
    MANAGEMENT
    MANAGEMENT
    WORKERS
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "
    WORKERS
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -763,108 +776,95 @@ func Layout(view ViewContext, content templ.Component) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "
    © ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var47 string - templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", time.Now().Year())) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 329, Col: 60} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, " SeaweedFS Admin v") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -907,140 +920,140 @@ func LoginForm(title string, errorMessage string, csrfToken string) templ.Compon }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var55 := templ.GetChildren(ctx) - if templ_7745c5c3_Var55 == nil { - templ_7745c5c3_Var55 = templ.NopComponent + templ_7745c5c3_Var56 := templ.GetChildren(ctx) + if templ_7745c5c3_Var56 == nil { + templ_7745c5c3_Var56 = templ.NopComponent } ctx = templ.ClearChildren(ctx) prefix := dash.URLPrefixFromContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var56 string - templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(title) + var templ_7745c5c3_Var57 string + templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 363, Col: 17} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, " - Login

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "\" rel=\"stylesheet\">

    Please sign in to continue

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "\" rel=\"stylesheet\">

    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var61 string + templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 382, Col: 57} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "

    Please sign in to continue

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if errorMessage != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var61 string - templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(errorMessage) + var templ_7745c5c3_Var62 string + templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(errorMessage) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 384, Col: 45} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layout/layout.templ`, Line: 389, Col: 45} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "\">
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/s3api/s3api_server.go b/weed/s3api/s3api_server.go index a41c15e89..53565dca2 100644 --- a/weed/s3api/s3api_server.go +++ b/weed/s3api/s3api_server.go @@ -173,7 +173,7 @@ func NewS3ApiServerWithStore(router *mux.Router, option *S3ApiServerOption, expl if clientHost == "0.0.0.0" || clientHost == "" { clientHost = util.DetectedHostAddress() } - masterClient = wdclient.NewMasterClient(option.GrpcDialOption, option.FilerGroup, cluster.S3Type, pb.ServerAddress(util.JoinHostPort(clientHost, option.GrpcPort)), "", "", *pb.NewServiceDiscoveryFromMap(masterMap)) + masterClient = wdclient.NewMasterClient(option.GrpcDialOption, option.FilerGroup, cluster.S3Type, pb.ServerAddress(util.JoinHostPort(clientHost, option.GrpcPort)), option.DataCenter, "", *pb.NewServiceDiscoveryFromMap(masterMap)) // Build the object-write lock client and subscribe to the master's // lock-ring updates BEFORE starting the master loop, so the initial // LockRingUpdate sent on connect isn't dropped (the master only delivers