140 lines
3.7 KiB
Go
140 lines
3.7 KiB
Go
package httpapp
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
// DashboardData represents aggregated dashboard statistics
|
|
type DashboardData struct {
|
|
Storage struct {
|
|
TotalCapacity uint64 `json:"total_capacity"`
|
|
TotalAllocated uint64 `json:"total_allocated"`
|
|
TotalAvailable uint64 `json:"total_available"`
|
|
PoolCount int `json:"pool_count"`
|
|
DatasetCount int `json:"dataset_count"`
|
|
ZVOLCount int `json:"zvol_count"`
|
|
SnapshotCount int `json:"snapshot_count"`
|
|
} `json:"storage"`
|
|
Services struct {
|
|
SMBShares int `json:"smb_shares"`
|
|
NFSExports int `json:"nfs_exports"`
|
|
ISCSITargets int `json:"iscsi_targets"`
|
|
SMBStatus bool `json:"smb_status"`
|
|
NFSStatus bool `json:"nfs_status"`
|
|
ISCSIStatus bool `json:"iscsi_status"`
|
|
} `json:"services"`
|
|
Jobs struct {
|
|
Total int `json:"total"`
|
|
Running int `json:"running"`
|
|
Completed int `json:"completed"`
|
|
Failed int `json:"failed"`
|
|
} `json:"jobs"`
|
|
RecentAuditLogs []map[string]interface{} `json:"recent_audit_logs,omitempty"`
|
|
}
|
|
|
|
// handleDashboardAPI returns aggregated dashboard data
|
|
func (a *App) handleDashboardAPI(w http.ResponseWriter, r *http.Request) {
|
|
data := DashboardData{}
|
|
|
|
// Storage statistics
|
|
pools, err := a.zfs.ListPools()
|
|
if err == nil {
|
|
data.Storage.PoolCount = len(pools)
|
|
for _, pool := range pools {
|
|
data.Storage.TotalCapacity += pool.Size
|
|
data.Storage.TotalAllocated += pool.Allocated
|
|
data.Storage.TotalAvailable += pool.Free
|
|
}
|
|
}
|
|
|
|
datasets, err := a.zfs.ListDatasets("")
|
|
if err == nil {
|
|
data.Storage.DatasetCount = len(datasets)
|
|
}
|
|
|
|
zvols, err := a.zfs.ListZVOLs("")
|
|
if err == nil {
|
|
data.Storage.ZVOLCount = len(zvols)
|
|
}
|
|
|
|
snapshots, err := a.zfs.ListSnapshots("")
|
|
if err == nil {
|
|
data.Storage.SnapshotCount = len(snapshots)
|
|
}
|
|
|
|
// Service statistics
|
|
// Sync from OS first to ensure accurate counts
|
|
if err := a.syncSMBSharesFromOS(); err != nil {
|
|
log.Printf("warning: failed to sync SMB shares from OS in dashboard: %v", err)
|
|
}
|
|
if err := a.syncNFSExportsFromOS(); err != nil {
|
|
log.Printf("warning: failed to sync NFS exports from OS in dashboard: %v", err)
|
|
}
|
|
|
|
smbShares := a.smbStore.List()
|
|
data.Services.SMBShares = len(smbShares)
|
|
|
|
nfsExports := a.nfsStore.List()
|
|
data.Services.NFSExports = len(nfsExports)
|
|
|
|
iscsiTargets := a.iscsiStore.List()
|
|
data.Services.ISCSITargets = len(iscsiTargets)
|
|
|
|
// Service status
|
|
if a.smbService != nil {
|
|
data.Services.SMBStatus, _ = a.smbService.GetStatus()
|
|
}
|
|
if a.nfsService != nil {
|
|
data.Services.NFSStatus, _ = a.nfsService.GetStatus()
|
|
}
|
|
if a.iscsiService != nil {
|
|
data.Services.ISCSIStatus, _ = a.iscsiService.GetStatus()
|
|
}
|
|
|
|
// Job statistics
|
|
allJobs := a.jobManager.List("")
|
|
data.Jobs.Total = len(allJobs)
|
|
for _, job := range allJobs {
|
|
switch job.Status {
|
|
case "running":
|
|
data.Jobs.Running++
|
|
case "completed":
|
|
data.Jobs.Completed++
|
|
case "failed":
|
|
data.Jobs.Failed++
|
|
}
|
|
}
|
|
|
|
// Recent audit logs (last 5)
|
|
auditLogs := a.auditStore.List("", "", "", 5)
|
|
data.RecentAuditLogs = make([]map[string]interface{}, 0, len(auditLogs))
|
|
for _, log := range auditLogs {
|
|
data.RecentAuditLogs = append(data.RecentAuditLogs, map[string]interface{}{
|
|
"id": log.ID,
|
|
"actor": log.Actor,
|
|
"action": log.Action,
|
|
"resource": log.Resource,
|
|
"result": log.Result,
|
|
"timestamp": log.Timestamp.Format("2006-01-02 15:04:05"),
|
|
})
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, data)
|
|
}
|
|
|
|
// formatBytes formats bytes to human-readable format
|
|
func formatBytes(bytes uint64) string {
|
|
const unit = 1024
|
|
if bytes < unit {
|
|
return fmt.Sprintf("%d B", bytes)
|
|
}
|
|
div, exp := int64(unit), 0
|
|
for n := bytes / unit; n >= unit; n /= unit {
|
|
div *= unit
|
|
exp++
|
|
}
|
|
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
|
|
}
|