aboutsummaryrefslogtreecommitdiff
path: root/weed/admin/handlers/admin_handlers.go
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2025-07-06 13:57:02 -0700
committerGitHub <noreply@github.com>2025-07-06 13:57:02 -0700
commitaa668523047c273dc4065dc0f40852efcdf9e9f0 (patch)
tree87f7f145d699cf1824c8251ae71435462bfd3318 /weed/admin/handlers/admin_handlers.go
parent302e62d4805c60f3fdb6620b01e85859d68078ed (diff)
downloadseaweedfs-aa668523047c273dc4065dc0f40852efcdf9e9f0.tar.xz
seaweedfs-aa668523047c273dc4065dc0f40852efcdf9e9f0.zip
Admin UI add maintenance menu (#6944)
* add ui for maintenance * valid config loading. fix workers page. * refactor * grpc between admin and workers * add a long-running bidirectional grpc call between admin and worker * use the grpc call to heartbeat * use the grpc call to communicate * worker can remove the http client * admin uses http port + 10000 as its default grpc port * one task one package * handles connection failures gracefully with exponential backoff * grpc with insecure tls * grpc with optional tls * fix detecting tls * change time config from nano seconds to seconds * add tasks with 3 interfaces * compiles reducing hard coded * remove a couple of tasks * remove hard coded references * reduce hard coded values * remove hard coded values * remove hard coded from templ * refactor maintenance package * fix import cycle * simplify * simplify * auto register * auto register factory * auto register task types * self register types * refactor * simplify * remove one task * register ui * lazy init executor factories * use registered task types * DefaultWorkerConfig remove hard coded task types * remove more hard coded * implement get maintenance task * dynamic task configuration * "System Settings" should only have system level settings * adjust menu for tasks * ensure menu not collapsed * render job configuration well * use templ for ui of task configuration * fix ordering * fix bugs * saving duration in seconds * use value and unit for duration * Delete WORKER_REFACTORING_PLAN.md * Delete maintenance.json * Delete custom_worker_example.go * remove address from workers * remove old code from ec task * remove creating collection button * reconnect with exponential backoff * worker use security.toml * start admin server with tls info from security.toml * fix "weed admin" cli description
Diffstat (limited to 'weed/admin/handlers/admin_handlers.go')
-rw-r--r--weed/admin/handlers/admin_handlers.go53
1 files changed, 51 insertions, 2 deletions
diff --git a/weed/admin/handlers/admin_handlers.go b/weed/admin/handlers/admin_handlers.go
index 541bb6293..03d156d08 100644
--- a/weed/admin/handlers/admin_handlers.go
+++ b/weed/admin/handlers/admin_handlers.go
@@ -17,6 +17,7 @@ type AdminHandlers struct {
clusterHandlers *ClusterHandlers
fileBrowserHandlers *FileBrowserHandlers
userHandlers *UserHandlers
+ maintenanceHandlers *MaintenanceHandlers
}
// NewAdminHandlers creates a new instance of AdminHandlers
@@ -25,12 +26,14 @@ func NewAdminHandlers(adminServer *dash.AdminServer) *AdminHandlers {
clusterHandlers := NewClusterHandlers(adminServer)
fileBrowserHandlers := NewFileBrowserHandlers(adminServer)
userHandlers := NewUserHandlers(adminServer)
+ maintenanceHandlers := NewMaintenanceHandlers(adminServer)
return &AdminHandlers{
adminServer: adminServer,
authHandlers: authHandlers,
clusterHandlers: clusterHandlers,
fileBrowserHandlers: fileBrowserHandlers,
userHandlers: userHandlers,
+ maintenanceHandlers: maintenanceHandlers,
}
}
@@ -69,13 +72,22 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, username,
protected.GET("/cluster/volumes/:id/:server", h.clusterHandlers.ShowVolumeDetails)
protected.GET("/cluster/collections", h.clusterHandlers.ShowClusterCollections)
+ // Maintenance system routes
+ protected.GET("/maintenance", h.maintenanceHandlers.ShowMaintenanceQueue)
+ protected.GET("/maintenance/workers", h.maintenanceHandlers.ShowMaintenanceWorkers)
+ protected.GET("/maintenance/config", h.maintenanceHandlers.ShowMaintenanceConfig)
+ protected.POST("/maintenance/config", h.maintenanceHandlers.UpdateMaintenanceConfig)
+ protected.GET("/maintenance/config/:taskType", h.maintenanceHandlers.ShowTaskConfig)
+ protected.POST("/maintenance/config/:taskType", h.maintenanceHandlers.UpdateTaskConfig)
+
// API routes for AJAX calls
api := protected.Group("/api")
{
api.GET("/cluster/topology", h.clusterHandlers.GetClusterTopology)
api.GET("/cluster/masters", h.clusterHandlers.GetMasters)
api.GET("/cluster/volumes", h.clusterHandlers.GetVolumeServers)
- api.GET("/admin", h.adminServer.ShowAdmin) // JSON API for admin data
+ api.GET("/admin", h.adminServer.ShowAdmin) // JSON API for admin data
+ api.GET("/config", h.adminServer.GetConfigInfo) // Configuration information
// S3 API routes
s3Api := api.Group("/s3")
@@ -118,6 +130,20 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, username,
{
volumeApi.POST("/:id/:server/vacuum", h.clusterHandlers.VacuumVolume)
}
+
+ // Maintenance API routes
+ maintenanceApi := api.Group("/maintenance")
+ {
+ maintenanceApi.POST("/scan", h.adminServer.TriggerMaintenanceScan)
+ maintenanceApi.GET("/tasks", h.adminServer.GetMaintenanceTasks)
+ maintenanceApi.GET("/tasks/:id", h.adminServer.GetMaintenanceTask)
+ maintenanceApi.POST("/tasks/:id/cancel", h.adminServer.CancelMaintenanceTask)
+ maintenanceApi.GET("/workers", h.adminServer.GetMaintenanceWorkersAPI)
+ maintenanceApi.GET("/workers/:id", h.adminServer.GetMaintenanceWorker)
+ maintenanceApi.GET("/stats", h.adminServer.GetMaintenanceStats)
+ maintenanceApi.GET("/config", h.adminServer.GetMaintenanceConfigAPI)
+ maintenanceApi.PUT("/config", h.adminServer.UpdateMaintenanceConfigAPI)
+ }
}
} else {
// No authentication required - all routes are public
@@ -140,13 +166,22 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, username,
r.GET("/cluster/volumes/:id/:server", h.clusterHandlers.ShowVolumeDetails)
r.GET("/cluster/collections", h.clusterHandlers.ShowClusterCollections)
+ // Maintenance system routes
+ r.GET("/maintenance", h.maintenanceHandlers.ShowMaintenanceQueue)
+ r.GET("/maintenance/workers", h.maintenanceHandlers.ShowMaintenanceWorkers)
+ r.GET("/maintenance/config", h.maintenanceHandlers.ShowMaintenanceConfig)
+ r.POST("/maintenance/config", h.maintenanceHandlers.UpdateMaintenanceConfig)
+ r.GET("/maintenance/config/:taskType", h.maintenanceHandlers.ShowTaskConfig)
+ r.POST("/maintenance/config/:taskType", h.maintenanceHandlers.UpdateTaskConfig)
+
// API routes for AJAX calls
api := r.Group("/api")
{
api.GET("/cluster/topology", h.clusterHandlers.GetClusterTopology)
api.GET("/cluster/masters", h.clusterHandlers.GetMasters)
api.GET("/cluster/volumes", h.clusterHandlers.GetVolumeServers)
- api.GET("/admin", h.adminServer.ShowAdmin) // JSON API for admin data
+ api.GET("/admin", h.adminServer.ShowAdmin) // JSON API for admin data
+ api.GET("/config", h.adminServer.GetConfigInfo) // Configuration information
// S3 API routes
s3Api := api.Group("/s3")
@@ -189,6 +224,20 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, username,
{
volumeApi.POST("/:id/:server/vacuum", h.clusterHandlers.VacuumVolume)
}
+
+ // Maintenance API routes
+ maintenanceApi := api.Group("/maintenance")
+ {
+ maintenanceApi.POST("/scan", h.adminServer.TriggerMaintenanceScan)
+ maintenanceApi.GET("/tasks", h.adminServer.GetMaintenanceTasks)
+ maintenanceApi.GET("/tasks/:id", h.adminServer.GetMaintenanceTask)
+ maintenanceApi.POST("/tasks/:id/cancel", h.adminServer.CancelMaintenanceTask)
+ maintenanceApi.GET("/workers", h.adminServer.GetMaintenanceWorkersAPI)
+ maintenanceApi.GET("/workers/:id", h.adminServer.GetMaintenanceWorker)
+ maintenanceApi.GET("/stats", h.adminServer.GetMaintenanceStats)
+ maintenanceApi.GET("/config", h.adminServer.GetMaintenanceConfigAPI)
+ maintenanceApi.PUT("/config", h.adminServer.UpdateMaintenanceConfigAPI)
+ }
}
}
}