mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-11-07 15:19:44 +00:00
wip
This commit is contained in:
parent
b0377cc659
commit
8445d5c3bc
@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-07-13 10:43:45
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-08-03 14:45:35
|
|
||||||
* @FilePath: /CasaOS/model/disk.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
type LSBLKModel struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
FsType string `json:"fstype"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
FSSize string `json:"fssize"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Model string `json:"model"` //设备标识符
|
|
||||||
RM bool `json:"rm"` //是否为可移动设备
|
|
||||||
RO bool `json:"ro"` //是否为只读设备
|
|
||||||
State string `json:"state"`
|
|
||||||
PhySec int `json:"phy-sec"` //物理扇区大小
|
|
||||||
Type string `json:"type"`
|
|
||||||
Vendor string `json:"vendor"` //供应商
|
|
||||||
Rev string `json:"rev"` //修订版本
|
|
||||||
FSAvail string `json:"fsavail"` //可用空间
|
|
||||||
FSUse string `json:"fsuse%"` //已用百分比
|
|
||||||
MountPoint string `json:"mountpoint"`
|
|
||||||
Format string `json:"format"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
HotPlug bool `json:"hotplug"`
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
FSUsed string `json:"fsused"`
|
|
||||||
Temperature int `json:"temperature"`
|
|
||||||
Tran string `json:"tran"`
|
|
||||||
MinIO uint64 `json:"min-io"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
Serial string `json:"serial"`
|
|
||||||
Children []LSBLKModel `json:"children"`
|
|
||||||
SubSystems string `json:"subsystems"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
//详情特有
|
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
|
||||||
Rota bool `json:"rota"` //true(hhd) false(ssd)
|
|
||||||
DiskType string `json:"disk_type"`
|
|
||||||
EndSector uint64 `json:"end_sector,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Drive struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
Temperature int `json:"temperature"`
|
|
||||||
DiskType string `json:"disk_type"`
|
|
||||||
NeedFormat bool `json:"need_format"`
|
|
||||||
Serial string `json:"serial"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
ChildrenNumber int `json:"children_number"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DriveUSB struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Avail uint64 `json:"avail"`
|
|
||||||
Children []USBChildren `json:"children"`
|
|
||||||
}
|
|
||||||
type USBChildren struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Avail uint64 `json:"avail"`
|
|
||||||
MountPoint string `json:"mount_point"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Storage struct {
|
|
||||||
MountPoint string `json:"mount_point"`
|
|
||||||
Size string `json:"size"`
|
|
||||||
Avail string `json:"avail"` //可用空间
|
|
||||||
Type string `json:"type"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
DriveName string `json:"drive_name"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
}
|
|
||||||
type Storages struct {
|
|
||||||
DiskName string `json:"disk_name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Children []Storage `json:"children"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Summary struct {
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Avail uint64 `json:"avail"` //可用空间
|
|
||||||
Health bool `json:"health"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-07-15 10:43:00
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-15 10:56:17
|
|
||||||
* @FilePath: /CasaOS/model/notify/storage.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package notify
|
|
||||||
|
|
||||||
type StorageMessage struct {
|
|
||||||
Type string `json:"type"` //sata,usb
|
|
||||||
Action string `json:"action"` //remove add
|
|
||||||
Path string `json:"path"`
|
|
||||||
Volume string `json:"volume"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
}
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
//
|
|
||||||
type SmartctlA struct {
|
|
||||||
Smartctl struct {
|
|
||||||
Version []int `json:"version"`
|
|
||||||
SvnRevision string `json:"svn_revision"`
|
|
||||||
PlatformInfo string `json:"platform_info"`
|
|
||||||
BuildInfo string `json:"build_info"`
|
|
||||||
Argv []string `json:"argv"`
|
|
||||||
ExitStatus int `json:"exit_status"`
|
|
||||||
} `json:"smartctl"`
|
|
||||||
Device struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
InfoName string `json:"info_name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Protocol string `json:"protocol"`
|
|
||||||
} `json:"device"`
|
|
||||||
ModelName string `json:"model_name"`
|
|
||||||
SerialNumber string `json:"serial_number"`
|
|
||||||
FirmwareVersion string `json:"firmware_version"`
|
|
||||||
UserCapacity struct {
|
|
||||||
Blocks int `json:"blocks"`
|
|
||||||
Bytes int64 `json:"bytes"`
|
|
||||||
} `json:"user_capacity"`
|
|
||||||
SmartStatus struct {
|
|
||||||
Passed bool `json:"passed"`
|
|
||||||
} `json:"smart_status"`
|
|
||||||
AtaSmartData struct {
|
|
||||||
OfflineDataCollection struct {
|
|
||||||
Status struct {
|
|
||||||
Value int `json:"value"`
|
|
||||||
String string `json:"string"`
|
|
||||||
} `json:"status"`
|
|
||||||
CompletionSeconds int `json:"completion_seconds"`
|
|
||||||
} `json:"offline_data_collection"`
|
|
||||||
SelfTest struct {
|
|
||||||
Status struct {
|
|
||||||
Value int `json:"value"`
|
|
||||||
String string `json:"string"`
|
|
||||||
Passed bool `json:"passed"`
|
|
||||||
} `json:"status"`
|
|
||||||
PollingMinutes struct {
|
|
||||||
Short int `json:"short"`
|
|
||||||
Extended int `json:"extended"`
|
|
||||||
Conveyance int `json:"conveyance"`
|
|
||||||
} `json:"polling_minutes"`
|
|
||||||
} `json:"self_test"`
|
|
||||||
Capabilities struct {
|
|
||||||
Values []int `json:"values"`
|
|
||||||
ExecOfflineImmediateSupported bool `json:"exec_offline_immediate_supported"`
|
|
||||||
OfflineIsAbortedUponNewCmd bool `json:"offline_is_aborted_upon_new_cmd"`
|
|
||||||
OfflineSurfaceScanSupported bool `json:"offline_surface_scan_supported"`
|
|
||||||
SelfTestsSupported bool `json:"self_tests_supported"`
|
|
||||||
ConveyanceSelfTestSupported bool `json:"conveyance_self_test_supported"`
|
|
||||||
SelectiveSelfTestSupported bool `json:"selective_self_test_supported"`
|
|
||||||
AttributeAutosaveEnabled bool `json:"attribute_autosave_enabled"`
|
|
||||||
ErrorLoggingSupported bool `json:"error_logging_supported"`
|
|
||||||
GpLoggingSupported bool `json:"gp_logging_supported"`
|
|
||||||
} `json:"capabilities"`
|
|
||||||
} `json:"ata_smart_data"`
|
|
||||||
PowerOnTime struct {
|
|
||||||
Hours int `json:"hours"`
|
|
||||||
} `json:"power_on_time"`
|
|
||||||
PowerCycleCount int `json:"power_cycle_count"`
|
|
||||||
Temperature struct {
|
|
||||||
Current int `json:"current"`
|
|
||||||
} `json:"temperature"`
|
|
||||||
}
|
|
||||||
@ -2,11 +2,9 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func OnlyExec(cmdStr string) {
|
func OnlyExec(cmdStr string) {
|
||||||
@ -35,8 +33,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//str, err := ioutil.ReadAll(stdout)
|
// str, err := ioutil.ReadAll(stdout)
|
||||||
var networklist = []string{}
|
networklist := []string{}
|
||||||
outputBuf := bufio.NewReader(stdout)
|
outputBuf := bufio.NewReader(stdout)
|
||||||
for {
|
for {
|
||||||
output, _, err := outputBuf.ReadLine()
|
output, _, err := outputBuf.ReadLine()
|
||||||
@ -72,41 +70,3 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
}
|
}
|
||||||
return string(str)
|
return string(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
|
||||||
func ExecLSBLK() []byte {
|
|
||||||
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("lsblk", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
//执行 lsblk 命令
|
|
||||||
func ExecLSBLKByPath(path string) []byte {
|
|
||||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("lsblk", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
//exec smart
|
|
||||||
func ExecSmartCTLByPath(path string) []byte {
|
|
||||||
timeout := 3
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
output, err := exec.CommandContext(ctx, "smartctl", "-a", path, "-j").Output()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("smartctl", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExecEnabledSMART(path string) {
|
|
||||||
|
|
||||||
exec.Command("smartctl", "-s on", path).Output()
|
|
||||||
}
|
|
||||||
|
|||||||
608
route/v1/disk.go
608
route/v1/disk.go
@ -1,608 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
)
|
|
||||||
|
|
||||||
var diskMap = make(map[string]string)
|
|
||||||
|
|
||||||
// @Summary disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/list [get]
|
|
||||||
func GetDiskList(c *gin.Context) {
|
|
||||||
path := c.Query("path")
|
|
||||||
if len(path) > 0 {
|
|
||||||
m := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := c.DefaultQuery("type", "")
|
|
||||||
list := service.MyService.Disk().LSBLK(false)
|
|
||||||
if t == "usb" {
|
|
||||||
data := []model.DriveUSB{}
|
|
||||||
for _, v := range list {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data = append(data, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
part := make(map[string]int64, len(dbList))
|
|
||||||
for _, v := range dbList {
|
|
||||||
part[v.MountPoint] = v.CreatedAt
|
|
||||||
}
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
disks := []model.Drive{}
|
|
||||||
storage := []model.Storage{}
|
|
||||||
avail := []model.Drive{}
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
disk := model.Drive{}
|
|
||||||
if list[i].Rota {
|
|
||||||
disk.DiskType = "HDD"
|
|
||||||
} else {
|
|
||||||
disk.DiskType = "SSD"
|
|
||||||
}
|
|
||||||
disk.Serial = list[i].Serial
|
|
||||||
disk.Name = list[i].Name
|
|
||||||
disk.Size = list[i].Size
|
|
||||||
disk.Path = list[i].Path
|
|
||||||
disk.Model = list[i].Model
|
|
||||||
disk.ChildrenNumber = len(list[i].Children)
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = v.MountPoint
|
|
||||||
stor.Size = v.FSSize
|
|
||||||
stor.Avail = v.FSAvail
|
|
||||||
stor.Path = v.Path
|
|
||||||
stor.Type = v.FsType
|
|
||||||
stor.DriveName = "System"
|
|
||||||
disk.Model = "System"
|
|
||||||
if strings.Contains(v.SubSystems, "mmc") {
|
|
||||||
disk.DiskType = "MMC"
|
|
||||||
} else if strings.Contains(v.SubSystems, "usb") {
|
|
||||||
disk.DiskType = "USB"
|
|
||||||
}
|
|
||||||
disk.Health = "true"
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
storage = append(storage, stor)
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = list[i].Children[j].MountPoint
|
|
||||||
stor.Size = list[i].Children[j].FSSize
|
|
||||||
stor.Avail = list[i].Children[j].FSAvail
|
|
||||||
stor.Path = list[i].Children[j].Path
|
|
||||||
stor.Type = list[i].Children[j].FsType
|
|
||||||
stor.DriveName = "System"
|
|
||||||
disk.Model = "System"
|
|
||||||
if strings.Contains(list[i].Children[j].SubSystems, "mmc") {
|
|
||||||
disk.DiskType = "MMC"
|
|
||||||
} else if strings.Contains(list[i].Children[j].SubSystems, "usb") {
|
|
||||||
disk.DiskType = "USB"
|
|
||||||
}
|
|
||||||
disk.Health = "true"
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
storage = append(storage, stor)
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
temp.SmartStatus.Passed = true
|
|
||||||
}
|
|
||||||
isAvail := true
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
if v.MountPoint != "" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = v.MountPoint
|
|
||||||
stor.Size = v.FSSize
|
|
||||||
stor.Avail = v.FSAvail
|
|
||||||
stor.Path = v.Path
|
|
||||||
stor.Type = v.FsType
|
|
||||||
stor.DriveName = list[i].Name
|
|
||||||
storage = append(storage, stor)
|
|
||||||
isAvail = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isAvail {
|
|
||||||
//if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
|
|
||||||
disk.NeedFormat = false
|
|
||||||
avail = append(avail, disk)
|
|
||||||
// } else {
|
|
||||||
// disk.NeedFormat = true
|
|
||||||
// avail = append(avail, disk)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
disk.Temperature = temp.Temperature.Current
|
|
||||||
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data := make(map[string]interface{}, 3)
|
|
||||||
data["drive"] = disks
|
|
||||||
data["storage"] = storage
|
|
||||||
data["avail"] = avail
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/list [get]
|
|
||||||
func GetDisksUSBList(c *gin.Context) {
|
|
||||||
list := service.MyService.Disk().LSBLK(false)
|
|
||||||
data := []model.DriveUSB{}
|
|
||||||
for _, v := range list {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Label
|
|
||||||
if temp.Name == "" {
|
|
||||||
temp.Name = v.Name
|
|
||||||
}
|
|
||||||
temp.Size = v.Size
|
|
||||||
children := []model.USBChildren{}
|
|
||||||
for _, child := range v.Children {
|
|
||||||
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
tempChildren := model.USBChildren{}
|
|
||||||
tempChildren.MountPoint = child.MountPoint
|
|
||||||
tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64)
|
|
||||||
tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
tempChildren.Name = child.Label
|
|
||||||
if len(tempChildren.Name) == 0 {
|
|
||||||
tempChildren.Name = filepath.Base(child.MountPoint)
|
|
||||||
}
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
children = append(children, tempChildren)
|
|
||||||
temp.Avail += avail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
temp.Children = children
|
|
||||||
data = append(data, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteDisksUmount(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
|
|
||||||
path := js["path"]
|
|
||||||
pwd := js["password"]
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if encryption.GetMD5ByStr(pwd) != user.Password {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
diskInfo := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
for _, v := range diskInfo.Children {
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(v.Path)
|
|
||||||
//delete data
|
|
||||||
service.MyService.Disk().DeleteMountPoint(v.Path, v.MountPoint)
|
|
||||||
|
|
||||||
service.MyService.Shares().DeleteShareByPath(v.MountPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
//send notify to client
|
|
||||||
msg := notify.StorageMessage{}
|
|
||||||
msg.Action = "REMOVED"
|
|
||||||
msg.Path = path
|
|
||||||
msg.Volume = ""
|
|
||||||
msg.Size = 0
|
|
||||||
msg.Type = ""
|
|
||||||
service.MyService.Notify().SendStorageBySocket(msg)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: path})
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteDiskUSB(c *gin.Context) {
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
mountPoint := js["mount_point"]
|
|
||||||
if file.CheckNotExist(mountPoint) {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Disk().UmountUSB(mountPoint)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary get disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/lists [get]
|
|
||||||
func GetPlugInDisks(c *gin.Context) {
|
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
var result []*disk.UsageStat
|
|
||||||
for _, item := range list {
|
|
||||||
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary disk detail
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path query string true "for example /dev/sda"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/info [get]
|
|
||||||
func GetDiskInfo(c *gin.Context) {
|
|
||||||
path := c.Query("path")
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
}
|
|
||||||
m := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取支持的格式
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/type [get]
|
|
||||||
func FormatDiskType(c *gin.Context) {
|
|
||||||
var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除分区
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda1"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/delpart [delete]
|
|
||||||
func RemovePartition(c *gin.Context) {
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
path := js["path"]
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
}
|
|
||||||
var p = path[:len(path)-1]
|
|
||||||
var n = path[len(path)-1:]
|
|
||||||
service.MyService.Disk().DelPartition(p, n)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary add storage
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "disk path e.g. /dev/sda"
|
|
||||||
// @Param serial formData string true "serial"
|
|
||||||
// @Param name formData string true "name"
|
|
||||||
// @Param format formData bool true "need format(true)"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/storage [post]
|
|
||||||
func PostDiskAddPartition(c *gin.Context) {
|
|
||||||
|
|
||||||
js := make(map[string]interface{})
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
path := js["path"].(string)
|
|
||||||
name := js["name"].(string)
|
|
||||||
format := js["format"].(bool)
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//diskInfo := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
|
|
||||||
// if !file.CheckNotExist("/DATA/" + name) {
|
|
||||||
// // /mnt/name exist
|
|
||||||
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
diskMap[path] = "busying"
|
|
||||||
currentDisk := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
if format {
|
|
||||||
// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
|
|
||||||
// if len(format) == 0 {
|
|
||||||
// delete(diskMap, path)
|
|
||||||
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
service.MyService.Disk().AddPartition(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatBool := true
|
|
||||||
// for formatBool {
|
|
||||||
// currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
// if len(currentDisk.Children) > 0 {
|
|
||||||
// formatBool = false
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// time.Sleep(time.Second)
|
|
||||||
// }
|
|
||||||
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
// if len(currentDisk.Children) != 1 {
|
|
||||||
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
fmt.Println(name)
|
|
||||||
if len(name) == 0 {
|
|
||||||
name = "Storage"
|
|
||||||
}
|
|
||||||
fmt.Println(name)
|
|
||||||
for i := 0; i < len(currentDisk.Children); i++ {
|
|
||||||
childrenName := currentDisk.Children[i].Label
|
|
||||||
if len(childrenName) == 0 {
|
|
||||||
//childrenName = name + "_" + currentDisk.Children[i].Name
|
|
||||||
childrenName = name + "_" + strconv.Itoa(i+1)
|
|
||||||
}
|
|
||||||
mountPath := "/DATA/" + childrenName
|
|
||||||
if !file.CheckNotExist(mountPath) {
|
|
||||||
ls := service.MyService.System().GetDirPath(mountPath)
|
|
||||||
if len(ls) > 0 {
|
|
||||||
// exist
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m := model2.SerialDisk{}
|
|
||||||
m.MountPoint = mountPath
|
|
||||||
m.Path = currentDisk.Children[i].Path
|
|
||||||
m.UUID = currentDisk.Children[i].UUID
|
|
||||||
m.State = 0
|
|
||||||
m.CreatedAt = time.Now().Unix()
|
|
||||||
service.MyService.Disk().SaveMountPoint(m)
|
|
||||||
//mount dir
|
|
||||||
service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
delete(diskMap, path)
|
|
||||||
|
|
||||||
//send notify to client
|
|
||||||
msg := notify.StorageMessage{}
|
|
||||||
msg.Action = "ADDED"
|
|
||||||
msg.Path = currentDisk.Children[0].Path
|
|
||||||
msg.Volume = "/DATA/"
|
|
||||||
msg.Size = currentDisk.Children[0].Size
|
|
||||||
msg.Type = currentDisk.Children[0].Tran
|
|
||||||
service.MyService.Notify().SendStorageBySocket(msg)
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Param pwd formData string true "user password"
|
|
||||||
// @Param volume formData string true "mount point"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/format [post]
|
|
||||||
func PostDiskFormat(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
path := js["path"]
|
|
||||||
t := "ext4"
|
|
||||||
pwd := js["password"]
|
|
||||||
volume := js["volume"]
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if encryption.GetMD5ByStr(pwd) != user.Password {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(path) == 0 || len(t) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
diskMap[path] = "busying"
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
|
||||||
format := service.MyService.Disk().FormatDisk(path, t)
|
|
||||||
if len(format) == 0 {
|
|
||||||
delete(diskMap, path)
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Disk().MountDisk(path, volume)
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
delete(diskMap, path)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary remove mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "e.g. /dev/sda1"
|
|
||||||
// @Param mount_point formData string true "e.g. /mnt/volume1"
|
|
||||||
// @Param pwd formData string true "user password"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/umount [post]
|
|
||||||
func PostDiskUmount(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
|
|
||||||
path := js["path"]
|
|
||||||
mountPoint := js["volume"]
|
|
||||||
pwd := js["password"]
|
|
||||||
|
|
||||||
if len(path) == 0 || len(mountPoint) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if encryption.GetMD5ByStr(pwd) != user.Password {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
|
||||||
//delete data
|
|
||||||
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
//send notify to client
|
|
||||||
msg := notify.StorageMessage{}
|
|
||||||
msg.Action = "REMOVED"
|
|
||||||
msg.Path = path
|
|
||||||
msg.Volume = mountPoint
|
|
||||||
msg.Size = 0
|
|
||||||
msg.Type = ""
|
|
||||||
service.MyService.Notify().SendStorageBySocket(msg)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary confirm delete disk
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/remove/{id} [delete]
|
|
||||||
func DeleteDisk(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
service.MyService.Disk().DeleteMount(id)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary check mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/init [get]
|
|
||||||
func GetDiskCheck(c *gin.Context) {
|
|
||||||
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
mapList := make(map[string]string)
|
|
||||||
|
|
||||||
for _, v := range list {
|
|
||||||
mapList[v.Serial] = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range dbList {
|
|
||||||
if _, ok := mapList[v.UUID]; !ok {
|
|
||||||
//disk undefind
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
285
service/disk.go
285
service/disk.go
@ -1,285 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
json2 "encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DiskService interface {
|
|
||||||
GetPlugInDisk() []string
|
|
||||||
LSBLK(isUseCache bool) []model.LSBLKModel
|
|
||||||
SmartCTL(path string) model.SmartctlA
|
|
||||||
FormatDisk(path, format string) []string
|
|
||||||
UmountPointAndRemoveDir(path string) []string
|
|
||||||
GetDiskInfo(path string) model.LSBLKModel
|
|
||||||
DelPartition(path, num string) string
|
|
||||||
AddPartition(path string) string
|
|
||||||
GetDiskInfoByPath(path string) *disk.UsageStat
|
|
||||||
MountDisk(path, volume string)
|
|
||||||
GetSerialAll() []model2.SerialDisk
|
|
||||||
SaveMountPoint(m model2.SerialDisk)
|
|
||||||
DeleteMountPoint(path, mountPoint string)
|
|
||||||
DeleteMount(id string)
|
|
||||||
UpdateMountPoint(m model2.SerialDisk)
|
|
||||||
RemoveLSBLKCache()
|
|
||||||
UmountUSB(path string)
|
|
||||||
}
|
|
||||||
type diskService struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) RemoveLSBLKCache() {
|
|
||||||
key := "system_lsblk"
|
|
||||||
Cache.Delete(key)
|
|
||||||
}
|
|
||||||
func (d *diskService) UmountUSB(path string) {
|
|
||||||
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path)
|
|
||||||
fmt.Println(r)
|
|
||||||
}
|
|
||||||
func (d *diskService) SmartCTL(path string) model.SmartctlA {
|
|
||||||
|
|
||||||
key := "system_smart_" + path
|
|
||||||
if result, ok := Cache.Get(key); ok {
|
|
||||||
|
|
||||||
res, ok := result.(model.SmartctlA)
|
|
||||||
if ok {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var m model.SmartctlA
|
|
||||||
str := command2.ExecSmartCTLByPath(path)
|
|
||||||
if str == nil {
|
|
||||||
loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error"))
|
|
||||||
Cache.Add(key, m, time.Minute*10)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
err := json2.Unmarshal([]byte(str), &m)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(m, model.SmartctlA{}) {
|
|
||||||
Cache.Add(key, m, time.Hour*24)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
//通过脚本获取外挂磁盘
|
|
||||||
func (d *diskService) GetPlugInDisk() []string {
|
|
||||||
return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPlugInDisk")
|
|
||||||
}
|
|
||||||
|
|
||||||
//格式化硬盘
|
|
||||||
func (d *diskService) FormatDisk(path, format string) []string {
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;FormatDisk " + path + " " + format)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
//移除挂载点,删除目录
|
|
||||||
func (d *diskService) UmountPointAndRemoveDir(path string) []string {
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + path)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除分区
|
|
||||||
func (d *diskService) DelPartition(path, num string) string {
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;DelPartition " + path + " " + num)
|
|
||||||
fmt.Println(r)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
//part
|
|
||||||
func (d *diskService) AddPartition(path string) string {
|
|
||||||
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;AddPartition " + path)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) AddAllPartition(path string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取硬盘详情
|
|
||||||
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
|
||||||
diskInfo, err := disk.Usage(path + "1")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
|
||||||
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
|
||||||
return diskInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
//get disk details
|
|
||||||
func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
|
||||||
key := "system_lsblk"
|
|
||||||
var n []model.LSBLKModel
|
|
||||||
|
|
||||||
if result, ok := Cache.Get(key); ok && isUseCache {
|
|
||||||
|
|
||||||
res, ok := result.([]model.LSBLKModel)
|
|
||||||
if ok {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
str := command2.ExecLSBLK()
|
|
||||||
if str == nil {
|
|
||||||
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var m []model.LSBLKModel
|
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
var c []model.LSBLKModel
|
|
||||||
|
|
||||||
var fsused uint64
|
|
||||||
|
|
||||||
var health = true
|
|
||||||
for _, i := range m {
|
|
||||||
if i.Type != "loop" && !i.RO {
|
|
||||||
fsused = 0
|
|
||||||
for _, child := range i.Children {
|
|
||||||
if child.RM {
|
|
||||||
child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskHealthState " + child.Path))
|
|
||||||
if strings.ToLower(strings.TrimSpace(child.State)) != "ok" {
|
|
||||||
health = false
|
|
||||||
}
|
|
||||||
f, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
|
||||||
fsused += f
|
|
||||||
} else {
|
|
||||||
health = false
|
|
||||||
}
|
|
||||||
c = append(c, child)
|
|
||||||
}
|
|
||||||
//i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskType " + i.Path))
|
|
||||||
if health {
|
|
||||||
i.Health = "OK"
|
|
||||||
}
|
|
||||||
i.FSUsed = strconv.FormatUint(fsused, 10)
|
|
||||||
i.Children = c
|
|
||||||
if fsused > 0 {
|
|
||||||
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to parse float", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n = append(n, i)
|
|
||||||
health = true
|
|
||||||
c = []model.LSBLKModel{}
|
|
||||||
fsused = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(n) > 0 {
|
|
||||||
Cache.Add(key, n, time.Second*100)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|
||||||
str := command2.ExecLSBLKByPath(path)
|
|
||||||
if str == nil {
|
|
||||||
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
|
|
||||||
return model.LSBLKModel{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ml []model.LSBLKModel
|
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
|
||||||
return model.LSBLKModel{}
|
|
||||||
}
|
|
||||||
|
|
||||||
m := model.LSBLKModel{}
|
|
||||||
if len(ml) > 0 {
|
|
||||||
m = ml[0]
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
// 下面为计算是否可以继续分区的部分,暂时不需要
|
|
||||||
chiArr := make(map[string]string)
|
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPartitionSectors " + m.Path)
|
|
||||||
if len(chiList) == 0 {
|
|
||||||
loger.Error("chiList length error", zap.Any("err", "chiList length error"))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(chiList); i++ {
|
|
||||||
tempArr := strings.Split(chiList[i], ",")
|
|
||||||
chiArr[tempArr[0]] = chiList[i]
|
|
||||||
}
|
|
||||||
var maxSector uint64 = 0
|
|
||||||
for i := 0; i < len(m.Children); i++ {
|
|
||||||
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
|
||||||
m.Children[i].StartSector, _ = strconv.ParseUint(tempArr[1], 10, 64)
|
|
||||||
m.Children[i].EndSector, _ = strconv.ParseUint(tempArr[2], 10, 64)
|
|
||||||
if m.Children[i].EndSector > maxSector {
|
|
||||||
maxSector = m.Children[i].EndSector
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
|
||||||
|
|
||||||
if len(diskEndSector) < 2 {
|
|
||||||
loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error"))
|
|
||||||
}
|
|
||||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
|
||||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
|
||||||
//添加可以分区情况
|
|
||||||
p := model.LSBLKModel{}
|
|
||||||
p.Path = "可以添加"
|
|
||||||
m.Children = append(m.Children, p)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) MountDisk(path, volume string) {
|
|
||||||
//fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
|
|
||||||
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
|
|
||||||
fmt.Println(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
|
||||||
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
|
|
||||||
d.db.Create(&m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
|
|
||||||
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) DeleteMount(id string) {
|
|
||||||
|
|
||||||
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
|
|
||||||
|
|
||||||
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
|
|
||||||
|
|
||||||
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;do_umount " + path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) GetSerialAll() []model2.SerialDisk {
|
|
||||||
var m []model2.SerialDisk
|
|
||||||
d.db.Find(&m)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDiskService(db *gorm.DB) DiskService {
|
|
||||||
return &diskService{db: db}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.org
|
|
||||||
* @Date: 2021-12-07 17:14:41
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-08-17 18:46:43
|
|
||||||
* @FilePath: /CasaOS/service/model/o_disk.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
//SerialAdvanced Technology Attachment (STAT)
|
|
||||||
type SerialDisk struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
State int `json:"state"`
|
|
||||||
MountPoint string `json:"mount_point"`
|
|
||||||
CreatedAt int64 `json:"created_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *SerialDisk) TableName() string {
|
|
||||||
return "o_disk"
|
|
||||||
}
|
|
||||||
@ -21,16 +21,17 @@ var Cache *cache.Cache
|
|||||||
|
|
||||||
var MyService Repository
|
var MyService Repository
|
||||||
|
|
||||||
var WebSocketConns []*websocket.Conn
|
var (
|
||||||
var NewVersionApp map[string]string
|
WebSocketConns []*websocket.Conn
|
||||||
var SocketRun bool
|
NewVersionApp map[string]string
|
||||||
|
SocketRun bool
|
||||||
|
)
|
||||||
|
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
App() AppService
|
App() AppService
|
||||||
User() UserService
|
User() UserService
|
||||||
Docker() DockerService
|
Docker() DockerService
|
||||||
Casa() CasaService
|
Casa() CasaService
|
||||||
Disk() DiskService
|
|
||||||
Notify() NotifyServer
|
Notify() NotifyServer
|
||||||
Rely() RelyService
|
Rely() RelyService
|
||||||
System() SystemService
|
System() SystemService
|
||||||
@ -51,7 +52,6 @@ func NewService(db *gorm.DB, RuntimePath string) Repository {
|
|||||||
user: NewUserService(db),
|
user: NewUserService(db),
|
||||||
docker: NewDockerService(),
|
docker: NewDockerService(),
|
||||||
casa: NewCasaService(),
|
casa: NewCasaService(),
|
||||||
disk: NewDiskService(db),
|
|
||||||
notify: NewNotifyService(db),
|
notify: NewNotifyService(db),
|
||||||
rely: NewRelyService(db),
|
rely: NewRelyService(db),
|
||||||
system: NewSystemService(),
|
system: NewSystemService(),
|
||||||
@ -66,7 +66,6 @@ type store struct {
|
|||||||
user UserService
|
user UserService
|
||||||
docker DockerService
|
docker DockerService
|
||||||
casa CasaService
|
casa CasaService
|
||||||
disk DiskService
|
|
||||||
notify NotifyServer
|
notify NotifyServer
|
||||||
rely RelyService
|
rely RelyService
|
||||||
system SystemService
|
system SystemService
|
||||||
@ -78,9 +77,11 @@ type store struct {
|
|||||||
func (c *store) Gateway() gateway.ManagementService {
|
func (c *store) Gateway() gateway.ManagementService {
|
||||||
return c.gateway
|
return c.gateway
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) Connections() ConnectionsService {
|
func (s *store) Connections() ConnectionsService {
|
||||||
return s.connections
|
return s.connections
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) Shares() SharesService {
|
func (s *store) Shares() SharesService {
|
||||||
return s.shares
|
return s.shares
|
||||||
}
|
}
|
||||||
@ -92,8 +93,8 @@ func (c *store) Rely() RelyService {
|
|||||||
func (c *store) System() SystemService {
|
func (c *store) System() SystemService {
|
||||||
return c.system
|
return c.system
|
||||||
}
|
}
|
||||||
func (c *store) Notify() NotifyServer {
|
|
||||||
|
|
||||||
|
func (c *store) Notify() NotifyServer {
|
||||||
return c.notify
|
return c.notify
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +113,3 @@ func (c *store) Docker() DockerService {
|
|||||||
func (c *store) Casa() CasaService {
|
func (c *store) Casa() CasaService {
|
||||||
return c.casa
|
return c.casa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) Disk() DiskService {
|
|
||||||
return c.disk
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user