mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 21:14:41 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
493dc5c032 | ||
|
|
9a73bc2a18 | ||
|
|
55a9acd9f6 | ||
|
|
d060968b7a | ||
|
|
88a7f53130 | ||
|
|
26e5b18a5d | ||
|
|
011ace96f6 | ||
|
|
5c00655d14 | ||
|
|
eb36c262db | ||
|
|
29d1861545 | ||
|
|
3c9b410693 | ||
|
|
4c3b41433b | ||
|
|
1fd13668c0 | ||
|
|
d1ab7261a6 | ||
|
|
0fc65bcb3a | ||
|
|
f1ce8bfd99 | ||
|
|
3f472f1864 | ||
|
|
229d94cae7 | ||
|
|
c28e1bbf93 | ||
|
|
a840029000 | ||
|
|
aad2646cf2 | ||
|
|
ca1f8ad73e | ||
|
|
dea02763a2 | ||
|
|
ea67385a64 | ||
|
|
fa2daa2767 | ||
|
|
fcb906aa85 |
2
UI
2
UI
Submodule UI updated: f3088b6354...25c7eec90d
@@ -20,13 +20,57 @@ type LSBLKModel struct {
|
|||||||
Format string `json:"format"`
|
Format string `json:"format"`
|
||||||
Health string `json:"health"`
|
Health string `json:"health"`
|
||||||
HotPlug bool `json:"hotplug"`
|
HotPlug bool `json:"hotplug"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
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"`
|
||||||
Serial string `json:"serial"`
|
Serial string `json:"serial"`
|
||||||
Children []LSBLKModel `json:"children"`
|
Children []LSBLKModel `json:"children"`
|
||||||
|
SubSystems string `json:"subsystems"`
|
||||||
//详情特有
|
//详情特有
|
||||||
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriveUSB struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Used uint64 `json:"use"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Mount bool `json:"mount"` //是否完全挂载
|
||||||
|
Avail uint64 `json:"avail"` //可用空间
|
||||||
|
}
|
||||||
|
|
||||||
|
type Storage struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
MountPoint string `json:"mountpoint"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
Avail string `json:"avail"` //可用空间
|
||||||
|
Type string `json:"type"`
|
||||||
|
CreatedAt int64 `json:"create_at"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
DriveName string `json:"drive_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Summary struct {
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Avail uint64 `json:"avail"` //可用空间
|
||||||
|
Health bool `json:"health"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
}
|
||||||
|
|||||||
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"`
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type Path struct {
|
type Path struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
IsDir bool `json:"is_dir"`
|
IsDir bool `json:"is_dir"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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", "us_en")
|
||||||
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)
|
||||||
@@ -195,23 +195,40 @@ func CheckSerialDiskMount() {
|
|||||||
// check mount point
|
// check mount point
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
mountPoint := make(map[string]string, len(dbList))
|
mountPoint := make(map[string]string, len(dbList))
|
||||||
|
//remount
|
||||||
|
for _, v := range dbList {
|
||||||
|
mountPoint[v.UUID] = 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.UUID]; 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.UUID = v.UUID
|
||||||
|
ms.MountPoint = volume
|
||||||
|
service.MyService.Disk().UpdateMountPoint(ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
//remount
|
|
||||||
for _, item := range dbList {
|
|
||||||
if _, ok := mountPoint[item.MountPoint]; !ok {
|
|
||||||
service.MyService.Disk().MountDisk(item.Path, item.MountPoint)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
|
||||||
|
|
||||||
}
|
}
|
||||||
func Update2_3() {
|
func Update2_3() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func InitRouter() *gin.Engine {
|
|||||||
|
|
||||||
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
||||||
|
|
||||||
r.GET("/debug", v1.GetSystemConfigDebug)
|
r.GET("/v1/debug", v1.GetSystemConfigDebug)
|
||||||
//set user
|
//set user
|
||||||
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
||||||
//get user info
|
//get user info
|
||||||
@@ -205,7 +205,7 @@ func InitRouter() *gin.Engine {
|
|||||||
v1FileGroup.PUT("/rename", v1.RenamePath)
|
v1FileGroup.PUT("/rename", v1.RenamePath)
|
||||||
v1FileGroup.GET("/read", v1.GetFilerContent)
|
v1FileGroup.GET("/read", v1.GetFilerContent)
|
||||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||||
v1FileGroup.GET("/dirpath", v1.DirPath)
|
v1FileGroup.GET("/catalog", v1.DirPath)
|
||||||
//创建目录
|
//创建目录
|
||||||
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
||||||
v1FileGroup.POST("/create", v1.PostCreateFile)
|
v1FileGroup.POST("/create", v1.PostCreateFile)
|
||||||
@@ -218,30 +218,31 @@ 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)
|
||||||
|
|
||||||
//删除分区
|
//删除分区
|
||||||
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
||||||
|
v1DiskGroup.GET("/usb", v1.GetUSBList)
|
||||||
|
|
||||||
//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()
|
||||||
|
|||||||
@@ -35,25 +35,26 @@ func AppList(c *gin.Context) {
|
|||||||
t := c.DefaultQuery("type", "rank")
|
t := c.DefaultQuery("type", "rank")
|
||||||
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)
|
language := c.GetHeader("Language")
|
||||||
for i := 0; i < len(recommend); i++ {
|
recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key, language)
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
// for i := 0; i < len(recommend); i++ {
|
||||||
if ct != nil {
|
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
||||||
list[i].State = ct.State
|
// if ct != nil {
|
||||||
}
|
// recommend[i].State = ct.State
|
||||||
}
|
// }
|
||||||
for i := 0; i < len(list); i++ {
|
// }
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
// for i := 0; i < len(list); i++ {
|
||||||
if ct != nil {
|
// ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
||||||
list[i].State = ct.State
|
// if ct != nil {
|
||||||
}
|
// list[i].State = ct.State
|
||||||
}
|
// }
|
||||||
for i := 0; i < len(community); i++ {
|
// }
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
// for i := 0; i < len(community); i++ {
|
||||||
if ct != nil {
|
// ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
||||||
list[i].State = ct.State
|
// if ct != nil {
|
||||||
}
|
// 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 +138,8 @@ 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)
|
language := c.GetHeader("Language")
|
||||||
|
info := service.MyService.OAPI().GetServerAppInfo(id, "", language)
|
||||||
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) {
|
||||||
|
|||||||
308
route/v1/disk.go
308
route/v1/disk.go
@@ -2,9 +2,14 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"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 +17,143 @@ 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(false)
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
part := make(map[string]int64, len(dbList))
|
||||||
|
for _, v := range dbList {
|
||||||
|
part[v.MountPoint] = v.CreatedAt
|
||||||
|
}
|
||||||
|
findSystem := 0
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
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
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
|
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.Name = "System"
|
||||||
|
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.Name = "System"
|
||||||
|
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" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
temp.SmartStatus.Passed = true
|
||||||
|
}
|
||||||
|
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.MountPoint = list[i].Children[0].MountPoint
|
||||||
|
stor.Size = list[i].Children[0].FSSize
|
||||||
|
stor.Avail = list[i].Children[0].FSAvail
|
||||||
|
stor.Path = list[i].Children[0].Path
|
||||||
|
stor.Type = list[i].Children[0].FsType
|
||||||
|
stor.DriveName = list[i].Name
|
||||||
|
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
|
||||||
|
if len(pathArr) == 3 {
|
||||||
|
stor.Name = pathArr[2]
|
||||||
|
}
|
||||||
|
if t, ok := part[list[i].Children[0].MountPoint]; ok {
|
||||||
|
stor.CreatedAt = t
|
||||||
|
}
|
||||||
|
storage = append(storage, stor)
|
||||||
|
} else {
|
||||||
|
//todo 长度有问题
|
||||||
|
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(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary get disk list
|
// @Summary get disk list
|
||||||
@@ -35,7 +165,7 @@ func GetPlugInDisk(c *gin.Context) {
|
|||||||
// @Router /disk/lists [get]
|
// @Router /disk/lists [get]
|
||||||
func GetPlugInDisks(c *gin.Context) {
|
func GetPlugInDisks(c *gin.Context) {
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
var result []*disk.UsageStat
|
var result []*disk.UsageStat
|
||||||
for _, item := range list {
|
for _, item := range list {
|
||||||
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
||||||
@@ -60,25 +190,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 +266,77 @@ 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")
|
format, _ := strconv.ParseBool(c.PostForm("format"))
|
||||||
if len(path) == 0 || len(serial) == 0 {
|
if len(name) == 0 || len(path) == 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
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
if !file.CheckNotExist("/DATA/" + 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[path] = "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, path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
service.MyService.Disk().AddPartition(path)
|
service.MyService.Disk().AddPartition(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
formatBool := true
|
||||||
|
for formatBool {
|
||||||
|
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if len(currentDisk.Children) != 1 {
|
||||||
|
formatBool = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
}
|
||||||
|
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if len(currentDisk.Children) != 1 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_err.DISK_NEEDS_FORMAT)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mountPath := "/DATA/" + name
|
||||||
|
m := model2.SerialDisk{}
|
||||||
|
m.MountPoint = mountPath
|
||||||
|
m.Path = currentDisk.Children[0].Path
|
||||||
|
m.UUID = currentDisk.Children[0].UUID
|
||||||
|
m.State = 0
|
||||||
|
m.CreatedAt = time.Now().Unix()
|
||||||
|
service.MyService.Disk().SaveMountPoint(m)
|
||||||
|
|
||||||
|
//mount dir
|
||||||
|
service.MyService.Disk().MountDisk(currentDisk.Children[0].Path, mountPath)
|
||||||
|
|
||||||
|
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)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +354,7 @@ func PostMountDisk(c *gin.Context) {
|
|||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
serial := c.PostForm("serial")
|
serial := c.PostForm("serial")
|
||||||
|
|
||||||
mountPath := "/mnt/volume"
|
mountPath := "/DATA/volume"
|
||||||
var list = service.MyService.Disk().GetSerialAll()
|
var list = service.MyService.Disk().GetSerialAll()
|
||||||
var pathMapList = make(map[string]string, len(list))
|
var pathMapList = make(map[string]string, len(list))
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
@@ -165,13 +370,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.UUID = 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 +385,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)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +441,7 @@ func DeleteDisk(c *gin.Context) {
|
|||||||
func GetDiskCheck(c *gin.Context) {
|
func GetDiskCheck(c *gin.Context) {
|
||||||
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
|
||||||
mapList := make(map[string]string)
|
mapList := make(map[string]string)
|
||||||
|
|
||||||
@@ -229,7 +450,7 @@ func GetDiskCheck(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range dbList {
|
for _, v := range dbList {
|
||||||
if _, ok := mapList[v.Serial]; !ok {
|
if _, ok := mapList[v.UUID]; !ok {
|
||||||
//disk undefind
|
//disk undefind
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"})
|
||||||
return
|
return
|
||||||
@@ -238,3 +459,38 @@ func GetDiskCheck(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 check mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/usb [get]
|
||||||
|
func GetUSBList(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.Name
|
||||||
|
temp.Size = v.Size
|
||||||
|
mountTemp := true
|
||||||
|
if len(v.Children) == 0 {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
for _, child := range v.Children {
|
||||||
|
if len(child.MountPoint) > 0 {
|
||||||
|
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||||
|
temp.Avail += avail
|
||||||
|
} else {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp.Mount = mountTemp
|
||||||
|
data = append(data, temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ func SpeedPush(c *gin.Context) {
|
|||||||
// @Router /app/install/{id} [post]
|
// @Router /app/install/{id} [post]
|
||||||
func InstallApp(c *gin.Context) {
|
func InstallApp(c *gin.Context) {
|
||||||
appId := c.Param("id")
|
appId := c.Param("id")
|
||||||
|
language := c.GetHeader("Language")
|
||||||
var appInfo model.ServerAppList
|
var appInfo model.ServerAppList
|
||||||
m := model.CustomizationPostData{}
|
m := model.CustomizationPostData{}
|
||||||
c.BindJSON(&m)
|
c.BindJSON(&m)
|
||||||
@@ -174,7 +175,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, "", language)
|
||||||
|
|
||||||
} 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 length: " + strconv.Itoa(len(config.SystemConfigInfo.SyncKey))
|
||||||
|
|
||||||
|
var bugContent string = fmt.Sprintf(`
|
||||||
|
- 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()
|
||||||
@@ -234,10 +259,104 @@ func PostKillCasaOS(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /sys/info [get]
|
// @Router /sys/info [get]
|
||||||
func Info(c *gin.Context) {
|
func Info(c *gin.Context) {
|
||||||
var data = make(map[string]interface{}, 5)
|
var data = make(map[string]interface{}, 6)
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
data["disk"] = list
|
|
||||||
|
summary := model.Summary{}
|
||||||
|
healthy := true
|
||||||
|
findSystem := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
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 == "/" {
|
||||||
|
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if list[i].Children[j].MountPoint == "/" {
|
||||||
|
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
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" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//list[i].Temperature = temp.Temperature.Current
|
||||||
|
if !temp.SmartStatus.Passed {
|
||||||
|
healthy = false
|
||||||
|
}
|
||||||
|
if len(list[i].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children {
|
||||||
|
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.Health = healthy
|
||||||
|
data["disk"] = summary
|
||||||
|
usbList := service.MyService.Disk().LSBLK(false)
|
||||||
|
usb := []model.DriveUSB{}
|
||||||
|
for _, v := range usbList {
|
||||||
|
if v.Tran == "usb" {
|
||||||
|
temp := model.DriveUSB{}
|
||||||
|
temp.Model = v.Model
|
||||||
|
temp.Name = v.Name
|
||||||
|
temp.Size = v.Size
|
||||||
|
mountTemp := true
|
||||||
|
if len(v.Children) == 0 {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
for _, child := range v.Children {
|
||||||
|
if len(child.MountPoint) > 0 {
|
||||||
|
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||||
|
temp.Avail += avail
|
||||||
|
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
||||||
|
temp.Used += used
|
||||||
|
} else {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp.Mount = mountTemp
|
||||||
|
usb = append(usb, temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data["usb"] = usb
|
||||||
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{})
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 登录zerotier获取token
|
// @Summary 登录zerotier获取token
|
||||||
@@ -432,11 +433,17 @@ func ZeroTierDeleteNetwork(c *gin.Context) {
|
|||||||
// @Router /zerotier/join/{id} [post]
|
// @Router /zerotier/join/{id} [post]
|
||||||
func ZeroTierJoinNetwork(c *gin.Context) {
|
func ZeroTierJoinNetwork(c *gin.Context) {
|
||||||
networkId := c.Param("id")
|
networkId := c.Param("id")
|
||||||
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
if len(networkId) != 16 {
|
||||||
if len(networkId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
for _, v := range networkId {
|
||||||
|
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,10 +457,19 @@ func ZeroTierJoinNetwork(c *gin.Context) {
|
|||||||
// @Router /zerotier/leave/{id} [post]
|
// @Router /zerotier/leave/{id} [post]
|
||||||
func ZeroTierLeaveNetwork(c *gin.Context) {
|
func ZeroTierLeaveNetwork(c *gin.Context) {
|
||||||
networkId := c.Param("id")
|
networkId := c.Param("id")
|
||||||
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
|
||||||
if len(networkId) == 0 {
|
if len(networkId) != 16 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, v := range networkId {
|
||||||
|
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CasaService interface {
|
type CasaService interface {
|
||||||
GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList)
|
GetServerList(index, size, tp, categoryId, key, language 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, language string) model.ServerAppList
|
||||||
ShareAppFile(body []byte) string
|
ShareAppFile(body []byte) string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,9 +45,9 @@ func (o *casaService) GetTaskList(size int) []model2.TaskDBModel {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList) {
|
func (o *casaService) GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList) {
|
||||||
|
|
||||||
keyName := fmt.Sprintf("list_%s_%s_%s_%s", index, size, tp, categoryId)
|
keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, language)
|
||||||
|
|
||||||
if result, ok := Cache.Get(keyName); ok {
|
if result, ok := Cache.Get(keyName); ok {
|
||||||
res, ok := result.(string)
|
res, ok := result.(string)
|
||||||
@@ -63,7 +63,7 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (re
|
|||||||
|
|
||||||
head["Authorization"] = GetToken()
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key, head)
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key+"&language="+language, head)
|
||||||
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &list)
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &list)
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend)
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend)
|
||||||
@@ -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, language 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+"&language="+language, 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"
|
||||||
@@ -19,9 +20,10 @@ import (
|
|||||||
|
|
||||||
type DiskService interface {
|
type DiskService interface {
|
||||||
GetPlugInDisk() []string
|
GetPlugInDisk() []string
|
||||||
LSBLK() []model.LSBLKModel
|
LSBLK(isUseCache bool) []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,23 +109,21 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
//get disk details
|
//get disk details
|
||||||
func (d *diskService) LSBLK() []model.LSBLKModel {
|
func (d *diskService) LSBLK(isUseCache bool) []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 && isUseCache {
|
||||||
|
|
||||||
res, ok := result.([]model.LSBLKModel)
|
res, ok := result.([]model.LSBLKModel)
|
||||||
if ok {
|
if 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("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
|
||||||
d.db.Create(&m)
|
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) {
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ package model
|
|||||||
//SerialAdvanced Technology Attachment (STAT)
|
//SerialAdvanced Technology Attachment (STAT)
|
||||||
type SerialDisk struct {
|
type SerialDisk struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Serial string `json:"serial"`
|
UUID string `json:"uuid"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
State int `json:"state"`
|
State int `json:"state"`
|
||||||
MountPoint string `json:"mount_point"`
|
MountPoint string `json:"mount_point"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SerialDisk) TableName() string {
|
func (p *SerialDisk) TableName() string {
|
||||||
|
|||||||
@@ -4,18 +4,20 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/zerotier"
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/zerotier"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ZeroTierService interface {
|
type ZeroTierService interface {
|
||||||
@@ -33,6 +35,7 @@ type ZeroTierService interface {
|
|||||||
DeleteMember(token string, id, mId string) interface{}
|
DeleteMember(token string, id, mId string) interface{}
|
||||||
DeleteNetwork(token, id string) interface{}
|
DeleteNetwork(token, id string) interface{}
|
||||||
GetJoinNetworks() string
|
GetJoinNetworks() string
|
||||||
|
NetworkIdFilter(letter rune) bool
|
||||||
}
|
}
|
||||||
type zerotierStruct struct {
|
type zerotierStruct struct {
|
||||||
}
|
}
|
||||||
@@ -333,6 +336,13 @@ func (c *zerotierStruct) GetJoinNetworks() string {
|
|||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *zerotierStruct) NetworkIdFilter(letter rune) bool {
|
||||||
|
if unicode.IsNumber(letter) || unicode.IsLetter(letter) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
func NewZeroTierService() ZeroTierService {
|
func NewZeroTierService() ZeroTierService {
|
||||||
//初始化client
|
//初始化client
|
||||||
client = http.Client{Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
client = http.Client{Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
@@ -86,10 +87,10 @@ func (c *zima) GetDirPath(path string) []model.Path {
|
|||||||
|
|
||||||
if strings.Count(path, "/") > 0 {
|
if strings.Count(path, "/") > 0 {
|
||||||
for _, l := range ls {
|
for _, l := range ls {
|
||||||
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir()})
|
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime()})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true})
|
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})
|
||||||
}
|
}
|
||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,35 @@ version_0_2_3() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# add in v0.2.5
|
||||||
|
|
||||||
|
readonly CASA_DEPANDS="curl smartmontools parted fdisk partprobe"
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,13 +115,11 @@ AddPartition() {
|
|||||||
parted -s $1 mklabel gpt
|
parted -s $1 mklabel gpt
|
||||||
|
|
||||||
parted -s $1 mkpart primary ext4 0 100%
|
parted -s $1 mkpart primary ext4 0 100%
|
||||||
|
PATH=`lsblk -r $1 | sort | grep part | head -n 1 | awk '{print $1}'`
|
||||||
mkfs.ext4 $11
|
mkfs.ext4 -m 1 /dev/${PATH}
|
||||||
|
|
||||||
partprobe $1
|
partprobe $1
|
||||||
|
|
||||||
# mount $11 $2
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#磁盘类型
|
#磁盘类型
|
||||||
@@ -148,20 +144,20 @@ 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}'
|
||||||
}
|
}
|
||||||
|
|
||||||
#检查没有使用的挂载点删除文件夹
|
#检查没有使用的挂载点删除文件夹
|
||||||
AutoRemoveUnuseDir() {
|
AutoRemoveUnuseDir() {
|
||||||
DIRECTORY="/mnt/"
|
DIRECTORY="/DATA/"
|
||||||
dir=$(ls -l $DIRECTORY | awk '/^d/ {print $NF}')
|
dir=$(ls -l $DIRECTORY | grep "Storage[0-9]" | awk '/^d/ {print $NF}')
|
||||||
for i in $dir; do
|
for i in $dir; do
|
||||||
|
|
||||||
path="$DIRECTORY$i"
|
path="$DIRECTORY$i"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
# copy to /casaOS/util/shell path
|
# copy to /casaOS/util/shell path
|
||||||
# chmod 755
|
# chmod 755
|
||||||
@@ -30,23 +30,32 @@ do_mount() {
|
|||||||
|
|
||||||
# Figure out a mount point to use
|
# Figure out a mount point to use
|
||||||
# LABEL=${ID_FS_LABEL}
|
# LABEL=${ID_FS_LABEL}
|
||||||
LABEL=${DEVBASE}
|
# LABEL=${DEVBASE}
|
||||||
if grep -q " /mnt/casa_${LABEL} " /etc/mtab; then
|
# if grep -q " /DATA/USB_${LABEL} " /etc/mtab; then
|
||||||
# Already in use, make a unique one
|
# # Already in use, make a unique one
|
||||||
LABEL+="-${DEVBASE}"
|
# LABEL+="-${DEVBASE}"
|
||||||
fi
|
# fi
|
||||||
DEV_LABEL="${LABEL}"
|
# DEV_LABEL="${LABEL}"
|
||||||
|
|
||||||
# Use the device name in case the drive doesn't have label
|
# # Use the device name in case the drive doesn't have label
|
||||||
if [ -z ${DEV_LABEL} ]; then
|
# if [ -z ${DEV_LABEL} ]; then
|
||||||
DEV_LABEL="${DEVBASE}"
|
# DEV_LABEL="${DEVBASE}"
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
MOUNT_POINT="/mnt/casa_${DEV_LABEL}"
|
MOUNT_POINT="/DATA/USB_Storage1"
|
||||||
|
arr=("/DATA/USB_Storage1" "/DATA/USB_Storage2" "/DATA/USB_Storage3" "/DATA/USB_Storage4" "/DATA/USB_Storage5" "/DATA/USB_Storage6" "/DATA/USB_Storage7" "/DATA/USB_Storage8" "/DATA/USB_Storage9" "/DATA/USB_Storage10" "/DATA/USB_Storage11" "/DATA/USB_Storage12")
|
||||||
|
for folder in ${arr[@]}; do
|
||||||
|
#如果文件夹不存在,创建文件夹
|
||||||
|
if [ ! -d "$folder" ]; then
|
||||||
|
mkdir -p ${folder}
|
||||||
|
MOUNT_POINT=$folder
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
${log} "Mount point: ${MOUNT_POINT}"
|
${log} "Mount point: ${MOUNT_POINT}"
|
||||||
|
|
||||||
mkdir -p ${MOUNT_POINT}
|
|
||||||
|
|
||||||
# # Global mount options
|
# # Global mount options
|
||||||
# OPTS="rw,relatime"
|
# OPTS="rw,relatime"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
const CURRENTVERSION = "0.2.5"
|
const CURRENTVERSION = "0.2.8"
|
||||||
const BODY = "<li>New App Store</li><li>Fix minor bugs</li>"
|
|
||||||
|
const BODY = "<li>Compatible with more types of disks</li><li>Add usb display</li><li>Change translation</li>"
|
||||||
|
|||||||
BIN
web/img/storage.d487ddb6.png
Normal file
BIN
web/img/storage.d487ddb6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
677
web/js/2.js
677
web/js/2.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
10
web/js/4.js
10
web/js/4.js
File diff suppressed because one or more lines are too long
164
web/js/app.js
164
web/js/app.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user