Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agent/app/dto/response/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type DiskBasicInfo struct {
type CompleteDiskInfo struct {
Disks []DiskInfo `json:"disks"`
UnpartitionedDisks []DiskBasicInfo `json:"unpartitionedDisks"`
SystemDisk *DiskInfo `json:"systemDisk"`
SystemDisks []DiskInfo `json:"systemDisks"`
TotalDisks int `json:"totalDisks"`
TotalCapacity int64 `json:"totalCapacity"`
}
Expand Down
24 changes: 16 additions & 8 deletions agent/app/service/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,22 @@ func NewIDiskService() IDiskService {
}

func (s *DiskService) GetCompleteDiskInfo() (*response.CompleteDiskInfo, error) {
output, err := cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
if err != nil {
return nil, fmt.Errorf("failed to execute lsblk command: %v", err)
}

diskInfos, err := parseLsblkOutput(output)
if err != nil {
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
var diskInfos []response.DiskBasicInfo
output, err := cmd.RunDefaultWithStdoutBashC("lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
if err == nil {
diskInfos, err = parseLsblkJsonOutput(output)
if err != nil {
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
}
} else {
output, err = cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
if err != nil {
return nil, fmt.Errorf("failed to run lsblk command: %v", err)
}
diskInfos, err = parseLsblkOutput(output)
if err != nil {
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
}
}

result := organizeDiskInfo(diskInfos)
Expand Down
157 changes: 144 additions & 13 deletions agent/app/service/disk_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package service

import (
"bufio"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"os"
"os/exec"
"strconv"
Expand All @@ -12,12 +14,134 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/re"
)

type LsblkRaw struct {
Blockdevices []LsblkDevice `json:"blockdevices"`
}

type LsblkDevice struct {
Name string `json:"name"`
Size string `json:"size"`
Type string `json:"type"`
Mountpoint string `json:"mountpoint"`
Fstype string `json:"fstype"`
Model string `json:"model"`
Serial string `json:"serial"`
Tran string `json:"tran"`
Rota bool `json:"rota"`
Children []LsblkDevice `json:"children"`
}

func parseDevice(dev LsblkDevice) []response.DiskBasicInfo {
var list []response.DiskBasicInfo

if strings.HasPrefix(dev.Name, "loop") || strings.HasPrefix(dev.Name, "dm-") || dev.Type == "rom" {
return list
}

if dev.Type == "lvm" {
return list
}

diskType := "Unknown"
if dev.Type == "disk" || dev.Type == "part" {
if dev.Rota {
diskType = "HDD"
} else {
diskType = "SSD"
}
}

mountPoint := dev.Mountpoint
filesystem := dev.Fstype
size := dev.Size

var used, avail, totalSize string
var usePercent int
isMounted := mountPoint != ""
isSystem := false

if dev.Fstype == "LVM2_member" && len(dev.Children) > 0 {
for _, child := range dev.Children {
if child.Type == "lvm" && child.Mountpoint != "" {
devicePath := "/dev/mapper/" + child.Name
totalSize, used, avail, usePercent, _ := getDiskUsageInfo(devicePath)

childInfo := response.DiskBasicInfo{
Device: dev.Name,
Size: totalSize,
Model: dev.Model,
DiskType: diskType,
Filesystem: child.Fstype,
MountPoint: child.Mountpoint,
IsMounted: true,
UsePercent: usePercent,
Used: used,
Avail: avail,
Serial: dev.Serial,
IsRemovable: dev.Tran == "usb",
IsSystem: isSystemDisk(child.Mountpoint),
}
list = append(list, childInfo)
}
}
return list
} else if isMounted {
isSystem = isSystemDisk(mountPoint)
devicePath := "/dev/" + dev.Name
totalSize, used, avail, usePercent, _ = getDiskUsageInfo(devicePath)
if totalSize != "" {
size = totalSize
}
}

info := response.DiskBasicInfo{
Device: dev.Name,
Size: size,
Model: dev.Model,
DiskType: diskType,
Filesystem: filesystem,
MountPoint: mountPoint,
IsMounted: isMounted,
UsePercent: usePercent,
Used: used,
Avail: avail,
Serial: dev.Serial,
IsRemovable: dev.Tran == "usb",
IsSystem: isSystem,
}

list = append(list, info)

for _, child := range dev.Children {
childList := parseDevice(child)
list = append(list, childList...)
}

return list
}

func parseLsblkJsonOutput(output string) ([]response.DiskBasicInfo, error) {
raw := &LsblkRaw{}
if err := json.Unmarshal([]byte(output), raw); err != nil {
return nil, fmt.Errorf("failed to parse lsblk json output: %v", err)
}
var disks []response.DiskBasicInfo

for _, dev := range raw.Blockdevices {
if strings.HasPrefix(dev.Name, "loop") ||
strings.HasPrefix(dev.Name, "dm-") {
continue
}
devList := parseDevice(dev)
disks = append(disks, devList...)
}
return disks, nil
}

func organizeDiskInfo(diskInfos []response.DiskBasicInfo) response.CompleteDiskInfo {
var result response.CompleteDiskInfo
var systemDisk *response.DiskInfo
diskMap := make(map[string]*response.DiskInfo)
partitions := make(map[string][]response.DiskBasicInfo)

Expand Down Expand Up @@ -55,15 +179,14 @@ func organizeDiskInfo(diskInfos []response.DiskBasicInfo) response.CompleteDiskI
totalCapacity += capacity

if disk.IsSystem {
systemDisk = disk
result.SystemDisks = append(result.SystemDisks, *disk)
} else if len(disk.Partitions) == 0 {
result.UnpartitionedDisks = append(result.UnpartitionedDisks, disk.DiskBasicInfo)
} else {
result.Disks = append(result.Disks, *disk)
}
}

result.SystemDisk = systemDisk
result.TotalDisks = len(diskMap)
result.TotalCapacity = totalCapacity

Expand Down Expand Up @@ -162,17 +285,25 @@ func parseLsblkOutput(output string) ([]response.DiskBasicInfo, error) {
if fsType == "LVM2_member" {
for _, lvmInfo := range lvmMap {
if lvmInfo.IsMounted {
actualMountPoint = lvmInfo.MountPoint
actualFsType = lvmInfo.Filesystem
actualUsed = lvmInfo.Used
size = lvmInfo.Size
actualAvail = lvmInfo.Avail
actualUsePercent = lvmInfo.UsePercent
isMounted = true
isSystemPartition = lvmInfo.IsSystem
break
lvmDiskInfo := response.DiskBasicInfo{
Device: name,
Size: lvmInfo.Size,
Model: model,
DiskType: "LVM",
IsRemovable: tran == "usb",
IsSystem: lvmInfo.IsSystem,
Filesystem: lvmInfo.Filesystem,
Used: lvmInfo.Used,
Avail: lvmInfo.Avail,
UsePercent: lvmInfo.UsePercent,
MountPoint: lvmInfo.MountPoint,
IsMounted: true,
Serial: serial,
}
diskInfos = append(diskInfos, lvmDiskInfo)
}
}
continue
}

info := response.DiskBasicInfo{
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/interface/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export namespace Host {
export interface CompleteDiskInfo {
disks: DiskInfo[];
unpartitionedDisks: DiskBasicInfo[];
systemDisk?: DiskInfo;
systemDisks?: DiskInfo[];
totalDisks: number;
totalCapacity: number;
}
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/views/host/disk-management/disk/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
<div>
<DiskRouter />
<MainDiv class="mt-2" :height-diff="140" v-loading="loading">
<div v-if="diskInfo?.systemDisk">
<DiskCard class="mt-2" :diskInfo="diskInfo.systemDisk" scope="system" />
<div v-if="diskInfo?.systemDisks">
<DiskCard
class="mt-2"
v-for="(disk, index) in diskInfo.systemDisks"
:diskInfo="disk"
scope="system"
:key="index"
/>
</div>
<div v-if="diskInfo?.unpartitionedDisks">
<DiskCard
Expand Down
Loading