diff --git a/CHANGELOG.md b/CHANGELOG.md
index d64918d..f78ec4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+## [0.3.5-alpha] - 2022-08-08
+
+### Added
+
+- [File] Condivisione samba montata
+- [File] Condivisione dei file tramite samba
+
+### Changed
+
+- [Disk] Supporto per il montaggio di dischi dati esistenti
+
+### Fixed
+
+- fixed uninstalling imported docker container apps results in wiping ALL your config data from them ([#360](https://github.com/IceWhaleTech/CasaOS/issues/360))
+
## [0.3.4] - 2022-07-29(UTC)
### Added
diff --git a/go.mod b/go.mod
index 47e365e..550dbc5 100644
--- a/go.mod
+++ b/go.mod
@@ -27,6 +27,7 @@ require (
github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/mock v1.6.0
github.com/gomodule/redigo v1.8.5
github.com/google/go-github/v36 v36.0.0
github.com/google/uuid v1.3.0 // indirect
@@ -56,6 +57,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect
+ github.com/stretchr/testify v1.7.0
github.com/tidwall/gjson v1.10.2
github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/ugorji/go v1.2.6 // indirect
diff --git a/main.go b/main.go
index 932f28d..e1ec179 100644
--- a/main.go
+++ b/main.go
@@ -15,6 +15,7 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
+ "github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron"
"gorm.io/gorm"
@@ -26,21 +27,31 @@ var configFlag = flag.String("c", "", "config address")
var dbFlag = flag.String("db", "", "db path")
var resetUser = flag.Bool("ru", false, "reset user")
var user = flag.String("user", "", "user name")
+var version = flag.Bool("v", false, "show version")
func init() {
flag.Parse()
+ if *version {
+ fmt.Println("v" + types.CURRENTVERSION)
+ return
+ }
config.InitSetup(*configFlag)
config.UpdateSetup()
+
loger.LogInit()
if len(*dbFlag) == 0 {
*dbFlag = config.AppInfo.DBPath + "/db"
}
+
sqliteDB = sqlite.GetDb(*dbFlag)
//gredis.GetRedisConn(config.RedisInfo),
+
service.MyService = service.NewService(sqliteDB)
+
service.Cache = cache.Init()
service.GetToken()
+
service.NewVersionApp = make(map[string]string)
route.InitFunction()
@@ -62,6 +73,9 @@ func init() {
// @BasePath /v1
func main() {
service.NotifyMsg = make(chan notify.Message, 10)
+ if *version {
+ return
+ }
if *resetUser {
if user == nil || len(*user) == 0 {
fmt.Println("user is empty")
diff --git a/model/connections.go b/model/connections.go
index c0ab07b..84719ab 100644
--- a/model/connections.go
+++ b/model/connections.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-27 10:30:43
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-27 11:36:08
+ * @LastEditTime: 2022-08-04 20:06:04
* @FilePath: /CasaOS/model/connections.go
* @Description:
* @Website: https://www.casaos.io
@@ -16,6 +16,5 @@ type Connections struct {
Password string `json:"password,omitempty"`
Host string `json:"host"`
Port string `json:"port"`
- Directory string `json:"directory"`
MountPoint string `json:"mount_point"`
}
diff --git a/model/disk.go b/model/disk.go
index c573e13..75d3bc5 100644
--- a/model/disk.go
+++ b/model/disk.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-13 10:43:45
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-29 14:21:59
+ * @LastEditTime: 2022-08-03 14:45:35
* @FilePath: /CasaOS/model/disk.go
* @Description:
* @Website: https://www.casaos.io
@@ -61,16 +61,21 @@ type Drive struct {
}
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"`
+ Name string `json:"name"`
+ Size uint64 `json:"size"`
+ Model string `json:"model"`
+ Avail uint64 `json:"avail"`
+ Children []USBChildren `json:"children"`
+}
+type USBChildren struct {
+ Name string `json:"name"`
+ Size uint64 `json:"size"`
+ Avail uint64 `json:"avail"`
+ MountPoint string `json:"mount_point"`
}
type Storage struct {
- MountPoint string `json:"mountpoint"`
+ MountPoint string `json:"mount_point"`
Size string `json:"size"`
Avail string `json:"avail"` //可用空间
Type string `json:"type"`
diff --git a/model/zima.go b/model/zima.go
index 5e8e664..e144b7c 100644
--- a/model/zima.go
+++ b/model/zima.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-28 13:47:00
+ * @LastEditTime: 2022-08-01 18:32:57
* @FilePath: /CasaOS/model/zima.go
* @Description:
* @Website: https://www.casaos.io
@@ -13,13 +13,13 @@ package model
import "time"
type Path struct {
- Name string `json:"name"` //File name or document name
- Path string `json:"path"` //Full path to file or folder
- IsDir bool `json:"is_dir"` //Is it a folder
- Date time.Time `json:"date"`
- Size int64 `json:"size"` //File Size
- Type string `json:"type,omitempty"`
- Label string `json:"label,omitempty"`
- Write bool `json:"write"`
- Extensions map[string]string `json:"extensions"`
+ Name string `json:"name"` //File name or document name
+ Path string `json:"path"` //Full path to file or folder
+ IsDir bool `json:"is_dir"` //Is it a folder
+ Date time.Time `json:"date"`
+ Size int64 `json:"size"` //File Size
+ Type string `json:"type,omitempty"`
+ Label string `json:"label,omitempty"`
+ Write bool `json:"write"`
+ Extensions map[string]interface{} `json:"extensions"`
}
diff --git a/pkg/samba/smaba.go b/pkg/samba/smaba.go
index 0d35e0b..58a9874 100644
--- a/pkg/samba/smaba.go
+++ b/pkg/samba/smaba.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-27 10:35:29
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-27 10:40:26
+ * @LastEditTime: 2022-08-01 13:56:44
* @FilePath: /CasaOS/pkg/samba/smaba.go
* @Description:
* @Website: https://www.casaos.io
@@ -47,3 +47,29 @@ func ConnectSambaService(host, port, username, password, directory string) error
}
return errors.New("directory not found")
}
+
+//get share name list
+func GetSambaSharesList(host, port, username, password string) ([]string, error) {
+ conn, err := net.Dial("tcp", host+":"+port)
+ if err != nil {
+ return nil, err
+ }
+ defer conn.Close()
+ d := &smb2.Dialer{
+ Initiator: &smb2.NTLMInitiator{
+ User: username,
+ Password: password,
+ },
+ }
+
+ s, err := d.Dial(conn)
+ if err != nil {
+ return nil, err
+ }
+ defer s.Logoff()
+ names, err := s.ListSharenames()
+ if err != nil {
+ return nil, err
+ }
+ return names, err
+}
diff --git a/route/init.go b/route/init.go
index c3a1591..19e4e20 100644
--- a/route/init.go
+++ b/route/init.go
@@ -1,11 +1,13 @@
package route
import (
+ "fmt"
"os"
"strconv"
"strings"
"github.com/IceWhaleTech/CasaOS/pkg/config"
+ "github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@@ -17,13 +19,12 @@ import (
func InitFunction() {
ShellInit()
CheckSerialDiskMount()
-
CheckToken2_11()
ImportApplications()
// Soon to be removed
ChangeAPIUrl()
-
MoveUserToDB()
+ InitNetworkMount()
}
func CheckSerialDiskMount() {
@@ -40,25 +41,25 @@ func CheckSerialDiskMount() {
command.ExecEnabledSMART(v.Path)
if v.Children != nil {
for _, h := range v.Children {
- 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)
- }
+ //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)
- }
-
}
+ 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)
+ }
+
}
+ //}
}
}
}
@@ -138,3 +139,32 @@ func MoveUserToDB() {
}
}
+
+func InitNetworkMount() {
+ connections := service.MyService.Connections().GetConnectionsList()
+ for _, v := range connections {
+ connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
+ directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
+ if err != nil {
+ service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
+ continue
+ }
+ baseHostPath := "/mnt/" + connection.Host
+
+ mountPointList := service.MyService.System().GetDirPath(baseHostPath)
+ for _, v := range mountPointList {
+ service.MyService.Connections().UnmountSmaba(v.Path)
+ }
+
+ os.RemoveAll(baseHostPath)
+
+ file.IsNotExistMkDir(baseHostPath)
+ for _, v := range directories {
+ mountPoint := baseHostPath + "/" + v
+ file.IsNotExistMkDir(mountPoint)
+ service.MyService.Connections().MountSmaba(connection.Username, connection.Host, v, connection.Port, mountPoint, connection.Password)
+ }
+ connection.Directories = strings.Join(directories, ",")
+ service.MyService.Connections().UpdateConnection(&connection)
+ }
+}
diff --git a/route/periodical.go b/route/periodical.go
index 0740ab2..c3bab59 100644
--- a/route/periodical.go
+++ b/route/periodical.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-01 15:11:36
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-21 15:25:07
+ * @LastEditTime: 2022-08-03 14:49:15
* @FilePath: /CasaOS/route/periodical.go
* @Description:
* @Website: https://www.casaos.io
@@ -133,21 +133,14 @@ func SendUSBBySocket() {
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)
}
}
@@ -250,21 +243,12 @@ func SendAllHardwareStatusBySocket() {
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)
}
}
diff --git a/route/route.go b/route/route.go
index 823aff3..8629bd9 100644
--- a/route/route.go
+++ b/route/route.go
@@ -196,6 +196,8 @@ func InitRouter() *gin.Engine {
//v1DisksGroup.POST("", v1.PostMountDisk)
v1DisksGroup.GET("", v1.GetDiskList)
+ v1DisksGroup.GET("/usb", v1.GetDisksUSBList)
+ v1DisksGroup.DELETE("/usb", v1.DeleteDiskUSB)
// //format storage
// v1DiskGroup.POST("/format", v1.PostDiskFormat)
diff --git a/route/v1/disk.go b/route/v1/disk.go
index a0b7f47..7d5a9c9 100644
--- a/route/v1/disk.go
+++ b/route/v1/disk.go
@@ -1,7 +1,6 @@
package v1
import (
- "fmt"
"net/http"
"reflect"
"strconv"
@@ -45,19 +44,12 @@ func GetDiskList(c *gin.Context) {
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)
}
}
@@ -189,6 +181,60 @@ func GetDiskList(c *gin.Context) {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
+// @Summary disk list
+// @Produce application/json
+// @Accept application/json
+// @Tags disk
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /disk/list [get]
+func GetDisksUSBList(c *gin.Context) {
+ list := service.MyService.Disk().LSBLK(false)
+ data := []model.DriveUSB{}
+ for _, v := range list {
+ if v.Tran == "usb" {
+ temp := model.DriveUSB{}
+ temp.Model = v.Model
+ temp.Name = v.Label
+ if temp.Name == "" {
+ temp.Name = v.Name
+ }
+ temp.Size = v.Size
+ children := []model.USBChildren{}
+ for _, child := range v.Children {
+
+ if len(child.MountPoint) > 0 {
+ tempChildren := model.USBChildren{}
+ tempChildren.MountPoint = child.MountPoint
+ tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64)
+ tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64)
+ tempChildren.Name = child.Label
+ avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
+ children = append(children, tempChildren)
+ temp.Avail += avail
+ }
+ }
+
+ temp.Children = children
+ data = append(data, temp)
+ }
+ }
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+
+}
+
+func DeleteDiskUSB(c *gin.Context) {
+ js := make(map[string]string)
+ c.ShouldBind(&js)
+ mountPoint := js["mount_point"]
+ if file.CheckNotExist(mountPoint) {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
+ return
+ }
+ service.MyService.Disk().UmountUSB(mountPoint)
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint})
+}
+
// @Summary get disk list
// @Produce application/json
// @Accept application/json
@@ -274,10 +320,10 @@ func PostDiskAddPartition(c *gin.Context) {
js := make(map[string]interface{})
c.ShouldBind(&js)
path := js["path"].(string)
- name := js["name"].(string)
+ //name := js["name"].(string)
format := js["format"].(bool)
- if len(name) == 0 || len(path) == 0 {
+ if len(path) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
@@ -285,11 +331,14 @@ func PostDiskAddPartition(c *gin.Context) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
return
}
- if !file.CheckNotExist("/DATA/" + name) {
- // /mnt/name exist
- c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
- return
- }
+
+ //diskInfo := service.MyService.Disk().GetDiskInfo(path)
+
+ // if !file.CheckNotExist("/DATA/" + name) {
+ // // /mnt/name exist
+ // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
+ // return
+ // }
diskMap[path] = "busying"
currentDisk := service.MyService.Disk().GetDiskInfo(path)
if format {
@@ -302,33 +351,43 @@ func PostDiskAddPartition(c *gin.Context) {
service.MyService.Disk().AddPartition(path)
}
- formatBool := true
- for formatBool {
- currentDisk = service.MyService.Disk().GetDiskInfo(path)
- fmt.Println(currentDisk.Children)
- if len(currentDisk.Children) > 0 {
- formatBool = false
- break
- }
- time.Sleep(time.Second)
- }
+ // formatBool := true
+ // for formatBool {
+ // currentDisk = service.MyService.Disk().GetDiskInfo(path)
+ // if len(currentDisk.Children) > 0 {
+ // formatBool = false
+ // break
+ // }
+ // time.Sleep(time.Second)
+ // }
currentDisk = service.MyService.Disk().GetDiskInfo(path)
// if len(currentDisk.Children) != 1 {
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
// return
// }
for i := 0; i < len(currentDisk.Children); i++ {
- mountPath := "/DATA/" + name
+ childrenName := currentDisk.Children[i].Label
+ if len(childrenName) == 0 {
+ childrenName = "Storage_" + currentDisk.Children[i].Name
+ }
+ mountPath := "/DATA/" + childrenName
+ if !file.CheckNotExist(mountPath) {
+ ls := service.MyService.System().GetDirPath(mountPath)
+ if len(ls) > 0 {
+ // exist
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
+ return
+ }
+ }
m := model2.SerialDisk{}
- m.MountPoint = mountPath + strconv.Itoa(i)
+ m.MountPoint = mountPath
m.Path = currentDisk.Children[i].Path
m.UUID = currentDisk.Children[i].UUID
m.State = 0
m.CreatedAt = time.Now().Unix()
service.MyService.Disk().SaveMountPoint(m)
-
//mount dir
- service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath+strconv.Itoa(i))
+ service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath)
}
service.MyService.Disk().RemoveLSBLKCache()
@@ -339,7 +398,7 @@ func PostDiskAddPartition(c *gin.Context) {
msg := notify.StorageMessage{}
msg.Action = "ADDED"
msg.Path = currentDisk.Children[0].Path
- msg.Volume = "/DATA/" + name
+ msg.Volume = "/DATA/"
msg.Size = currentDisk.Children[0].Size
msg.Type = currentDisk.Children[0].Tran
service.MyService.Notify().SendStorageBySocket(msg)
diff --git a/route/v1/docker.go b/route/v1/docker.go
index 3e15ae1..c04cce8 100644
--- a/route/v1/docker.go
+++ b/route/v1/docker.go
@@ -209,7 +209,7 @@ func InstallApp(c *gin.Context) {
dockerImage = m.Image
dockerImageVersion = "latest"
}
-
+ m.Image = dockerImage + ":" + dockerImageVersion
for _, u := range m.Ports {
if u.Protocol == "udp" {
@@ -334,11 +334,11 @@ func InstallApp(c *gin.Context) {
return
}
- for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
+ for !service.MyService.Docker().IsExistImage(m.Image) {
time.Sleep(time.Second)
}
- _, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m)
+ _, err = service.MyService.Docker().DockerContainerCreate(m, "")
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
notify := notify.Application{}
@@ -829,7 +829,6 @@ func UpdateSetting(c *gin.Context) {
// c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
// return
// }
-
service.MyService.Docker().DockerContainerStop(id)
portMap, _ := strconv.Atoi(m.PortMap)
if !port2.IsPortAvailable(portMap, "tcp") {
@@ -874,7 +873,7 @@ func UpdateSetting(c *gin.Context) {
service.MyService.Docker().DockerContainerUpdateName(id, id)
//service.MyService.Docker().DockerContainerRemove(id, true)
- containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m)
+ containerId, err := service.MyService.Docker().DockerContainerCreate(m, id)
if err != nil {
service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
service.MyService.Docker().DockerContainerStart(id)
diff --git a/route/v1/file.go b/route/v1/file.go
index 44a0d0f..0b2dbc7 100644
--- a/route/v1/file.go
+++ b/route/v1/file.go
@@ -1,6 +1,7 @@
package v1
import (
+ "fmt"
"io"
"io/ioutil"
"log"
@@ -221,7 +222,7 @@ func DirPath(c *gin.Context) {
shares := service.MyService.Shares().GetSharesList()
sharesMap := make(map[string]string)
for _, v := range shares {
- sharesMap[v.Path] = v.Name
+ sharesMap[v.Path] = fmt.Sprint(v.ID)
}
if path == "/DATA/AppData" {
list := service.MyService.Docker().DockerContainerList()
@@ -234,11 +235,6 @@ func DirPath(c *gin.Context) {
info[i].Label = v
info[i].Type = "application"
}
- if _, ok := sharesMap[info[i].Path]; ok {
- ex := make(map[string]string)
- ex["shared"] = "true"
- info[i].Extensions = ex
- }
}
} else if path == "/DATA" {
disk := make(map[string]string)
@@ -265,14 +261,19 @@ func DirPath(c *gin.Context) {
if v, ok := disk[info[i].Path]; ok {
info[i].Type = v
}
- if _, ok := sharesMap[info[i].Path]; ok {
- ex := make(map[string]string)
- ex["shared"] = "true"
- info[i].Extensions = ex
- }
}
}
+ for i := 0; i < len(info); i++ {
+ if v, ok := sharesMap[info[i].Path]; ok {
+ ex := make(map[string]interface{})
+ shareEx := make(map[string]string)
+ shareEx["shared"] = "true"
+ shareEx["id"] = v
+ ex["share"] = shareEx
+ info[i].Extensions = ex
+ }
+ }
//Hide the files or folders in operation
fileQueue := make(map[string]string)
if len(service.OpStrArr) > 0 {
diff --git a/route/v1/samba.go b/route/v1/samba.go
index d330684..5bb3dc2 100644
--- a/route/v1/samba.go
+++ b/route/v1/samba.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-26 11:08:48
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-28 11:51:03
+ * @LastEditTime: 2022-08-05 12:16:39
* @FilePath: /CasaOS/route/v1/samba.go
* @Description:
* @Website: https://www.casaos.io
@@ -12,6 +12,7 @@ package v1
import (
"fmt"
+ "os"
"path/filepath"
"strings"
@@ -108,10 +109,9 @@ func GetSambaConnectionsList(c *gin.Context) {
connectionList = append(connectionList, model.Connections{
ID: v.ID,
Username: v.Username,
- MountPoint: v.MountPoint,
- Directory: v.Directory,
Port: v.Port,
Host: v.Host,
+ MountPoint: v.MountPoint,
})
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connectionList})
@@ -119,29 +119,24 @@ func GetSambaConnectionsList(c *gin.Context) {
func PostSambaConnectionsCreate(c *gin.Context) {
connection := model.Connections{}
- err := c.ShouldBindJSON(&connection)
- fmt.Println(err)
+ c.ShouldBindJSON(&connection)
if connection.Port == "" {
connection.Port = "445"
}
- if connection.Username == "" || connection.Directory == "" || connection.Host == "" || connection.MountPoint == "" {
+ if connection.Username == "" || connection.Host == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
// check is exists
- connections := service.MyService.Connections().GetConnectionByDirectory(connection.Directory)
+ connections := service.MyService.Connections().GetConnectionByHost(connection.Host)
if len(connections) > 0 {
- for _, v := range connections {
- if v.Host == connection.Host {
- c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)})
- return
- }
- }
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)})
+ return
}
// check connect is ok
- if err := samba.ConnectSambaService(connection.Host, connection.Port, connection.Username, connection.Password, connection.Directory); err != nil {
- fmt.Println("check", err)
+ directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
+ if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
}
@@ -149,13 +144,21 @@ func PostSambaConnectionsCreate(c *gin.Context) {
connectionDBModel := model2.ConnectionsDBModel{}
connectionDBModel.Username = connection.Username
connectionDBModel.Password = connection.Password
- connectionDBModel.Directory = connection.Directory
connectionDBModel.Host = connection.Host
connectionDBModel.Port = connection.Port
- connectionDBModel.MountPoint = connection.MountPoint
- file.IsNotExistMkDir(connection.MountPoint)
+ connectionDBModel.Directories = strings.Join(directories, ",")
+ baseHostPath := "/mnt/" + connection.Host
+ connectionDBModel.MountPoint = baseHostPath
+ connection.MountPoint = baseHostPath
+ file.IsNotExistMkDir(baseHostPath)
+ for _, v := range directories {
+ mountPoint := baseHostPath + "/" + v
+ file.IsNotExistMkDir(mountPoint)
+ service.MyService.Connections().MountSmaba(connectionDBModel.Username, connectionDBModel.Host, v, connectionDBModel.Port, mountPoint, connectionDBModel.Password)
+ }
+
service.MyService.Connections().CreateConnection(&connectionDBModel)
- service.MyService.Connections().MountSmaba(&connectionDBModel)
+
connection.ID = connectionDBModel.ID
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connection})
}
@@ -167,7 +170,11 @@ func DeleteSambaConnections(c *gin.Context) {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.Record_NOT_EXIST, Message: common_err.GetMsg(common_err.Record_NOT_EXIST)})
return
}
- service.MyService.Connections().UnmountSmaba(connection.MountPoint)
+ mountPointList := service.MyService.System().GetDirPath(connection.MountPoint)
+ for _, v := range mountPointList {
+ service.MyService.Connections().UnmountSmaba(v.Path)
+ }
+ os.RemoveAll(connection.MountPoint)
service.MyService.Connections().DeleteConnection(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
}
diff --git a/route/v1/samba_test.go b/route/v1/samba_test.go
new file mode 100644
index 0000000..455b973
--- /dev/null
+++ b/route/v1/samba_test.go
@@ -0,0 +1,73 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-08-02 15:10:56
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-02 16:58:42
+ * @FilePath: /CasaOS/route/v1/samba_test.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package v1
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gin-gonic/gin"
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
+)
+
+func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
+ req, _ := http.NewRequest(method, path, nil)
+ w := httptest.NewRecorder()
+ r.ServeHTTP(w, req)
+ return w
+}
+
+// func TestHelloWorld(t *testing.T) {
+// // Build our expected body
+// body := gin.H{
+// "hello": "world",
+// }
+// // Grab our router
+// router := "SetupRouter()"
+// // Perform a GET request with that handler.
+// w := performRequest(router, "GET", "/")
+// // Assert we encoded correctly,
+// // the request gives a 200
+// assert.Equal(t, http.StatusOK, w.Code)
+// // Convert the JSON response to a map
+// var response map[string]string
+// err := json.Unmarshal([]byte(w.Body.String()), &response)
+// // Grab the value & whether or not it exists
+// value, exists := response["hello"]
+// // Make some assertions on the correctness of the response.
+// assert.Nil(t, err)
+// assert.True(t, exists)
+// assert.Equal(t, body["hello"], value)
+// }
+
+func TestGetSambaSharesList(t *testing.T) {
+ gin.SetMode(gin.TestMode)
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ executeWithContext := func() *httptest.ResponseRecorder {
+ response := httptest.NewRecorder()
+ con, ginEngine := gin.CreateTestContext(response)
+
+ requestUrl := "/v1/samba/shares"
+ httpRequest, _ := http.NewRequest("GET", requestUrl, nil)
+ GetSambaSharesList(con)
+ ginEngine.ServeHTTP(response, httpRequest)
+ return response
+ }
+
+ t.Run("Happy", func(t *testing.T) {
+ res := executeWithContext()
+ assert.Equal(t, http.StatusOK, res.Code)
+ })
+
+}
diff --git a/route/v1/storage.go b/route/v1/storage.go
index ff1ab74..d4169cc 100644
--- a/route/v1/storage.go
+++ b/route/v1/storage.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-11 16:02:29
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-29 14:14:17
+ * @LastEditTime: 2022-08-04 11:27:25
* @FilePath: /CasaOS/route/v1/storage.go
* @Description:
* @Website: https://www.casaos.io
@@ -13,7 +13,6 @@ package v1
import (
"reflect"
"strconv"
- "strings"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
@@ -22,14 +21,22 @@ import (
)
func GetStorageList(c *gin.Context) {
-
+ system := c.Query("system")
storages := []model.Storages{}
disks := service.MyService.Disk().LSBLK(false)
diskNumber := 1
children := 1
+ findSystem := 0
for _, d := range disks {
- children = 1
- if d.Tran == "sata" || d.Tran == "nvme" || d.Tran == "spi" || d.Tran == "sas" || strings.Contains(d.SubSystems, "virtio") || (d.Tran == "ata" && d.Type == "disk") {
+ if d.Tran != "usb" {
+ tempSystemDisk := false
+ children = 1
+ tempDisk := model.Storages{
+ DiskName: d.Model,
+ Path: d.Path,
+ Size: d.Size,
+ }
+
storageArr := []model.Storage{}
temp := service.MyService.Disk().SmartCTL(d.Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
@@ -37,6 +44,24 @@ func GetStorageList(c *gin.Context) {
}
for _, v := range d.Children {
if v.MountPoint != "" {
+ if findSystem == 0 {
+ if v.MountPoint == "/" {
+ tempDisk.DiskName = "System"
+ findSystem = 1
+ tempSystemDisk = true
+ }
+ if len(v.Children) > 0 {
+ for _, c := range v.Children {
+ if c.MountPoint == "/" {
+ tempDisk.DiskName = "System"
+ findSystem = 1
+ tempSystemDisk = true
+ break
+ }
+ }
+ }
+ }
+
stor := model.Storage{}
stor.MountPoint = v.MountPoint
stor.Size = v.FSSize
@@ -53,16 +78,27 @@ func GetStorageList(c *gin.Context) {
storageArr = append(storageArr, stor)
}
}
+
if len(storageArr) > 0 {
- storages = append(storages, model.Storages{
- DiskName: d.Model,
- Path: d.Path,
- Size: d.Size,
- Children: storageArr,
- })
- diskNumber += 1
+ if tempSystemDisk && len(system) > 0 {
+ tempStorageArr := []model.Storage{}
+ for i := 0; i < len(storageArr); i++ {
+ if storageArr[i].MountPoint != "/boot/efi" && storageArr[i].Type != "swap" {
+ tempStorageArr = append(tempStorageArr, storageArr[i])
+ }
+ }
+ tempDisk.Children = tempStorageArr
+ storages = append(storages, tempDisk)
+ diskNumber += 1
+ } else if !tempSystemDisk {
+ tempDisk.Children = storageArr
+ storages = append(storages, tempDisk)
+ diskNumber += 1
+ }
+
}
}
}
+
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: storages})
}
diff --git a/route/v1/system.go b/route/v1/system.go
index 42d7d32..c4e7233 100644
--- a/route/v1/system.go
+++ b/route/v1/system.go
@@ -354,21 +354,13 @@ func GetSystemUtilization(c *gin.Context) {
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)
}
}
diff --git a/service/connections.go b/service/connections.go
index 5136676..f9fe135 100644
--- a/service/connections.go
+++ b/service/connections.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 18:13:22
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-27 13:44:12
+ * @LastEditTime: 2022-08-04 20:10:31
* @FilePath: /CasaOS/service/connections.go
* @Description:
* @Website: https://www.casaos.io
@@ -20,11 +20,12 @@ import (
type ConnectionsService interface {
GetConnectionsList() (connections []model2.ConnectionsDBModel)
- GetConnectionByDirectory(directory string) (connections []model2.ConnectionsDBModel)
+ GetConnectionByHost(host string) (connections []model2.ConnectionsDBModel)
GetConnectionByID(id string) (connections model2.ConnectionsDBModel)
CreateConnection(connection *model2.ConnectionsDBModel)
DeleteConnection(id string)
- MountSmaba(connection *model2.ConnectionsDBModel) string
+ UpdateConnection(connection *model2.ConnectionsDBModel)
+ MountSmaba(username, host, directory, port, mountPoint, password string) string
UnmountSmaba(mountPoint string) string
}
@@ -32,27 +33,30 @@ type connectionsStruct struct {
db *gorm.DB
}
-func (s *connectionsStruct) GetConnectionByDirectory(directory string) (connections []model2.ConnectionsDBModel) {
- s.db.Select("username,host,directory,status,mount_point,id").Where("directory = ?", directory).Find(&connections)
+func (s *connectionsStruct) GetConnectionByHost(host string) (connections []model2.ConnectionsDBModel) {
+ s.db.Select("username,host,status,id").Where("host = ?", host).Find(&connections)
return
}
func (s *connectionsStruct) GetConnectionByID(id string) (connections model2.ConnectionsDBModel) {
- s.db.Select("username,password,host,directory,status,mount_point,id").Where("id = ?", id).First(&connections)
+ s.db.Select("username,password,host,status,id,directories,mount_point,port").Where("id = ?", id).First(&connections)
return
}
func (s *connectionsStruct) GetConnectionsList() (connections []model2.ConnectionsDBModel) {
- s.db.Select("username,host,port,directory,status,mount_point,id").Find(&connections)
+ s.db.Select("username,host,port,status,id,mount_point").Find(&connections)
return
}
func (s *connectionsStruct) CreateConnection(connection *model2.ConnectionsDBModel) {
s.db.Create(connection)
}
+func (s *connectionsStruct) UpdateConnection(connection *model2.ConnectionsDBModel) {
+ s.db.Save(connection)
+}
func (s *connectionsStruct) DeleteConnection(id string) {
s.db.Where("id= ?", id).Delete(&model.ConnectionsDBModel{})
}
-func (s *connectionsStruct) MountSmaba(connection *model2.ConnectionsDBModel) string {
- str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + connection.Username + " " + connection.Host + " " + connection.Directory + " " + connection.Port + " " + connection.MountPoint + " " + connection.Password)
+func (s *connectionsStruct) MountSmaba(username, host, directory, port, mountPoint, password string) string {
+ str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password)
return str
}
func (s *connectionsStruct) UnmountSmaba(mountPoint string) string {
diff --git a/service/disk.go b/service/disk.go
index e832c3b..dfe8219 100644
--- a/service/disk.go
+++ b/service/disk.go
@@ -36,6 +36,7 @@ type DiskService interface {
DeleteMount(id string)
UpdateMountPoint(m model2.SerialDisk)
RemoveLSBLKCache()
+ UmountUSB(path string)
}
type diskService struct {
db *gorm.DB
@@ -45,6 +46,10 @@ func (d *diskService) RemoveLSBLKCache() {
key := "system_lsblk"
Cache.Delete(key)
}
+func (d *diskService) UmountUSB(path string) {
+ r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path)
+ fmt.Println(r)
+}
func (d *diskService) SmartCTL(path string) model.SmartctlA {
key := "system_smart_" + path
@@ -243,9 +248,9 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
}
func (d *diskService) MountDisk(path, volume string) {
- fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
+ //fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
- fmt.Print(r)
+ fmt.Println(r)
}
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
diff --git a/service/docker.go b/service/docker.go
index 4501345..45bc4a8 100644
--- a/service/docker.go
+++ b/service/docker.go
@@ -45,7 +45,7 @@ import (
type DockerService interface {
DockerPullImage(imageName string, icon, name string) error
IsExistImage(imageName string) bool
- DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error)
+ DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
DockerContainerStart(name string) error
DockerContainerStats(name string) (string, error)
@@ -376,7 +376,7 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c
//param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口
//param udp 容器其他udp端口
-func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error) {
+func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
if len(m.NetworkModel) == 0 {
m.NetworkModel = "bridge"
}
@@ -385,6 +385,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
if err != nil {
return "", err
}
+
defer cli.Close()
ports := make(nat.PortSet)
portMaps := make(nat.PortMap)
@@ -523,15 +524,26 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
if len(m.HostName) == 0 {
m.HostName = m.Label
}
- config := &container.Config{
- Image: imageName,
- Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin, "casaos": "casaos"},
- Env: envArr,
- // Healthcheck: health,
- Hostname: m.HostName,
- Cmd: m.Cmd,
+
+ info, err := cli.ContainerInspect(context.Background(), id)
+ hostConfig := &container.HostConfig{}
+ config := &container.Config{}
+ config.Labels = map[string]string{}
+ if err == nil {
+ // info.HostConfig = &container.HostConfig{}
+ // info.Config = &container.Config{}
+ // info.NetworkSettings = &types.NetworkSettings{}
+ hostConfig = info.HostConfig
+ config = info.Config
}
+ config.Cmd = m.Cmd
+ config.Image = m.Image
+ config.Env = envArr
+ config.Hostname = m.HostName
+ config.ExposedPorts = ports
+ config.Labels["origin"] = m.Origin
+ config.Labels["casaos"] = "casaos"
config.Labels["web"] = m.PortMap
config.Labels["icon"] = m.Icon
config.Labels["desc"] = m.Description
@@ -541,12 +553,19 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
config.Labels["protocol"] = m.Protocol
config.Labels["host"] = m.Host
config.Labels["name"] = m.Label
- hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(m.NetworkModel), Privileged: m.Privileged, CapAdd: m.CapAdd}
+ //container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
+
+ hostConfig.Mounts = volumes
+ hostConfig.Privileged = m.Privileged
+ hostConfig.CapAdd = m.CapAdd
+ hostConfig.NetworkMode = container.NetworkMode(m.NetworkModel)
+ hostConfig.RestartPolicy = rp
+ hostConfig.Resources = res
+ //hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: , Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" {
- config.ExposedPorts = ports
+
hostConfig.PortBindings = portMaps
//}
-
containerDb, err := cli.ContainerCreate(context.Background(),
config,
hostConfig,
diff --git a/service/model/o_connections.go b/service/model/o_connections.go
index 9c79df3..45b1244 100644
--- a/service/model/o_connections.go
+++ b/service/model/o_connections.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-07-26 17:17:57
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-27 10:44:46
+ * @LastEditTime: 2022-08-01 17:08:08
* @FilePath: /CasaOS/service/model/o_connections.go
* @Description:
* @Website: https://www.casaos.io
@@ -11,16 +11,16 @@
package model
type ConnectionsDBModel struct {
- ID uint `gorm:"column:id;primary_key" json:"id"`
- Updated int64 `gorm:"autoUpdateTime"`
- Created int64 `gorm:"autoCreateTime"`
- Username string `json:"username"`
- Password string `json:"password"`
- Host string `json:"host"`
- Port string `json:"port"`
- Directory string `json:"directory"`
- MountPoint string `json:"mount_point"`
- Status string `json:"status"`
+ ID uint `gorm:"column:id;primary_key" json:"id"`
+ Updated int64 `gorm:"autoUpdateTime"`
+ Created int64 `gorm:"autoCreateTime"`
+ Username string `json:"username"`
+ Password string `json:"password"`
+ Host string `json:"host"`
+ Port string `json:"port"`
+ Status string `json:"status"`
+ Directories string `json:"directories"` // string array
+ MountPoint string `json:"mount_point"` //parent directory of mount point
}
func (p *ConnectionsDBModel) TableName() string {
diff --git a/shell/helper.sh b/shell/helper.sh
index 3a724ca..2a7545e 100644
--- a/shell/helper.sh
+++ b/shell/helper.sh
@@ -383,5 +383,7 @@ CheckServiceStatus(){
echo "running"
fi
}
-
+UDEVILUmount(){
+ $sudo_cmd udevil umount -f $1
+}
diff --git a/types/system.go b/types/system.go
index 9a3d4e8..92b4c4c 100644
--- a/types/system.go
+++ b/types/system.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-02-17 18:53:22
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-18 18:47:15
+ * @LastEditTime: 2022-08-10 13:50:57
* @FilePath: /CasaOS/types/system.go
* @Description:
* @Website: https://www.casaos.io
@@ -10,6 +10,6 @@
*/
package types
-const CURRENTVERSION = "0.3.4"
+const CURRENTVERSION = "0.3.5"
-const BODY = ""
+const BODY = " "
diff --git a/web/index.html b/web/index.html
index bcede30..bb2b479 100644
--- a/web/index.html
+++ b/web/index.html
@@ -20,7 +20,7 @@
CasaOS
-
+