package daemon import ( "context" "banger/internal/api" "banger/internal/model" "banger/internal/system" ) func (d *Daemon) DashboardSummary(ctx context.Context) (api.DashboardSummary, error) { summary := api.DashboardSummary{ GeneratedAt: model.Now(), Sudo: api.SudoStatus{ Command: "sudo -v", }, } if err := system.CheckSudo(ctx); err != nil { summary.Sudo.Error = err.Error() } else { summary.Sudo.Available = true } if host, err := system.ReadHostResources(); err == nil { summary.Host.CPUCount = host.CPUCount summary.Host.TotalMemoryBytes = host.TotalMemoryBytes } if usage, err := system.ReadFilesystemUsage(d.layout.StateDir); err == nil { summary.Host.StateFilesystemTotalBytes = usage.TotalBytes summary.Host.StateFilesystemFreeBytes = usage.FreeBytes } images, err := d.store.ListImages(ctx) if err != nil { return api.DashboardSummary{}, err } for _, image := range images { summary.Banger.ImageCount++ if image.Managed { summary.Banger.ManagedImageCount++ } } vms, err := d.store.ListVMs(ctx) if err != nil { return api.DashboardSummary{}, err } for _, vm := range vms { summary.Banger.VMCount++ summary.Banger.ConfiguredVCPUCount += vm.Spec.VCPUCount summary.Banger.ConfiguredMemoryBytes += int64(vm.Spec.MemoryMiB) * 1024 * 1024 summary.Banger.ConfiguredDiskBytes += vm.Spec.WorkDiskSizeBytes summary.Banger.UsedSystemOverlayBytes += vm.Stats.SystemOverlayBytes summary.Banger.UsedWorkDiskBytes += vm.Stats.WorkDiskBytes if vm.State == model.VMStateRunning && system.ProcessRunning(vm.Runtime.PID, vm.Runtime.APISockPath) { summary.Banger.RunningVMCount++ summary.Banger.RunningCPUPercent += vm.Stats.CPUPercent summary.Banger.RunningRSSBytes += vm.Stats.RSSBytes summary.Banger.RunningVSZBytes += vm.Stats.VSZBytes } } return summary, nil }