diff options
| author | Chris Lu <chrislusf@users.noreply.github.com> | 2025-07-06 13:57:02 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-06 13:57:02 -0700 |
| commit | aa668523047c273dc4065dc0f40852efcdf9e9f0 (patch) | |
| tree | 87f7f145d699cf1824c8251ae71435462bfd3318 /weed/admin/handlers/admin_handlers.go | |
| parent | 302e62d4805c60f3fdb6620b01e85859d68078ed (diff) | |
| download | seaweedfs-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.go | 53 |
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) + } } } } |
