mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-17 21:08:25 +08:00
644 lines
18 KiB
Go
644 lines
18 KiB
Go
package service
|
|
|
|
import (
|
|
"cmp"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
network "net"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
|
"github.com/1Panel-dev/1Panel/agent/app/model"
|
|
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
|
"github.com/1Panel-dev/1Panel/agent/buserr"
|
|
"github.com/1Panel-dev/1Panel/agent/constant"
|
|
"github.com/1Panel-dev/1Panel/agent/global"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/gpu"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/xpu"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/controller"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/copier"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/psutil"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/shirou/gopsutil/v4/disk"
|
|
"github.com/shirou/gopsutil/v4/load"
|
|
"github.com/shirou/gopsutil/v4/mem"
|
|
"github.com/shirou/gopsutil/v4/net"
|
|
)
|
|
|
|
type DashboardService struct{}
|
|
|
|
type IDashboardService interface {
|
|
LoadOsInfo() (*dto.OsInfo, error)
|
|
LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error)
|
|
LoadCurrentInfoForNode() *dto.NodeCurrent
|
|
LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent
|
|
LoadTopCPU() []dto.Process
|
|
LoadTopMem() []dto.Process
|
|
|
|
LoadQuickOptions() []dto.QuickJump
|
|
ChangeQuick(req dto.ChangeQuicks) error
|
|
|
|
LoadAppLauncher(ctx *gin.Context) ([]dto.AppLauncher, error)
|
|
ChangeShow(req dto.SettingUpdate) error
|
|
ListLauncherOption(filter string) ([]dto.LauncherOption, error)
|
|
Restart(operation string) error
|
|
}
|
|
|
|
func NewIDashboardService() IDashboardService {
|
|
return &DashboardService{}
|
|
}
|
|
|
|
func (u *DashboardService) Restart(operation string) error {
|
|
switch operation {
|
|
case "system":
|
|
{
|
|
go func() {
|
|
if err := cmd.RunDefaultBashCf("%s reboot", cmd.SudoHandleCmd()); err != nil {
|
|
global.LOG.Errorf("handle reboot failed, %v", err)
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
case "1panel-agent":
|
|
controller.RestartPanel(false, true, false)
|
|
return nil
|
|
case "1panel":
|
|
controller.RestartPanel(true, true, false)
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("handle restart operation %s failed, err: nonsupport such operation", operation)
|
|
}
|
|
}
|
|
|
|
func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) {
|
|
var baseInfo dto.OsInfo
|
|
hostInfo, err := psutil.HOST.GetHostInfo(false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
baseInfo.OS = hostInfo.OS
|
|
baseInfo.Platform = hostInfo.Platform
|
|
baseInfo.PlatformFamily = hostInfo.PlatformFamily
|
|
baseInfo.KernelArch = hostInfo.KernelArch
|
|
baseInfo.KernelVersion = hostInfo.KernelVersion
|
|
baseInfo.PrettyDistro = psutil.HOST.GetDistro()
|
|
|
|
diskInfo, err := psutil.DISK.GetUsage(global.Dir.BaseDir, false)
|
|
if err == nil {
|
|
baseInfo.DiskSize = int64(diskInfo.Free)
|
|
}
|
|
|
|
if baseInfo.KernelArch == "armv7l" {
|
|
baseInfo.KernelArch = "armv7"
|
|
}
|
|
if baseInfo.KernelArch == "x86_64" {
|
|
baseInfo.KernelArch = "amd64"
|
|
}
|
|
return &baseInfo, nil
|
|
}
|
|
|
|
func (u *DashboardService) LoadCurrentInfoForNode() *dto.NodeCurrent {
|
|
var currentInfo dto.NodeCurrent
|
|
|
|
currentInfo.CPUTotal, _ = psutil.CPUInfo.GetLogicalCores(false)
|
|
|
|
cpuUsedPercent, perCore, cpuDetailedPercent := psutil.CPU.GetCPUUsage()
|
|
if len(perCore) == 0 {
|
|
currentInfo.CPUTotal = psutil.CPU.NumCPU()
|
|
} else {
|
|
currentInfo.CPUTotal = len(perCore)
|
|
}
|
|
currentInfo.CPUUsedPercent = cpuUsedPercent
|
|
currentInfo.CPUUsed = cpuUsedPercent * 0.01 * float64(currentInfo.CPUTotal)
|
|
currentInfo.CPUDetailedPercent = cpuDetailedPercent
|
|
|
|
loadInfo, _ := load.Avg()
|
|
currentInfo.Load1 = loadInfo.Load1
|
|
currentInfo.Load5 = loadInfo.Load5
|
|
currentInfo.Load15 = loadInfo.Load15
|
|
currentInfo.LoadUsagePercent = loadInfo.Load1 / (float64(currentInfo.CPUTotal*2) * 0.75) * 100
|
|
|
|
memoryInfo, _ := mem.VirtualMemory()
|
|
currentInfo.MemoryTotal = memoryInfo.Total
|
|
currentInfo.MemoryAvailable = memoryInfo.Available
|
|
currentInfo.MemoryUsed = memoryInfo.Used
|
|
currentInfo.MemoryUsedPercent = memoryInfo.UsedPercent
|
|
|
|
swapInfo, _ := mem.SwapMemory()
|
|
currentInfo.SwapMemoryTotal = swapInfo.Total
|
|
currentInfo.SwapMemoryAvailable = swapInfo.Free
|
|
currentInfo.SwapMemoryUsed = swapInfo.Used
|
|
currentInfo.SwapMemoryUsedPercent = swapInfo.UsedPercent
|
|
|
|
return ¤tInfo
|
|
}
|
|
|
|
func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) {
|
|
var baseInfo dto.DashboardBase
|
|
hostInfo, err := psutil.HOST.GetHostInfo(false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ss, _ := json.Marshal(hostInfo)
|
|
baseInfo = dto.DashboardBase{
|
|
Hostname: hostInfo.Hostname,
|
|
OS: hostInfo.OS,
|
|
Platform: hostInfo.Platform,
|
|
PlatformFamily: hostInfo.PlatformFamily,
|
|
PlatformVersion: hostInfo.PlatformVersion,
|
|
PrettyDistro: psutil.HOST.GetDistro(),
|
|
KernelArch: hostInfo.KernelArch,
|
|
KernelVersion: hostInfo.KernelVersion,
|
|
VirtualizationSystem: string(ss),
|
|
IpV4Addr: loadOutboundIP(),
|
|
SystemProxy: "noProxy",
|
|
}
|
|
|
|
if proxy := cmp.Or(os.Getenv("http_proxy"), os.Getenv("HTTP_PROXY")); proxy != "" {
|
|
baseInfo.SystemProxy = proxy
|
|
}
|
|
|
|
loadQuickJump(&baseInfo)
|
|
|
|
cpuInfo, err := psutil.CPUInfo.GetCPUInfo(false)
|
|
if err == nil && len(cpuInfo) > 0 {
|
|
baseInfo.CPUModelName = cpuInfo[0].ModelName
|
|
}
|
|
|
|
baseInfo.CPUCores, _ = psutil.CPUInfo.GetPhysicalCores(false)
|
|
baseInfo.CPULogicalCores, _ = psutil.CPUInfo.GetLogicalCores(false)
|
|
baseInfo.CPUMhz = cpuInfo[0].Mhz
|
|
|
|
baseInfo.CurrentInfo = *u.LoadCurrentInfo(ioOption, netOption)
|
|
return &baseInfo, nil
|
|
}
|
|
|
|
func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent {
|
|
var currentInfo dto.DashboardCurrent
|
|
hostInfo, _ := psutil.HOST.GetHostInfo(false)
|
|
currentInfo.Uptime = hostInfo.Uptime
|
|
currentInfo.TimeSinceUptime = time.Unix(int64(hostInfo.BootTime), 0).Format(constant.DateTimeLayout)
|
|
currentInfo.Procs = hostInfo.Procs
|
|
currentInfo.CPUTotal, _ = psutil.CPUInfo.GetLogicalCores(false)
|
|
|
|
cpuUsedPercent, perCore, cpuDetailedPercent := psutil.CPU.GetCPUUsage()
|
|
if len(perCore) == 0 {
|
|
currentInfo.CPUTotal = psutil.CPU.NumCPU()
|
|
} else {
|
|
currentInfo.CPUTotal = len(perCore)
|
|
}
|
|
currentInfo.CPUPercent = perCore
|
|
currentInfo.CPUUsedPercent = cpuUsedPercent
|
|
currentInfo.CPUUsed = cpuUsedPercent * 0.01 * float64(currentInfo.CPUTotal)
|
|
currentInfo.CPUDetailedPercent = cpuDetailedPercent
|
|
|
|
loadInfo, _ := load.Avg()
|
|
currentInfo.Load1 = loadInfo.Load1
|
|
currentInfo.Load5 = loadInfo.Load5
|
|
currentInfo.Load15 = loadInfo.Load15
|
|
currentInfo.LoadUsagePercent = loadInfo.Load1 / (float64(currentInfo.CPUTotal*2) * 0.75) * 100
|
|
|
|
memoryInfo, _ := mem.VirtualMemory()
|
|
currentInfo.MemoryTotal = memoryInfo.Total
|
|
currentInfo.MemoryUsed = memoryInfo.Used
|
|
currentInfo.MemoryFree = memoryInfo.Free
|
|
currentInfo.MemoryCache = memoryInfo.Cached + memoryInfo.Buffers
|
|
currentInfo.MemoryShard = memoryInfo.Shared
|
|
currentInfo.MemoryAvailable = memoryInfo.Available
|
|
currentInfo.MemoryUsedPercent = memoryInfo.UsedPercent
|
|
|
|
swapInfo, _ := mem.SwapMemory()
|
|
currentInfo.SwapMemoryTotal = swapInfo.Total
|
|
currentInfo.SwapMemoryAvailable = swapInfo.Free
|
|
currentInfo.SwapMemoryUsed = swapInfo.Used
|
|
currentInfo.SwapMemoryUsedPercent = swapInfo.UsedPercent
|
|
|
|
currentInfo.DiskData = loadDiskInfo()
|
|
currentInfo.GPUData = loadGPUInfo()
|
|
currentInfo.XPUData = loadXpuInfo()
|
|
|
|
if ioOption == "all" {
|
|
diskInfo, _ := disk.IOCounters()
|
|
for _, state := range diskInfo {
|
|
currentInfo.IOReadBytes += state.ReadBytes
|
|
currentInfo.IOWriteBytes += state.WriteBytes
|
|
currentInfo.IOCount += (state.ReadCount + state.WriteCount)
|
|
currentInfo.IOReadTime += state.ReadTime
|
|
currentInfo.IOWriteTime += state.WriteTime
|
|
}
|
|
} else {
|
|
diskInfo, _ := disk.IOCounters(ioOption)
|
|
for _, state := range diskInfo {
|
|
currentInfo.IOReadBytes += state.ReadBytes
|
|
currentInfo.IOWriteBytes += state.WriteBytes
|
|
currentInfo.IOCount += (state.ReadCount + state.WriteCount)
|
|
currentInfo.IOReadTime += state.ReadTime
|
|
currentInfo.IOWriteTime += state.WriteTime
|
|
}
|
|
}
|
|
|
|
if netOption == "all" {
|
|
netInfo, _ := net.IOCounters(false)
|
|
if len(netInfo) != 0 {
|
|
currentInfo.NetBytesSent = netInfo[0].BytesSent
|
|
currentInfo.NetBytesRecv = netInfo[0].BytesRecv
|
|
}
|
|
} else {
|
|
netInfo, _ := net.IOCounters(true)
|
|
for _, state := range netInfo {
|
|
if state.Name == netOption {
|
|
currentInfo.NetBytesSent = state.BytesSent
|
|
currentInfo.NetBytesRecv = state.BytesRecv
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
currentInfo.ShotTime = time.Now()
|
|
return ¤tInfo
|
|
}
|
|
|
|
func (u *DashboardService) LoadTopCPU() []dto.Process {
|
|
return loadTopCPU()
|
|
}
|
|
|
|
func (u *DashboardService) LoadTopMem() []dto.Process {
|
|
return loadTopMem()
|
|
}
|
|
|
|
func (u *DashboardService) LoadAppLauncher(ctx *gin.Context) ([]dto.AppLauncher, error) {
|
|
var data []dto.AppLauncher
|
|
appInstalls, err := appInstallRepo.ListBy(context.Background())
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
apps, err := appRepo.GetBy()
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
|
|
showList, err := launcherRepo.ListName()
|
|
defaultList, err := appRepo.GetTopRecommend()
|
|
if err != nil {
|
|
return data, nil
|
|
}
|
|
allList := common.RemoveRepeatStr(append(defaultList, showList...))
|
|
for _, showItem := range allList {
|
|
var itemData dto.AppLauncher
|
|
for _, app := range apps {
|
|
if showItem == app.Key {
|
|
itemData.Key = app.Key
|
|
itemData.Type = app.Type
|
|
itemData.Name = app.Name
|
|
itemData.Icon = app.Icon
|
|
itemData.Limit = app.Limit
|
|
itemData.Recommend = app.Recommend
|
|
itemData.Description = app.GetDescription(ctx)
|
|
break
|
|
}
|
|
}
|
|
if len(itemData.Icon) == 0 {
|
|
continue
|
|
}
|
|
for _, install := range appInstalls {
|
|
if install.App.Key == showItem {
|
|
itemData.IsInstall = true
|
|
itemData.Detail = append(itemData.Detail, dto.InstallDetail{
|
|
InstallID: install.ID,
|
|
DetailID: install.AppDetailId,
|
|
Name: install.Name,
|
|
Version: install.Version,
|
|
Status: install.Status,
|
|
Path: install.GetPath(),
|
|
WebUI: install.WebUI,
|
|
HttpPort: install.HttpPort,
|
|
HttpsPort: install.HttpsPort,
|
|
})
|
|
}
|
|
}
|
|
if (ArryContains(showList, showItem) && len(itemData.Detail) != 0) ||
|
|
(ArryContains(defaultList, showItem) && len(itemData.Detail) == 0) {
|
|
data = append(data, itemData)
|
|
}
|
|
}
|
|
|
|
sort.Slice(data, func(i, j int) bool {
|
|
if data[i].IsInstall != data[j].IsInstall {
|
|
return data[i].IsInstall
|
|
}
|
|
return data[i].Recommend < data[j].Recommend
|
|
})
|
|
return data, nil
|
|
}
|
|
|
|
func (u *DashboardService) ChangeShow(req dto.SettingUpdate) error {
|
|
launcher, _ := launcherRepo.Get(repo.WithByKey(req.Key))
|
|
if req.Value == constant.StatusEnable && launcher.ID == 0 {
|
|
if err := launcherRepo.Create(&model.AppLauncher{Key: req.Key}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if req.Value == constant.StatusDisable && launcher.ID != 0 {
|
|
if err := launcherRepo.Delete(repo.WithByKey(req.Key)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (u *DashboardService) LoadQuickOptions() []dto.QuickJump {
|
|
quicks := launcherRepo.ListQuickJump(true)
|
|
var list []dto.QuickJump
|
|
for _, quick := range quicks {
|
|
var item dto.QuickJump
|
|
_ = copier.Copy(&item, &quick)
|
|
list = append(list, item)
|
|
}
|
|
return list
|
|
}
|
|
func (u *DashboardService) ChangeQuick(req dto.ChangeQuicks) error {
|
|
showCount := 0
|
|
var quicks []model.QuickJump
|
|
for _, item := range req.Quicks {
|
|
var quick model.QuickJump
|
|
if item.IsShow {
|
|
showCount++
|
|
}
|
|
if err := copier.Copy(&quick, &item); err != nil {
|
|
return err
|
|
}
|
|
quicks = append(quicks, quick)
|
|
}
|
|
if showCount == 0 {
|
|
return buserr.New("ErrMinQuickJump")
|
|
}
|
|
if showCount > 4 {
|
|
return buserr.New("ErrMaxQuickJump")
|
|
}
|
|
|
|
return launcherRepo.UpdateQuicks(quicks)
|
|
}
|
|
|
|
func (u *DashboardService) ListLauncherOption(filter string) ([]dto.LauncherOption, error) {
|
|
showList, _ := launcherRepo.ListName()
|
|
var data []dto.LauncherOption
|
|
optionMap := make(map[string]bool)
|
|
appInstalls, err := appInstallRepo.ListBy(context.Background())
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
|
|
for _, install := range appInstalls {
|
|
isShow := false
|
|
for _, item := range showList {
|
|
if install.App.Key == item {
|
|
isShow = true
|
|
break
|
|
}
|
|
}
|
|
optionMap[install.App.Key] = isShow
|
|
}
|
|
for key, val := range optionMap {
|
|
if len(filter) != 0 && !strings.Contains(key, filter) {
|
|
continue
|
|
}
|
|
data = append(data, dto.LauncherOption{Key: key, IsShow: val})
|
|
}
|
|
sort.Slice(data, func(i, j int) bool {
|
|
return data[i].Key < data[j].Key
|
|
})
|
|
return data, nil
|
|
}
|
|
|
|
type diskInfo struct {
|
|
Type string
|
|
Mount string
|
|
Device string
|
|
}
|
|
|
|
func loadDiskInfo() []dto.DiskInfo {
|
|
var datas []dto.DiskInfo
|
|
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second))
|
|
format := `awk 'NR>1 && !/tmpfs|snap\/core|udev/ {printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7}'`
|
|
stdout, err := cmdMgr.RunWithStdout("bash", "-c", `timeout 2 df -hT -P | `+format)
|
|
if err != nil {
|
|
cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
|
|
stdout, err = cmdMgr2.RunWithStdout("bash", "-c", `timeout 1 df -lhT -P | `+format)
|
|
if err != nil {
|
|
return datas
|
|
}
|
|
}
|
|
lines := strings.Split(stdout, "\n")
|
|
|
|
var mounts []diskInfo
|
|
var excludes = []string{"/mnt/cdrom", "/boot", "/boot/efi", "/dev", "/dev/shm", "/run/lock", "/run", "/run/shm", "/run/user"}
|
|
for _, line := range lines {
|
|
fields := strings.Split(line, "\t")
|
|
if len(fields) < 7 {
|
|
continue
|
|
}
|
|
if strings.HasPrefix(fields[6], "/snap") || len(strings.Split(fields[6], "/")) > 10 {
|
|
continue
|
|
}
|
|
if strings.TrimSpace(fields[1]) == "tmpfs" || strings.TrimSpace(fields[1]) == "overlay" {
|
|
continue
|
|
}
|
|
if strings.Contains(fields[2], "K") {
|
|
continue
|
|
}
|
|
if strings.Contains(fields[6], "docker") || strings.Contains(fields[6], "podman") || strings.Contains(fields[6], "containerd") || strings.HasPrefix(fields[6], "/var/lib/containers") {
|
|
continue
|
|
}
|
|
isExclude := false
|
|
for _, exclude := range excludes {
|
|
if exclude == fields[6] {
|
|
isExclude = true
|
|
}
|
|
}
|
|
if isExclude {
|
|
continue
|
|
}
|
|
mounts = append(mounts, diskInfo{Type: fields[1], Device: fields[0], Mount: strings.Join(fields[6:], " ")})
|
|
}
|
|
|
|
var (
|
|
wg sync.WaitGroup
|
|
mu sync.Mutex
|
|
)
|
|
wg.Add(len(mounts))
|
|
for i := 0; i < len(mounts); i++ {
|
|
go func(mount diskInfo) {
|
|
defer wg.Done()
|
|
|
|
var itemData dto.DiskInfo
|
|
itemData.Path = mount.Mount
|
|
itemData.Type = mount.Type
|
|
itemData.Device = mount.Device
|
|
|
|
type diskResult struct {
|
|
state *disk.UsageStat
|
|
err error
|
|
}
|
|
resultCh := make(chan diskResult, 1)
|
|
|
|
go func() {
|
|
state, err := psutil.DISK.GetUsage(mount.Mount, false)
|
|
resultCh <- diskResult{state: state, err: err}
|
|
}()
|
|
|
|
select {
|
|
case <-time.After(5 * time.Second):
|
|
mu.Lock()
|
|
datas = append(datas, itemData)
|
|
mu.Unlock()
|
|
global.LOG.Errorf("load disk info from %s failed, err: timeout", mount.Mount)
|
|
case result := <-resultCh:
|
|
if result.err != nil {
|
|
mu.Lock()
|
|
datas = append(datas, itemData)
|
|
mu.Unlock()
|
|
global.LOG.Errorf("load disk info from %s failed, err: %v", mount.Mount, result.err)
|
|
return
|
|
}
|
|
itemData.Total = result.state.Total
|
|
itemData.Free = result.state.Free
|
|
itemData.Used = result.state.Used
|
|
itemData.UsedPercent = result.state.UsedPercent
|
|
itemData.InodesTotal = result.state.InodesTotal
|
|
itemData.InodesUsed = result.state.InodesUsed
|
|
itemData.InodesFree = result.state.InodesFree
|
|
itemData.InodesUsedPercent = result.state.InodesUsedPercent
|
|
mu.Lock()
|
|
datas = append(datas, itemData)
|
|
mu.Unlock()
|
|
}
|
|
}(mounts[i])
|
|
}
|
|
wg.Wait()
|
|
|
|
sort.Slice(datas, func(i, j int) bool {
|
|
return datas[i].Path < datas[j].Path
|
|
})
|
|
return datas
|
|
}
|
|
|
|
func loadGPUInfo() []dto.GPUInfo {
|
|
ok, client := gpu.New()
|
|
var list []interface{}
|
|
if ok {
|
|
info, err := client.LoadGpuInfo()
|
|
if err != nil || len(info.GPUs) == 0 {
|
|
return nil
|
|
}
|
|
for _, item := range info.GPUs {
|
|
list = append(list, item)
|
|
}
|
|
}
|
|
if len(list) == 0 {
|
|
return nil
|
|
}
|
|
var data []dto.GPUInfo
|
|
for _, gpu := range list {
|
|
var dataItem dto.GPUInfo
|
|
if err := copier.Copy(&dataItem, &gpu); err != nil {
|
|
continue
|
|
}
|
|
dataItem.PowerUsage = dataItem.PowerDraw + " / " + dataItem.MaxPowerLimit
|
|
dataItem.MemoryUsage = dataItem.MemUsed + " / " + dataItem.MemTotal
|
|
data = append(data, dataItem)
|
|
}
|
|
return data
|
|
}
|
|
|
|
type AppLauncher struct {
|
|
Key string `json:"key"`
|
|
}
|
|
|
|
func ArryContains(arr []string, element string) bool {
|
|
for _, v := range arr {
|
|
if v == element {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func loadXpuInfo() []dto.XPUInfo {
|
|
var list []interface{}
|
|
ok, xpuClient := xpu.New()
|
|
if ok {
|
|
xpus, err := xpuClient.LoadDashData()
|
|
if err != nil || len(xpus) == 0 {
|
|
return nil
|
|
}
|
|
for _, item := range xpus {
|
|
list = append(list, item)
|
|
}
|
|
}
|
|
if len(list) == 0 {
|
|
return nil
|
|
}
|
|
var data []dto.XPUInfo
|
|
for _, gpu := range list {
|
|
var dataItem dto.XPUInfo
|
|
if err := copier.Copy(&dataItem, &gpu); err != nil {
|
|
continue
|
|
}
|
|
data = append(data, dataItem)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func loadOutboundIP() string {
|
|
conn, err := network.Dial("udp", "8.8.8.8:80")
|
|
|
|
if err != nil {
|
|
return "IPNotFound"
|
|
}
|
|
defer conn.Close()
|
|
|
|
localAddr := conn.LocalAddr().(*network.UDPAddr)
|
|
return localAddr.IP.String()
|
|
}
|
|
|
|
func loadQuickJump(base *dto.DashboardBase) {
|
|
website, _ := websiteRepo.GetBy()
|
|
base.WebsiteNumber = len(website)
|
|
|
|
postgresqlDbs, _ := postgresqlRepo.List()
|
|
mysqlDbs, _ := mysqlRepo.List()
|
|
base.DatabaseNumber = len(mysqlDbs) + len(postgresqlDbs)
|
|
|
|
cronjobs, _ := cronjobRepo.List()
|
|
base.CronjobNumber = len(cronjobs)
|
|
|
|
appInstall, _ := appInstallRepo.ListBy(context.Background())
|
|
base.AppInstalledNumber = len(appInstall)
|
|
|
|
quicks := launcherRepo.ListQuickJump(false)
|
|
for i := 0; i < len(quicks); i++ {
|
|
switch quicks[i].Name {
|
|
case "Website":
|
|
quicks[i].Detail = fmt.Sprintf("%d", base.WebsiteNumber)
|
|
case "Database":
|
|
quicks[i].Detail = fmt.Sprintf("%d", base.DatabaseNumber)
|
|
case "Cronjob":
|
|
quicks[i].Detail = fmt.Sprintf("%d", base.CronjobNumber)
|
|
case "AppInstalled":
|
|
quicks[i].Detail = fmt.Sprintf("%d", base.AppInstalledNumber)
|
|
}
|
|
var item dto.QuickJump
|
|
_ = copier.Copy(&item, quicks[i])
|
|
base.QuickJumps = append(base.QuickJumps, item)
|
|
}
|
|
sort.Slice(quicks, func(i, j int) bool {
|
|
return quicks[i].Recommend < quicks[j].Recommend
|
|
})
|
|
}
|