mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-06-16 05:55:33 +00:00
Storage Manager
Fix the app store classification problem Fix the application market classification problem
This commit is contained in:
parent
9675eff69e
commit
fcb906aa85
@ -21,6 +21,7 @@ type LSBLKModel struct {
|
|||||||
Health string `json:"health"`
|
Health string `json:"health"`
|
||||||
HotPlug bool `json:"hotplug"`
|
HotPlug bool `json:"hotplug"`
|
||||||
FSUsed string `json:"fsused"`
|
FSUsed string `json:"fsused"`
|
||||||
|
Temperature int `json:"temperature"`
|
||||||
Tran string `json:"tran"`
|
Tran string `json:"tran"`
|
||||||
MinIO uint64 `json:"min-io"`
|
MinIO uint64 `json:"min-io"`
|
||||||
UsedPercent float64 `json:"used_percent"`
|
UsedPercent float64 `json:"used_percent"`
|
||||||
@ -28,5 +29,7 @@ type LSBLKModel struct {
|
|||||||
Children []LSBLKModel `json:"children"`
|
Children []LSBLKModel `json:"children"`
|
||||||
//详情特有
|
//详情特有
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
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"`
|
EndSector uint64 `json:"end_sector,omitempty"`
|
||||||
}
|
}
|
||||||
|
69
model/smartctl_model.go
Normal file
69
model/smartctl_model.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
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,9 +2,11 @@ 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) {
|
||||||
@ -85,7 +87,26 @@ func ExecLSBLK() []byte {
|
|||||||
func ExecLSBLKByPath(path string) []byte {
|
func ExecLSBLKByPath(path string) []byte {
|
||||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("lsblk", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return output
|
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()
|
||||||
|
}
|
||||||
|
@ -21,6 +21,13 @@ const (
|
|||||||
//zerotier
|
//zerotier
|
||||||
GET_TOKEN_ERROR = 30001
|
GET_TOKEN_ERROR = 30001
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE = 40001
|
||||||
|
DISK_NEEDS_FORMAT = 40002
|
||||||
|
DISK_BUSYING = 40003
|
||||||
|
REMOVE_MOUNT_POINT_ERROR = 40004
|
||||||
|
FORMAT_ERROR = 40005
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR = 50001
|
UNINSTALL_APP_ERROR = 50001
|
||||||
PULL_IMAGE_ERROR = 50002
|
PULL_IMAGE_ERROR = 50002
|
||||||
@ -37,34 +44,41 @@ const (
|
|||||||
var MsgFlags = map[int]string{
|
var MsgFlags = map[int]string{
|
||||||
SUCCESS: "ok",
|
SUCCESS: "ok",
|
||||||
ERROR: "fail",
|
ERROR: "fail",
|
||||||
INVALID_PARAMS: "Invalid params",
|
INVALID_PARAMS: "Parameters Error",
|
||||||
ERROR_AUTH_TOKEN: "error auth token",
|
ERROR_AUTH_TOKEN: "Error auth token",
|
||||||
|
|
||||||
//user
|
//user
|
||||||
PWD_INVALID: "Password invalid",
|
PWD_INVALID: "Invalid password",
|
||||||
PWD_IS_EMPTY: "Password is empty",
|
PWD_IS_EMPTY: "Password is empty",
|
||||||
PWD_INVALID_OLD: "Old Password invalid",
|
PWD_INVALID_OLD: "Invalid old password",
|
||||||
ACCOUNT_LOCK: "Account Lock",
|
ACCOUNT_LOCK: "Account is locked",
|
||||||
|
|
||||||
//system
|
//system
|
||||||
DIR_ALREADY_EXISTS: "Directory already exists",
|
DIR_ALREADY_EXISTS: "Folder already exists",
|
||||||
FILE_ALREADY_EXISTS: "File already exists",
|
FILE_ALREADY_EXISTS: "File already exists",
|
||||||
FILE_OR_DIR_EXISTS: "File or directory already exists",
|
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
||||||
PORT_IS_OCCUPIED: "Port is occupied",
|
PORT_IS_OCCUPIED: "Port is occupied",
|
||||||
|
|
||||||
//zerotier
|
//zerotier
|
||||||
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR: "uninstall app error",
|
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||||
PULL_IMAGE_ERROR: "pull image error",
|
PULL_IMAGE_ERROR: "Error pulling image",
|
||||||
DEVICE_NOT_EXIST: "device not exist",
|
DEVICE_NOT_EXIST: "Device does not exist",
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE: "Name not available",
|
||||||
|
DISK_NEEDS_FORMAT: "Drive needs to be formatted",
|
||||||
|
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
|
||||||
|
DISK_BUSYING: "Drive is busy",
|
||||||
|
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
|
||||||
|
|
||||||
//
|
//
|
||||||
FILE_DOES_NOT_EXIST: "file does not exist",
|
FILE_DOES_NOT_EXIST: "File does not exist",
|
||||||
|
|
||||||
FILE_READ_ERROR: "file read error",
|
FILE_READ_ERROR: "File read error",
|
||||||
SHORTCUTS_URL_ERROR: "url error",
|
SHORTCUTS_URL_ERROR: "URL error",
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取错误信息
|
//获取错误信息
|
||||||
|
@ -3,6 +3,7 @@ package route
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -34,10 +35,9 @@ func installSyncthing(appId string) {
|
|||||||
m := model.CustomizationPostData{}
|
m := model.CustomizationPostData{}
|
||||||
var dockerImage string
|
var dockerImage string
|
||||||
var dockerImageVersion string
|
var dockerImageVersion string
|
||||||
|
appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "system")
|
||||||
appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
|
|
||||||
|
|
||||||
dockerImage = appInfo.Image
|
dockerImage = appInfo.Image
|
||||||
|
dockerImageVersion = appInfo.ImageVersion
|
||||||
|
|
||||||
if len(appInfo.ImageVersion) == 0 {
|
if len(appInfo.ImageVersion) == 0 {
|
||||||
dockerImageVersion = "latest"
|
dockerImageVersion = "latest"
|
||||||
@ -84,9 +84,9 @@ func installSyncthing(appId string) {
|
|||||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//pull image error
|
//pull image error
|
||||||
|
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
|
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
@ -101,8 +101,8 @@ func installSyncthing(appId string) {
|
|||||||
m.Volumes = appInfo.Volumes
|
m.Volumes = appInfo.Volumes
|
||||||
|
|
||||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("container create error", err)
|
||||||
// create container error
|
// create container error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ func checkSystemApp() {
|
|||||||
path := ""
|
path := ""
|
||||||
for _, i := range paths {
|
for _, i := range paths {
|
||||||
if i.ContainerPath == "/config" {
|
if i.ContainerPath == "/config" {
|
||||||
path = docker.GetDir(v.CustomId, i.Path) + "config.xml"
|
path = docker.GetDir(v.CustomId, i.Path) + "/config.xml"
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
if file.CheckNotExist(path) {
|
if file.CheckNotExist(path) {
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
@ -197,21 +197,37 @@ func CheckSerialDiskMount() {
|
|||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK()
|
||||||
mountPoint := make(map[string]string, len(dbList))
|
mountPoint := make(map[string]string, len(dbList))
|
||||||
|
//remount
|
||||||
|
for _, v := range dbList {
|
||||||
|
mountPoint[v.Path] = v.MountPoint
|
||||||
|
}
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
|
command.ExecEnabledSMART(v.Path)
|
||||||
if v.Children != nil {
|
if v.Children != nil {
|
||||||
for _, h := range v.Children {
|
for _, h := range v.Children {
|
||||||
mountPoint[h.MountPoint] = "1"
|
if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
|
||||||
|
if m, ok := mountPoint[h.Path]; ok {
|
||||||
|
//mount point check
|
||||||
|
volume := m
|
||||||
|
if !file.CheckNotExist(m) {
|
||||||
|
for i := 0; file.CheckNotExist(volume); i++ {
|
||||||
|
volume = m + strconv.Itoa(i+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.Disk().MountDisk(h.Path, volume)
|
||||||
|
if volume != m {
|
||||||
|
ms := model2.SerialDisk{}
|
||||||
|
ms.Serial = v.Serial
|
||||||
|
service.MyService.Disk().UpdateMountPoint(ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
//remount
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
|
||||||
for _, item := range dbList {
|
|
||||||
if _, ok := mountPoint[item.MountPoint]; !ok {
|
|
||||||
service.MyService.Disk().MountDisk(item.Path, item.MountPoint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
func Update2_3() {
|
func Update2_3() {
|
||||||
|
@ -218,17 +218,23 @@ func InitRouter() *gin.Engine {
|
|||||||
v1DiskGroup.Use()
|
v1DiskGroup.Use()
|
||||||
{
|
{
|
||||||
v1DiskGroup.GET("/check", v1.GetDiskCheck)
|
v1DiskGroup.GET("/check", v1.GetDiskCheck)
|
||||||
//获取磁盘列表
|
|
||||||
v1DiskGroup.GET("/list", v1.GetPlugInDisk)
|
v1DiskGroup.GET("/list", v1.GetDiskList)
|
||||||
|
|
||||||
//获取磁盘详情
|
//获取磁盘详情
|
||||||
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
||||||
|
|
||||||
//格式化磁盘
|
//format storage
|
||||||
v1DiskGroup.POST("/format", v1.FormatDisk)
|
v1DiskGroup.POST("/format", v1.FormatDisk)
|
||||||
|
|
||||||
//添加分区
|
// add storage
|
||||||
v1DiskGroup.POST("/part", v1.AddPartition)
|
v1DiskGroup.POST("/storage", v1.AddPartition)
|
||||||
|
|
||||||
|
//mount SATA disk
|
||||||
|
v1DiskGroup.POST("/mount", v1.PostMountDisk)
|
||||||
|
|
||||||
|
//umount sata disk
|
||||||
|
v1DiskGroup.POST("/umount", v1.PostDiskUmount)
|
||||||
|
|
||||||
//获取可以格式化的内容
|
//获取可以格式化的内容
|
||||||
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
||||||
@ -236,12 +242,6 @@ func InitRouter() *gin.Engine {
|
|||||||
//删除分区
|
//删除分区
|
||||||
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
||||||
|
|
||||||
//mount SATA disk
|
|
||||||
v1DiskGroup.POST("/mount", v1.PostMountDisk)
|
|
||||||
|
|
||||||
//umount SATA disk
|
|
||||||
v1DiskGroup.POST("/umount", v1.PostDiskUmount)
|
|
||||||
v1DiskGroup.DELETE("/remove/:id", v1.DeleteDisk)
|
|
||||||
}
|
}
|
||||||
v1ShareGroup := v1Group.Group("/share")
|
v1ShareGroup := v1Group.Group("/share")
|
||||||
v1ShareGroup.Use()
|
v1ShareGroup.Use()
|
||||||
|
@ -36,24 +36,24 @@ func AppList(c *gin.Context) {
|
|||||||
categoryId := c.DefaultQuery("category_id", "0")
|
categoryId := c.DefaultQuery("category_id", "0")
|
||||||
key := c.DefaultQuery("key", "")
|
key := c.DefaultQuery("key", "")
|
||||||
recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key)
|
recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key)
|
||||||
for i := 0; i < len(recommend); i++ {
|
// for i := 0; i < len(recommend); i++ {
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
||||||
if ct != nil {
|
// if ct != nil {
|
||||||
list[i].State = ct.State
|
// recommend[i].State = ct.State
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for i := 0; i < len(list); i++ {
|
// for i := 0; i < len(list); i++ {
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
// ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
||||||
if ct != nil {
|
// if ct != nil {
|
||||||
list[i].State = ct.State
|
// list[i].State = ct.State
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for i := 0; i < len(community); i++ {
|
// for i := 0; i < len(community); i++ {
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
// ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
||||||
if ct != nil {
|
// if ct != nil {
|
||||||
list[i].State = ct.State
|
// community[i].State = ct.State
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
data := make(map[string]interface{}, 3)
|
data := make(map[string]interface{}, 3)
|
||||||
data["recommend"] = recommend
|
data["recommend"] = recommend
|
||||||
data["list"] = list
|
data["list"] = list
|
||||||
@ -137,7 +137,7 @@ func AppUsageList(c *gin.Context) {
|
|||||||
func AppInfo(c *gin.Context) {
|
func AppInfo(c *gin.Context) {
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
info := service.MyService.OAPI().GetServerAppInfo(id)
|
info := service.MyService.OAPI().GetServerAppInfo(id, "")
|
||||||
if info.NetworkModel != "host" {
|
if info.NetworkModel != "host" {
|
||||||
for i := 0; i < len(info.Ports); i++ {
|
for i := 0; i < len(info.Ports); i++ {
|
||||||
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
||||||
|
159
route/v1/disk.go
159
route/v1/disk.go
@ -2,9 +2,13 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
@ -12,18 +16,53 @@ import (
|
|||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取磁盘列表
|
var diskMap = make(map[string]string)
|
||||||
|
|
||||||
|
// @Summary disk list
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/list [get]
|
// @Router /disk/list [get]
|
||||||
func GetPlugInDisk(c *gin.Context) {
|
func GetDiskList(c *gin.Context) {
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK()
|
||||||
|
newList := []model.LSBLKModel{}
|
||||||
|
for i := len(list) - 1; i >= 0; i-- {
|
||||||
|
if list[i].Rota {
|
||||||
|
list[i].DiskType = "HDD"
|
||||||
|
} else {
|
||||||
|
list[i].DiskType = "SSD"
|
||||||
|
}
|
||||||
|
if list[i].Tran == "sata" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
|
||||||
|
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
|
||||||
|
if len(pathArr) == 3 {
|
||||||
|
list[i].Children[0].Name = pathArr[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list[i].Temperature = temp.Temperature.Current
|
||||||
|
list[i].Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
||||||
|
|
||||||
|
newList = append(newList, list[i])
|
||||||
|
} else if len(list[i].Children) > 0 && list[i].Children[0].MountPoint == "/" {
|
||||||
|
//system
|
||||||
|
list[i].Children[0].Name = "System"
|
||||||
|
list[i].Model = "System"
|
||||||
|
list[i].DiskType = "EMMC"
|
||||||
|
list[i].Health = "true"
|
||||||
|
newList = append(newList, list[i])
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: newList})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary get disk list
|
// @Summary get disk list
|
||||||
@ -60,25 +99,46 @@ func GetDiskInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary format disk
|
// @Summary format storage
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "for example /dev/sda1"
|
// @Param path formData string true "e.g. /dev/sda1"
|
||||||
|
// @Param pwd formData string true "user password"
|
||||||
|
// @Param volume formData string true "mount point"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/format [post]
|
// @Router /disk/format [post]
|
||||||
func FormatDisk(c *gin.Context) {
|
func FormatDisk(c *gin.Context) {
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
|
t := "ext4"
|
||||||
|
pwd := c.PostForm("pwd")
|
||||||
|
volume := c.PostForm("volume")
|
||||||
|
|
||||||
t := c.PostForm("type")
|
if pwd != config.UserInfo.PWD {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(path) == 0 || len(t) == 0 {
|
if len(path) == 0 || len(t) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
service.MyService.Disk().FormatDisk(path, t)
|
if _, ok := diskMap[path]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diskMap[path] = "busying"
|
||||||
|
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
||||||
|
format := service.MyService.Disk().FormatDisk(path, t)
|
||||||
|
if len(format) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.FORMAT_ERROR, Message: oasis_err.GetMsg(oasis_err.FORMAT_ERROR)})
|
||||||
|
delete(diskMap, path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
service.MyService.Disk().MountDisk(path, volume)
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
delete(diskMap, path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,23 +175,64 @@ func RemovePartition(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary serial number
|
// @Summary add storage
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda"
|
// @Param path formData string true "disk path e.g. /dev/sda"
|
||||||
// @Param serial formData string true "serial"
|
// @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"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/addpart [post]
|
// @Router /disk/storage [post]
|
||||||
func AddPartition(c *gin.Context) {
|
func AddPartition(c *gin.Context) {
|
||||||
|
name := c.PostForm("name")
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
serial := c.PostForm("serial")
|
serial := c.PostForm("serial")
|
||||||
if len(path) == 0 || len(serial) == 0 {
|
format, _ := strconv.ParseBool(c.PostForm("format"))
|
||||||
|
if len(name) == 0 || len(path) == 0 || len(serial) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
service.MyService.Disk().AddPartition(path)
|
if _, ok := diskMap[serial]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !file.CheckNotExist("/mnt/" + name) {
|
||||||
|
// /mnt/name exist
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.NAME_NOT_AVAILABLE, Message: oasis_err.GetMsg(oasis_err.NAME_NOT_AVAILABLE)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diskMap[serial] = "busying"
|
||||||
|
currentDisk := service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if !format {
|
||||||
|
if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_err.DISK_NEEDS_FORMAT)})
|
||||||
|
delete(diskMap, serial)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
service.MyService.Disk().AddPartition(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
mountPath := "/mnt/" + name
|
||||||
|
|
||||||
|
service.MyService.Disk().MountDisk(path, mountPath)
|
||||||
|
|
||||||
|
m := model2.SerialDisk{}
|
||||||
|
m.MountPoint = mountPath
|
||||||
|
m.Path = path + "1"
|
||||||
|
m.Serial = serial
|
||||||
|
m.State = 0
|
||||||
|
service.MyService.Disk().SaveMountPoint(m)
|
||||||
|
|
||||||
|
//mount dir
|
||||||
|
service.MyService.Disk().MountDisk(path+"1", mountPath)
|
||||||
|
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
|
||||||
|
delete(diskMap, serial)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,13 +266,13 @@ func PostMountDisk(c *gin.Context) {
|
|||||||
|
|
||||||
//mount dir
|
//mount dir
|
||||||
service.MyService.Disk().MountDisk(path, mountPath)
|
service.MyService.Disk().MountDisk(path, mountPath)
|
||||||
//save to data
|
|
||||||
m := model2.SerialDisk{}
|
m := model2.SerialDisk{}
|
||||||
m.MountPoint = mountPath
|
m.MountPoint = mountPath
|
||||||
m.Path = path
|
m.Path = path
|
||||||
m.Serial = serial
|
m.Serial = serial
|
||||||
m.State = 0
|
m.State = 0
|
||||||
service.MyService.Disk().SaveMountPoint(m)
|
//service.MyService.Disk().SaveMountPoint(m)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,19 +281,35 @@ func PostMountDisk(c *gin.Context) {
|
|||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "for example: /dev/sda1"
|
// @Param path formData string true "e.g. /dev/sda1"
|
||||||
// @Param mount_point formData string true "for example: /mnt/volume1"
|
// @Param mount_point formData string true "e.g. /mnt/volume1"
|
||||||
|
// @Param pwd formData string true "user password"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/umount [post]
|
// @Router /disk/umount [post]
|
||||||
func PostDiskUmount(c *gin.Context) {
|
func PostDiskUmount(c *gin.Context) {
|
||||||
|
|
||||||
//
|
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
mountPoint := c.PostForm("mount_point")
|
mountPoint := c.PostForm("volume")
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
pwd := c.PostForm("pwd")
|
||||||
|
|
||||||
|
if len(path) == 0 || len(mountPoint) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pwd != config.UserInfo.PWD {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
||||||
//delete data
|
//delete data
|
||||||
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ func InstallApp(c *gin.Context) {
|
|||||||
dockerImageVersion = "latest"
|
dockerImageVersion = "latest"
|
||||||
}
|
}
|
||||||
if m.Origin != "custom" {
|
if m.Origin != "custom" {
|
||||||
appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
|
appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -107,9 +108,33 @@ func GetSystemConfigDebug(c *gin.Context) {
|
|||||||
|
|
||||||
array := service.MyService.System().GetSystemConfigDebug()
|
array := service.MyService.System().GetSystemConfigDebug()
|
||||||
disk := service.MyService.ZiMa().GetDiskInfo()
|
disk := service.MyService.ZiMa().GetDiskInfo()
|
||||||
array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
|
sys := service.MyService.ZiMa().GetSysInfo()
|
||||||
|
//todo 准备sync需要显示的数据(镜像,容器)
|
||||||
|
var systemAppStatus string
|
||||||
|
images := service.MyService.Docker().IsExistImage("linuxserver/syncthing")
|
||||||
|
systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: array})
|
list := service.MyService.App().GetSystemAppList()
|
||||||
|
for _, v := range *list {
|
||||||
|
systemAppStatus += v.Image + ",\n\t"
|
||||||
|
}
|
||||||
|
systemAppStatus += "Sync Key: " + config.SystemConfigInfo.SyncKey + "\n\t"
|
||||||
|
|
||||||
|
var bugContent string = fmt.Sprintf(`
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: %s
|
||||||
|
- CasaOS Version: %s
|
||||||
|
- Disk Total: %v
|
||||||
|
- Disk Used: %v
|
||||||
|
- Sync State: %s
|
||||||
|
- System Info: %s
|
||||||
|
- Browser: $Browser$
|
||||||
|
- Version: $Version$
|
||||||
|
`, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, systemAppStatus, array)
|
||||||
|
|
||||||
|
// array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: bugContent})
|
||||||
}
|
}
|
||||||
func Sys(c *gin.Context) {
|
func Sys(c *gin.Context) {
|
||||||
service.DockerPull()
|
service.DockerPull()
|
||||||
@ -237,7 +262,42 @@ func Info(c *gin.Context) {
|
|||||||
var data = make(map[string]interface{}, 5)
|
var data = make(map[string]interface{}, 5)
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK()
|
||||||
data["disk"] = list
|
|
||||||
|
newList := []model.LSBLKModel{}
|
||||||
|
for i := len(list) - 1; i >= 0; i-- {
|
||||||
|
if list[i].Rota {
|
||||||
|
list[i].DiskType = "HDD"
|
||||||
|
} else {
|
||||||
|
list[i].DiskType = "SSD"
|
||||||
|
}
|
||||||
|
if list[i].Tran == "sata" {
|
||||||
|
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
|
||||||
|
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
|
||||||
|
if len(pathArr) == 3 {
|
||||||
|
list[i].Children[0].Name = pathArr[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list[i].Temperature = temp.Temperature.Current
|
||||||
|
list[i].Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
||||||
|
newList = append(newList, list[i])
|
||||||
|
} else if len(list[i].Children) > 0 && list[i].Children[0].MountPoint == "/" {
|
||||||
|
//system
|
||||||
|
list[i].Children[0].Name = "System"
|
||||||
|
list[i].Model = "System"
|
||||||
|
list[i].DiskType = "EMMC"
|
||||||
|
list[i].Health = "true"
|
||||||
|
newList = append(newList, list[i])
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data["disk"] = newList
|
||||||
cpu := service.MyService.ZiMa().GetCpuPercent()
|
cpu := service.MyService.ZiMa().GetCpuPercent()
|
||||||
num := service.MyService.ZiMa().GetCpuCoreNum()
|
num := service.MyService.ZiMa().GetCpuCoreNum()
|
||||||
cpuData := make(map[string]interface{})
|
cpuData := make(map[string]interface{})
|
||||||
|
@ -16,7 +16,7 @@ type CasaService interface {
|
|||||||
GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList)
|
GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList)
|
||||||
GetServerCategoryList() []model.ServerCategoryList
|
GetServerCategoryList() []model.ServerCategoryList
|
||||||
GetTaskList(size int) []model2.TaskDBModel
|
GetTaskList(size int) []model2.TaskDBModel
|
||||||
GetServerAppInfo(id string) model.ServerAppList
|
GetServerAppInfo(id, t string) model.ServerAppList
|
||||||
ShareAppFile(body []byte) string
|
ShareAppFile(body []byte) string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,13 +88,12 @@ func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
|
|||||||
|
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
func (o *casaService) GetServerAppInfo(id string) model.ServerAppList {
|
func (o *casaService) GetServerAppInfo(id, t string) model.ServerAppList {
|
||||||
|
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
|
|
||||||
head["Authorization"] = GetToken()
|
head["Authorization"] = GetToken()
|
||||||
|
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t, head)
|
||||||
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id, head)
|
|
||||||
|
|
||||||
info := model.ServerAppList{}
|
info := model.ServerAppList{}
|
||||||
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
@ -3,6 +3,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -20,8 +21,9 @@ import (
|
|||||||
type DiskService interface {
|
type DiskService interface {
|
||||||
GetPlugInDisk() []string
|
GetPlugInDisk() []string
|
||||||
LSBLK() []model.LSBLKModel
|
LSBLK() []model.LSBLKModel
|
||||||
FormatDisk(path, format string) string
|
SmartCTL(path string) model.SmartctlA
|
||||||
UmountPointAndRemoveDir(path string) string
|
FormatDisk(path, format string) []string
|
||||||
|
UmountPointAndRemoveDir(path string) []string
|
||||||
GetDiskInfo(path string) model.LSBLKModel
|
GetDiskInfo(path string) model.LSBLKModel
|
||||||
DelPartition(path, num string) string
|
DelPartition(path, num string) string
|
||||||
AddPartition(path string) string
|
AddPartition(path string) string
|
||||||
@ -31,30 +33,60 @@ type DiskService interface {
|
|||||||
SaveMountPoint(m model2.SerialDisk)
|
SaveMountPoint(m model2.SerialDisk)
|
||||||
DeleteMountPoint(path, mountPoint string)
|
DeleteMountPoint(path, mountPoint string)
|
||||||
DeleteMount(id string)
|
DeleteMount(id string)
|
||||||
|
UpdateMountPoint(m model2.SerialDisk)
|
||||||
|
RemoveLSBLKCache()
|
||||||
}
|
}
|
||||||
type diskService struct {
|
type diskService struct {
|
||||||
log loger2.OLog
|
log loger2.OLog
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *diskService) RemoveLSBLKCache() {
|
||||||
|
key := "system_lsblk"
|
||||||
|
Cache.Delete(key)
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
d.log.Error("smartctl exec error,smartctl")
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json2.Unmarshal([]byte(str), &m)
|
||||||
|
if err != nil {
|
||||||
|
d.log.Error("json ummarshal error", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(m, model.SmartctlA{}) {
|
||||||
|
Cache.Add(key, m, time.Second*10)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
//通过脚本获取外挂磁盘
|
//通过脚本获取外挂磁盘
|
||||||
func (d *diskService) GetPlugInDisk() []string {
|
func (d *diskService) GetPlugInDisk() []string {
|
||||||
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPlugInDisk")
|
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPlugInDisk")
|
||||||
}
|
}
|
||||||
|
|
||||||
//格式化硬盘
|
//格式化硬盘
|
||||||
func (d *diskService) FormatDisk(path, format string) string {
|
func (d *diskService) FormatDisk(path, format string) []string {
|
||||||
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format)
|
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format)
|
||||||
fmt.Println(r)
|
return r
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//移除挂载点,删除目录
|
//移除挂载点,删除目录
|
||||||
func (d *diskService) UmountPointAndRemoveDir(path string) string {
|
func (d *diskService) UmountPointAndRemoveDir(path string) []string {
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path)
|
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path)
|
||||||
fmt.Println(r)
|
return r
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除分区
|
//删除分区
|
||||||
@ -66,8 +98,7 @@ func (d *diskService) DelPartition(path, num string) string {
|
|||||||
|
|
||||||
//part
|
//part
|
||||||
func (d *diskService) AddPartition(path string) string {
|
func (d *diskService) AddPartition(path string) string {
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
|
command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
|
||||||
fmt.Println(r)
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,11 +109,10 @@ func (d *diskService) AddAllPartition(path string) {
|
|||||||
//获取硬盘详情
|
//获取硬盘详情
|
||||||
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
||||||
diskInfo, err := disk.Usage(path + "1")
|
diskInfo, err := disk.Usage(path + "1")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Println(path)
|
|
||||||
fmt.Println(diskInfo)
|
|
||||||
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
||||||
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
||||||
return diskInfo
|
return diskInfo
|
||||||
@ -91,7 +121,6 @@ func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
|||||||
//get disk details
|
//get disk details
|
||||||
func (d *diskService) LSBLK() []model.LSBLKModel {
|
func (d *diskService) LSBLK() []model.LSBLKModel {
|
||||||
key := "system_lsblk"
|
key := "system_lsblk"
|
||||||
|
|
||||||
var n []model.LSBLKModel
|
var n []model.LSBLKModel
|
||||||
|
|
||||||
if result, ok := Cache.Get(key); ok {
|
if result, ok := Cache.Get(key); ok {
|
||||||
@ -151,7 +180,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(n) > 0 {
|
if len(n) > 0 {
|
||||||
Cache.Add(key, n, time.Second*10)
|
Cache.Add(key, n, time.Second*100)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
@ -162,6 +191,7 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
d.log.Error("lsblk exec error,str")
|
d.log.Error("lsblk exec error,str")
|
||||||
return model.LSBLKModel{}
|
return model.LSBLKModel{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ml []model.LSBLKModel
|
var ml []model.LSBLKModel
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -169,9 +199,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
d.log.Error("json ummarshal error", err)
|
d.log.Error("json ummarshal error", err)
|
||||||
return model.LSBLKModel{}
|
return model.LSBLKModel{}
|
||||||
}
|
}
|
||||||
//todo 需要判断长度
|
|
||||||
m := ml[0]
|
m := model.LSBLKModel{}
|
||||||
//声明数组
|
if len(ml) > 0 {
|
||||||
|
m = ml[0]
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
// 下面为计算是否可以继续分区的部分,暂时不需要
|
||||||
chiArr := make(map[string]string)
|
chiArr := make(map[string]string)
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
||||||
if len(chiList) == 0 {
|
if len(chiList) == 0 {
|
||||||
@ -182,7 +216,6 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
tempArr := strings.Split(chiList[i], ",")
|
tempArr := strings.Split(chiList[i], ",")
|
||||||
chiArr[tempArr[0]] = chiList[i]
|
chiArr[tempArr[0]] = chiList[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxSector uint64 = 0
|
var maxSector uint64 = 0
|
||||||
for i := 0; i < len(m.Children); i++ {
|
for i := 0; i < len(m.Children); i++ {
|
||||||
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
||||||
@ -191,13 +224,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
if m.Children[i].EndSector > maxSector {
|
if m.Children[i].EndSector > maxSector {
|
||||||
maxSector = m.Children[i].EndSector
|
maxSector = m.Children[i].EndSector
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
||||||
|
|
||||||
if len(diskEndSector) < 2 {
|
if len(diskEndSector) < 2 {
|
||||||
d.log.Error("diskEndSector length error")
|
d.log.Error("diskEndSector length error")
|
||||||
}
|
}
|
||||||
|
|
||||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
||||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
||||||
//添加可以分区情况
|
//添加可以分区情况
|
||||||
@ -214,9 +247,14 @@ func (d *diskService) MountDisk(path, volume string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
||||||
|
d.db.Where("serial = ?", m.Serial).Delete(&model2.SerialDisk{})
|
||||||
d.db.Create(&m)
|
d.db.Create(&m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
|
||||||
|
d.db.Model(&model2.SerialDisk{}).Where("serial = ?", m.Serial).Update("mount_point", m.MountPoint)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *diskService) DeleteMount(id string) {
|
func (d *diskService) DeleteMount(id string) {
|
||||||
|
|
||||||
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
|
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
|
||||||
@ -224,7 +262,7 @@ func (d *diskService) DeleteMount(id string) {
|
|||||||
|
|
||||||
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
|
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
|
||||||
|
|
||||||
d.db.Delete(&model2.SerialDisk{}).Where("path= ? && mount_point = ?", path, mountPoint)
|
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
|
||||||
|
|
||||||
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path)
|
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path)
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,33 @@ version_0_2_3() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# add in v0.2.5
|
||||||
|
readonly CASA_DEPANDS="curl smartmontools"
|
||||||
|
version_0_2_5{
|
||||||
|
install_depends "$CASA_DEPANDS"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#Install Depends
|
||||||
|
install_depends() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
if [[ ! -x "$(command -v '$1')" ]]; then
|
||||||
|
show 2 "Install the necessary dependencies: $1"
|
||||||
|
packagesNeeded=$1
|
||||||
|
if [ -x "$(command -v apk)" ]; then
|
||||||
|
$sudo_cmd apk add --no-cache $packagesNeeded
|
||||||
|
elif [ -x "$(command -v apt-get)" ]; then
|
||||||
|
$sudo_cmd apt-get -y -q install $packagesNeeded
|
||||||
|
elif [ -x "$(command -v dnf)" ]; then
|
||||||
|
$sudo_cmd dnf install $packagesNeeded
|
||||||
|
elif [ -x "$(command -v zypper)" ]; then
|
||||||
|
$sudo_cmd zypper install $packagesNeeded
|
||||||
|
else
|
||||||
|
show 1 "Package manager not found. You must manually install: $packagesNeeded"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
version_0_2_3
|
version_0_2_3
|
||||||
|
|
||||||
|
version_0_2_5
|
||||||
|
@ -73,10 +73,8 @@ UMountPorintAndRemoveDir() {
|
|||||||
if [[ -z ${MOUNT_POINT} ]]; then
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
${log} "Warning: ${DEVICE} is not mounted"
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
else
|
else
|
||||||
umount -l ${DEVICE}
|
umount -lf ${DEVICE}
|
||||||
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
|
||||||
/bin/rmdir "${MOUNT_POINT}"
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,11 +87,11 @@ FormatDisk() {
|
|||||||
elif [ "$2" == "ntfs" ]; then
|
elif [ "$2" == "ntfs" ]; then
|
||||||
mkfs.ntfs $1
|
mkfs.ntfs $1
|
||||||
elif [ "$2" == "ext4" ]; then
|
elif [ "$2" == "ext4" ]; then
|
||||||
mkfs.ext4 -F $1
|
mkfs.ext4 -m 1 -F $1
|
||||||
elif [ "$2" == "exfat" ]; then
|
elif [ "$2" == "exfat" ]; then
|
||||||
mkfs.exfat $1
|
mkfs.exfat $1
|
||||||
else
|
else
|
||||||
mkfs.ext4 -F $1
|
mkfs.ext4 -m 1 -F $1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,12 +116,10 @@ AddPartition() {
|
|||||||
|
|
||||||
parted -s $1 mkpart primary ext4 0 100%
|
parted -s $1 mkpart primary ext4 0 100%
|
||||||
|
|
||||||
mkfs.ext4 $11
|
mkfs.ext4 -m 1 $11
|
||||||
|
|
||||||
partprobe $1
|
partprobe $1
|
||||||
|
|
||||||
# mount $11 $2
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#磁盘类型
|
#磁盘类型
|
||||||
@ -148,14 +144,14 @@ GetDiskHealthState() {
|
|||||||
#result bytes
|
#result bytes
|
||||||
#result sectors
|
#result sectors
|
||||||
GetDiskSizeAndSectors() {
|
GetDiskSizeAndSectors() {
|
||||||
fdisk $1 -l | grep "/dev/sda:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
fdisk $1 -l | grep "$1:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
#获取磁盘分区数据扇区
|
#获取磁盘分区数据扇区
|
||||||
#param 磁盘路径 /dev/sda
|
#param 磁盘路径 /dev/sda
|
||||||
#result start,end,sectors
|
#result start,end,sectors
|
||||||
GetPartitionSectors() {
|
GetPartitionSectors() {
|
||||||
fdisk $1 -l | grep "/dev/sda[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
|
fdisk $1 -l | grep "$1[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
|
||||||
}
|
}
|
||||||
|
|
||||||
#检查没有使用的挂载点删除文件夹
|
#检查没有使用的挂载点删除文件夹
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
const CURRENTVERSION = "0.2.4"
|
const CURRENTVERSION = "0.2.5"
|
||||||
const BODY = "<li>New App Store</li><li>Fix minor bugs</li>"
|
const BODY = "<li>Storage Manager</li><li>File synchronization issues</li><li>Fix the app store classification problem</li>"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user