1
0
mirror of https://github.com/IceWhaleTech/CasaOS.git synced 2025-07-15 23:54:17 +02:00

Merge pull request #48 from IceWhaleTech/dev

feat: Multiple updates
This commit is contained in:
link
2021-12-09 19:03:45 +08:00
committed by GitHub
35 changed files with 780 additions and 281 deletions

2
UI

Submodule UI updated: f7c46d7379...a982eb4bdd

4
go.mod
View File

@ -48,8 +48,8 @@ require (
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.3
github.com/tidwall/gjson v1.8.0
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/gjson v1.10.2
github.com/tidwall/sjson v1.2.3
github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/ugorji/go v1.2.6 // indirect
go.opencensus.io v0.23.0 // indirect

11
go.sum
View File

@ -741,13 +741,14 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=

View File

@ -2,8 +2,9 @@ package middleware
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"github.com/gin-gonic/gin"
)
func Cors() gin.HandlerFunc {
@ -17,7 +18,7 @@ func Cors() gin.HandlerFunc {
//服务器支持的所有跨域请求的方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
//允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session")
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
//设置缓存时间

View File

@ -24,6 +24,7 @@ type LSBLKModel struct {
Tran string `json:"tran"`
MinIO uint64 `json:"min-io"`
UsedPercent float64 `json:"used_percent"`
Serial string `json:"serial"`
Children []LSBLKModel `json:"children"`
//详情特有
StartSector uint64 `json:"start_sector,omitempty"`

8
model/docker.go Normal file
View File

@ -0,0 +1,8 @@
package model
type DockerStatsModel struct {
Icon string `json:"icon"`
Title string `json:"title"`
Data interface{} `json:"data"`
Pre interface{} `json:"pre"`
}

View File

@ -68,3 +68,7 @@ type SystemConfig struct {
SyncPort string `json:"sync_port"`
SyncKey string `json:"sync_key"`
}
type CasaOSGlobalVariables struct {
AddApp bool
}

View File

@ -33,6 +33,8 @@ var ServerInfo = &model.ServerModel{}
var SystemConfigInfo = &model.SystemConfig{}
var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
var Cfg *ini.File
//初始化设置,获取系统的部分信息。

View File

@ -16,6 +16,7 @@ const (
DIR_ALREADY_EXISTS = 20001
FILE_ALREADY_EXISTS = 20002
FILE_OR_DIR_EXISTS = 20003
PORT_IS_OCCUPIED = 20004
//zerotier
GET_TOKEN_ERROR = 30001
@ -49,6 +50,7 @@ var MsgFlags = map[int]string{
DIR_ALREADY_EXISTS: "Directory already exists",
FILE_ALREADY_EXISTS: "File already exists",
FILE_OR_DIR_EXISTS: "File or directory already exists",
PORT_IS_OCCUPIED: "Port is occupied",
//zerotier
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",

View File

@ -10,6 +10,7 @@ import (
"github.com/IceWhaleTech/CasaOS/model/system_app"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
@ -20,6 +21,7 @@ import (
func InitFunction() {
go checkSystemApp()
Update2_3()
}
var syncIsExistence = false
@ -190,3 +192,10 @@ func checkSystemApp() {
installSyncthing("44")
}
}
func CheckSerialDiskMount() {
// 检查挂载点重新挂载
// 检查新硬盘是否有多个分区,如有多个分区需提示
}
func Update2_3() {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
}

View File

@ -141,6 +141,8 @@ func InitRouter() *gin.Engine {
{
//获取我的已安装的列表
v1AppGroup.GET("/mylist", v1.MyAppList)
//
v1AppGroup.GET("/usage", v1.AppUsageList)
//app详情
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
//获取未安装的列表
@ -192,6 +194,9 @@ func InitRouter() *gin.Engine {
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
v1SysGroup.GET("/port", v1.GetCasaOSPort)
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.POST("/kill", v1.PostKillCasaOS)
}
v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use()
@ -221,7 +226,7 @@ func InitRouter() *gin.Engine {
v1DiskGroup.POST("/format", v1.FormatDisk)
//添加分区
v1DiskGroup.POST("/addpart", v1.AddPartition)
v1DiskGroup.POST("/part", v1.AddPartition)
//获取可以格式化的内容
v1DiskGroup.GET("/type", v1.FormatDiskType)
@ -229,6 +234,12 @@ func InitRouter() *gin.Engine {
//删除分区
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
//mount SATA disk
v1DiskGroup.POST("/mount", v1.PostMountDisk)
//umount SATA disk
v1DiskGroup.POST("/umount", v1.DeleteUmountDisk)
}
v1ShareGroup := v1Group.Group("/share")
v1ShareGroup.Use()

View File

@ -103,6 +103,18 @@ func MyAppList(c *gin.Context) {
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}
// @Summary my app hardware usage list
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/usage [get]
func AppUsageList(c *gin.Context) {
list := service.MyService.App().GetHardwareUsage()
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}
// @Summary 应用详情
// @Produce application/json
// @Accept application/json
@ -212,3 +224,14 @@ func ShareAppFile(c *gin.Context) {
content := service.MyService.OAPI().ShareAppFile(str)
c.JSON(http.StatusOK, json.RawMessage(content))
}
// @Summary Resource Usage
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/share [post]
func AppListResourceUsage() {
}

View File

@ -1,13 +1,13 @@
package v1
import (
"net/http"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v3/disk"
"net/http"
"strconv"
)
// @Summary 获取磁盘列表
@ -59,7 +59,7 @@ func GetPlugInDisk(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst})
}
// @Summary 获取磁盘列表
// @Summary get disk list
// @Produce application/json
// @Accept application/json
// @Tags disk
@ -76,12 +76,12 @@ func GetPlugInDisks(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result})
}
// @Summary 磁盘详情
// @Summary disk detail
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Param path query string true "要获取的磁盘详情 例如/dev/sda"
// @Param path query string true "for example /dev/sda"
// @Success 200 {string} string "ok"
// @Router /disk/info [get]
func GetDiskInfo(c *gin.Context) {
@ -93,7 +93,7 @@ func GetDiskInfo(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
}
// @Summary 磁盘详情
// @Summary format disk
// @Produce application/json
// @Accept multipart/form-data
// @Tags disk
@ -109,15 +109,9 @@ func FormatDisk(c *gin.Context) {
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)})
}
//删除挂载点
service.MyService.Disk().UmountPointAndRemoveDir(path)
//格式化磁盘
service.MyService.Disk().FormatDisk(path, t)
//重新挂载
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
@ -154,25 +148,43 @@ func RemovePartition(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
// @Summary 添加分区
// @Summary serial number
// @Produce application/json
// @Accept multipart/form-data
// @Tags disk
// @Security ApiKeyAuth
// @Param path formData string true "磁盘路径 例如/dev/sda"
// @Param size formData string true "需要分区容量大小(MB)"
// @Param num formData string true "磁盘符号"
// @Param serial formData string true "serial"
// @Success 200 {string} string "ok"
// @Router /disk/addpart [post]
func AddPartition(c *gin.Context) {
path := c.PostForm("path")
size, _ := strconv.Atoi(c.DefaultPostForm("size", "0"))
num := c.DefaultPostForm("num", "9")
if len(path) == 0 {
serial := c.PostForm("serial")
if len(path) == 0 || len(serial) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
//size*1024*1024/512
service.MyService.Disk().AddPartition(path, num, uint64(size*1024*2))
service.MyService.Disk().AddPartition(path)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
func PostMountDisk(c *gin.Context) {
// for example: path=/dev/sda1
path := c.PostForm("path")
//执行挂载目录
service.MyService.Disk().MountDisk(path, "volume")
//添加到数据库
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
func DeleteUmountDisk(c *gin.Context) {
// for example: path=/dev/sda1
path := c.PostForm("path")
service.MyService.Disk().UmountPointAndRemoveDir(path)
//删除数据库记录
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}

View File

@ -2,7 +2,6 @@ package v1
import (
"bytes"
"encoding/json"
json2 "encoding/json"
"net/http"
"reflect"
@ -11,6 +10,7 @@ import (
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@ -421,9 +421,12 @@ func InstallApp(c *gin.Context) {
rely := model.MapStrings{}
copier.Copy(&rely, &relyMap)
if m.Origin != "custom" {
for i := 0; i < len(m.Volumes); i++ {
m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].ContainerPath)
}
}
portsStr, _ := json2.Marshal(m.Ports)
envsStr, _ := json2.Marshal(m.Envs)
volumesStr, _ := json2.Marshal(m.Volumes)
@ -463,6 +466,7 @@ func InstallApp(c *gin.Context) {
// m.PortMap = m.Port
//}
service.MyService.App().SaveContainer(md)
config.CasaOSGlobalVariables.AddApp = true
}()
@ -677,7 +681,7 @@ func UnInstallApp(c *gin.Context) {
}
//step:删除容器
err = service.MyService.Docker().DockerContainerRemove(appId)
err = service.MyService.Docker().DockerContainerRemove(appId, false)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
return
@ -908,16 +912,10 @@ func UpdateSetting(c *gin.Context) {
//如果容器端口均未修改,这不进行处理
portsStr, _ := json2.Marshal(m.Ports)
list := []model.PathMap{}
json.Unmarshal([]byte(appInfo.Volumes), &list)
for i := 0; i < len(list); i++ {
list[i].Path = docker.GetDir(id, list[i].ContainerPath)
}
envsStr, _ := json2.Marshal(m.Envs)
volumesStr, _ := json2.Marshal(m.Volumes)
devicesStr, _ := json2.Marshal(m.Devices)
listStr, _ := json2.Marshal(list)
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(volumesStr, listStr) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel {
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel {
var newUUid = uuid.NewV4().String()
var err error
@ -934,7 +932,7 @@ func UpdateSetting(c *gin.Context) {
return
}
err = service.MyService.Docker().DockerContainerRemove(id)
err = service.MyService.Docker().DockerContainerRemove(id, true)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return

View File

@ -4,12 +4,14 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
@ -80,7 +82,7 @@ func GetCasaOSErrorLogs(c *gin.Context) {
// @Produce application/json
// @Accept multipart/form-data
// @Tags sys
// @Param file formData file true "用户头像"
// @Param config formData string true "config json string"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/changhead [post]
@ -135,6 +137,58 @@ func PostSetWidgetConfig(c *gin.Context) {
})
}
// @Summary get casaos server port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/port [get]
func GetCasaOSPort(c *gin.Context) {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: config.ServerInfo.HttpPort,
})
}
// @Summary edit casaos server port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Param port formData string true "port"
// @Success 200 {string} string "ok"
// @Router /sys/port [put]
func PutCasaOSPort(c *gin.Context) {
port, err := strconv.Atoi(c.PostForm("port"))
if err != nil {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.ERROR,
Message: err.Error(),
})
return
}
isAvailable := port2.IsPortAvailable(port, "tcp")
if !isAvailable {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.PORT_IS_OCCUPIED,
Message: oasis_err.GetMsg(oasis_err.PORT_IS_OCCUPIED),
})
return
}
service.MyService.System().UpSystemPort(strconv.Itoa(port))
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
})
}
// @Summary 检查是否进入引导状态
// @Produce application/json
// @Accept application/json
@ -156,3 +210,14 @@ func GetGuideCheck(c *gin.Context) {
Data: data,
})
}
// @Summary active killing casaos
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/kill [post]
func PostKillCasaOS(c *gin.Context) {
os.Exit(0)
}

View File

@ -2,9 +2,15 @@ package service
import (
"context"
"encoding/json"
"io"
"io/ioutil"
"runtime"
"strings"
"sync"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
@ -27,6 +33,9 @@ type AppService interface {
GetSimpleContainerInfo(name string) (types.Container, error)
DelAppConfigDir(path string)
GetSystemAppList() *[]model2.MyAppList
GetHardwareUsageSteam()
GetHardwareUsage() []model.DockerStatsModel
GetAppStats(id string) string
}
type appStruct struct {
@ -48,7 +57,6 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
}
//获取本地数据库应用
var lm []model2.AppListDBModel
@ -154,7 +162,6 @@ func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
//Rely: m.Rely,
})
}
}
return &list
@ -233,6 +240,110 @@ func (a *appStruct) RemoveContainerById(id string) {
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
}
var dataStr map[string]model.DockerStatsModel
var isFinish bool = false
func (a *appStruct) GetAppStats(id string) string {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return ""
}
defer cli.Close()
con, err := cli.ContainerStats(context.Background(), id, false)
if err != nil {
return err.Error()
}
defer con.Body.Close()
c, _ := ioutil.ReadAll(con.Body)
return string(c)
}
func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
steam := true
for !isFinish {
if steam {
steam = false
go func() {
a.GetHardwareUsageSteam()
}()
}
// 切一下,再次分配任务
runtime.Gosched()
}
list := []model.DockerStatsModel{}
for _, v := range dataStr {
list = append(list, v)
}
return list
}
func (a *appStruct) GetHardwareUsageSteam() {
var lock = &sync.Mutex{}
if len(dataStr) == 0 {
lock.Lock()
dataStr = make(map[string]model.DockerStatsModel)
lock.Unlock()
}
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return
}
defer cli.Close()
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var lm []model2.AppListDBModel
a.db.Table(model2.CONTAINERTABLENAME).Select("label,icon,container_id").Where("origin != ?", "system").Find(&lm)
var list []types.ContainerStats
for i := 0; i < 100; i++ {
if config.CasaOSGlobalVariables.AddApp {
a.db.Table(model2.CONTAINERTABLENAME).Select("label,icon,container_id").Where("origin != ?", "system").Find(&lm)
}
var wg sync.WaitGroup
for _, v := range lm {
wg.Add(1)
go func(v model2.AppListDBModel, lock *sync.Mutex) {
defer wg.Done()
stats, err := cli.ContainerStats(ctx, v.ContainerId, true)
if err != nil {
return
}
decode := json.NewDecoder(stats.Body)
var data interface{}
if err := decode.Decode(&data); err == io.EOF {
return
}
lock.Lock()
dockerStats := model.DockerStatsModel{}
dockerStats.Pre = dataStr[v.ContainerId].Data
dockerStats.Data = data
dockerStats.Icon = v.Icon
dockerStats.Title = v.Label
dataStr[v.ContainerId] = dockerStats
lock.Unlock()
}(v, lock)
}
wg.Wait()
isFinish = true
if i == 99 {
for _, v := range list {
v.Body.Close()
}
}
time.Sleep(time.Second * 2)
}
isFinish = false
cancel()
}
// init install
func Init() {

View File

@ -10,8 +10,10 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/shirou/gopsutil/v3/disk"
"github.com/tidwall/gjson"
"gorm.io/gorm"
)
type DiskService interface {
@ -21,11 +23,14 @@ type DiskService interface {
UmountPointAndRemoveDir(path string) string
GetDiskInfo(path string) model.LSBLKModel
DelPartition(path, num string) string
AddPartition(path, num string, size uint64) string
AddPartition(path string) string
GetDiskInfoByPath(path string) *disk.UsageStat
MountDisk(path, volume string)
SerialAll(mountPoint string) *[]model2.SerialDisk
}
type diskService struct {
log loger2.OLog
db *gorm.DB
}
//通过脚本获取外挂磁盘
@ -55,28 +60,17 @@ func (d *diskService) DelPartition(path, num string) string {
return ""
}
//添加分区
func (d *diskService) AddPartition(path, num string, size uint64) string {
var maxSector uint64 = 0
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + path)
if len(chiList) == 0 {
d.log.Error("chiList length error")
}
for i := 0; i < len(chiList); i++ {
tempArr := strings.Split(chiList[i], ",")
tempSector, _ := strconv.ParseUint(tempArr[2], 10, 64)
if tempSector > maxSector {
maxSector = tempSector
}
}
r := command2.ExecResultStrArray("source ./shell/helper.sh ;AddPartition " + path + " " + num + " " + strconv.FormatUint(maxSector+1, 10) + " " + strconv.FormatUint(size+maxSector+1, 10))
//part
func (d *diskService) AddPartition(path string) string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
fmt.Println(r)
return ""
}
func (d *diskService) AddAllPartition(path string) {
}
//获取硬盘详情
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
diskInfo, err := disk.Usage(path + "1")
@ -90,7 +84,7 @@ func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
return diskInfo
}
//获取磁盘信息
//get disk details
func (d *diskService) LSBLK() []model.LSBLKModel {
str := command2.ExecLSBLK()
if str == nil {
@ -111,7 +105,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
var health = true
for _, i := range m {
if i.Children != nil {
if i.Type != "loop" && !i.RO {
fsused = 0
for _, child := range i.Children {
if child.RM {
@ -134,7 +128,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
i.Children = c
if fsused > 0 {
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
fmt.Println(err)
d.log.Fatal("diskservice_lsblk_fsused", err)
}
n = append(n, i)
health = true
@ -197,17 +191,21 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
return m
}
//func GetDiskInfo(path string) *disk.UsageStat {
// diskInfo, _ := disk.Usage(path)
// diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
// diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
// return diskInfo
//}
//func (d *diskService) GetPlugInDisk() []string {
// return disk.Partitions(false)
//}
func NewDiskService(log loger2.OLog) DiskService {
return &diskService{log: log}
func (d *diskService) MountDisk(path, volume string) {
r := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_mount " + path + " " + volume)
fmt.Print(r)
}
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
d.db.Save(&m)
}
func (d *diskService) SerialAll(mountPoint string) *[]model2.SerialDisk {
var m []model2.SerialDisk
d.db.Find(&m)
return &m
}
func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService {
return &diskService{log: log, db: db}
}

View File

@ -53,7 +53,7 @@ type DockerService interface {
DockerListByImage(image, version string) (*types.Container, error)
DockerContainerInfo(name string) (*types.ContainerJSON, error)
DockerImageRemove(name string) error
DockerContainerRemove(name string) error
DockerContainerRemove(name string, update bool) error
DockerContainerStop(id string) error
DockerContainerUpdateName(name, id string) (err error)
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
@ -352,7 +352,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
//param udp 容器其他udp端口
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
if len(net) == 0 {
net = "oasis"
net = "bridge"
}
cli, err := client2.NewClientWithOpts(client2.FromEnv)
@ -515,7 +515,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
}
//删除容器
func (ds *dockerService) DockerContainerRemove(name string) error {
func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return err
@ -524,10 +524,12 @@ func (ds *dockerService) DockerContainerRemove(name string) error {
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
//路径处理
if !update {
path := docker.GetDir(name, "/config")
if !file.CheckNotExist(path) {
file.RMDir(path)
}
}
if err != nil {
return err

View File

@ -26,10 +26,6 @@ type AppListDBModel struct {
PortMap string `json:"port_map"`
Label string `json:"label"`
EnableUPNP bool `json:"enable_upnp"`
//Envs model.EnvArrey `json:"envs" bson:"envs"`
//Ports model.PortArrey `json:"ports" bson:"ports"`
//Volumes model.PathArrey `json:"volumes" bson:"volumes"`
//Devices model.PathArrey `json:"devices" bson:"devices"`
Envs string `json:"envs"`
Ports string `json:"ports"`
Volumes string `json:"volumes"`

14
service/model/o_disk.go Normal file
View File

@ -0,0 +1,14 @@
package model
//SerialAdvanced Technology Attachment (STAT)
type SerialDisk struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
DiskId string `json:"disk_id"`
Path string `json:"path"`
State int `json:"state"`
MountPoint string `json:"mount_point"`
}
func (p *SerialDisk) TableName() string {
return "o_disk"
}

View File

@ -40,7 +40,7 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
zerotier: NewZeroTierService(),
zima: NewZiMaService(),
oapi: NewOasisService(),
disk: NewDiskService(log),
disk: NewDiskService(log, db),
notify: NewNotifyService(db),
shareDirectory: NewShareDirService(db, log),
task: NewTaskService(db, log),

View File

@ -14,6 +14,8 @@ type SystemService interface {
UpdateSystemVersion(version string)
GetSystemConfigDebug() []string
GetCasaOSLogs(lineNumber int) string
UpdateAssist()
UpSystemPort(port string)
}
type systemService struct {
log loger.OLog
@ -25,6 +27,9 @@ func (s *systemService) UpdateSystemVersion(version string) {
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version))
//s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
}
func (s *systemService) UpdateAssist() {
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/assist.sh"))
}
func (s *systemService) GetSystemConfigDebug() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
}
@ -39,6 +44,13 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
}
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
func (s *systemService) UpSystemPort(port string) {
if len(port) > 0 && port != config.ServerInfo.HttpPort {
config.Cfg.Section("server").Key("HttpPort").SetValue(port)
config.ServerInfo.HttpPort = port
}
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
file, err := os.Open(s.log.Path())
if err != nil {

View File

@ -116,7 +116,6 @@ func (c *zima) GetNetState(name string) string {
//网络信息
func (c *zima) GetNetInfo() []net.IOCountersStat {
//loger.Error("输出个内容试试")
parts, _ := net.IOCounters(true)
//fmt.Println(net.ConntrackStatsWithContext(true))
return parts

12
shell/assist.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/bash
#add in v0.2.3
version_0_2_3() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
}
version_0_2_3

View File

@ -103,20 +103,22 @@ DelPartition() {
EOF
}
#添加分区
#添加分区只有一个分区
#param 路径 /dev/sdb
#param 磁盘号 最大128
#param 磁盘大小 字节 512*2048=1024kb=1M
#param 要挂载的目录
AddPartition() {
# fdisk $1 <<EOF
# n
# $2
# $3
# $4
# wq
#EOF
parted $1 mkpart primary ext4 s3 s4
DelPartition $1
parted -s $1 mklabel gpt
parted -s $1 mkpart primary ext4 0 100%
mkfs.ext4 $11
partprobe $1
# mount $11 $2
}
#磁盘类型
@ -151,7 +153,83 @@ GetPartitionSectors() {
fdisk $1 -l | grep "/dev/sda[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
}
#检查没有使用的挂载点删除文件夹
AutoRemoveUnuseDir() {
DIRECTORY="/mnt/"
dir=$(ls -l $DIRECTORY | awk '/^d/ {print $NF}')
for i in $dir; do
path="$DIRECTORY$i"
mountStr=$(mountpoint $path)
notMountpoint="is not a mountpoint"
if [[ $mountStr =~ $notMountpoint ]]; then
if [ "$(ls -A $path)" = "" ]; then
rm -fr $path
else
echo "$path is not empty"
fi
fi
done
}
#重载samba服务
ReloadSamba() {
/etc/init.d/smbd reload
}
# $1=sda1
# $2=volume{1}
do_mount() {
DEVBASE=$1
DEVICE="${DEVBASE}"
# See if this drive is already mounted, and if so where
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
if [ -n "${MOUNT_POINT}" ]; then
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
exit 1
fi
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
LABEL=$2
if grep -q " /media/${LABEL} " /etc/mtab; then
# Already in use, make a unique one
LABEL+="-${DEVBASE}"
fi
DEV_LABEL="${LABEL}"
# Use the device name in case the drive doesn't have label
if [ -z ${DEV_LABEL} ]; then
DEV_LABEL="${DEVBASE}"
fi
MOUNT_POINT="/media/${DEV_LABEL}"
${log} "Mount point: ${MOUNT_POINT}"
mkdir -p ${MOUNT_POINT}
case ${ID_FS_TYPE} in
vfat)
mount -t vfat -o rw,relatime,users,gid=100,umask=000,shortname=mixed,utf8=1,flush ${DEVICE} ${MOUNT_POINT}
;;
ext[2-4])
mount -o noatime ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
;;
exfat)
mount -t exfat ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
;;
ntfs)
ntfs-3g ${DEVICE} ${MOUNT_POINT}
;;
iso9660)
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
;;
*)
/bin/rmdir "${MOUNT_POINT}"
exit 0
;;
esac
}

View File

@ -60,7 +60,7 @@ show() {
}
run_external_script() {
show 0 "run_external_script"
assist.sh
}
update() {
@ -99,13 +99,13 @@ update() {
target_arch="386"
;;
*armv5*)
target_arch="armv5"
target_arch="arm-5"
;;
*armv6*)
target_arch="armv6"
target_arch="arm-6"
;;
*armv7*)
target_arch="armv7"
target_arch="arm-7"
;;
*)
show 1 "Aborted, unsupported or unknown architecture: $unamem"

View File

@ -1,12 +1,10 @@
#!/bin/sh
# copy to /oasis/util/shell path
# copy to /casaOS/util/shell path
# chmod 755
log="logger -t usb-mount.sh -s "
${log} "变量:$1 $2"
ACTION=$1
DEVBASE=$2
@ -18,10 +16,10 @@ MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
do_mount() {
if [[ -n ${MOUNT_POINT} ]]; then
if [ -n "${MOUNT_POINT}" ]; then
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
exit 1
fib
fi
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
@ -33,7 +31,7 @@ do_mount() {
# Figure out a mount point to use
# LABEL=${ID_FS_LABEL}
LABEL=${DEVBASE}
if grep -q " /media/${LABEL} " /etc/mtab; then
if grep -q " /mnt/casa_${LABEL} " /etc/mtab; then
# Already in use, make a unique one
LABEL+="-${DEVBASE}"
fi
@ -44,7 +42,7 @@ do_mount() {
DEV_LABEL="${DEVBASE}"
fi
MOUNT_POINT="/media/${DEV_LABEL}"
MOUNT_POINT="/mnt/casa_${DEV_LABEL}"
${log} "Mount point: ${MOUNT_POINT}"

View File

@ -4,5 +4,5 @@ Description=Mount USB Drive on %i
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/oasis/util/shell/usb-mount.sh add %i
ExecStop=/oasis/util/shell/usb-mount.sh remove %i
ExecStart=/casaOS/server/shell/usb-mount.sh add %i
ExecStop=/casaOS/server/shell/usb-mount.sh remove %i

View File

@ -1,4 +1,4 @@
package types
const CURRENTVERSION = "0.2.2"
const BODY = "<li>ui adjustment</li><li>fixed bugs</li>"
const CURRENTVERSION = "0.2.3"
const BODY = "<li>Add detailed CPU and memory statistics.</li><li>Add the multi-language function and add Chinese translation.</li><li>Add the function to modify the search engine.</li><li>Add the function of modifying the WebUI port</li><li>fixed some bugs</li><li>Preprocessing usb automounting</li><li>Update update script</li>"

View File

@ -0,0 +1,11 @@
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.32" x="0.435625" y="0.435625" width="71.1288" height="71.1288" rx="7.56437" fill="white" stroke="url(#paint0_linear_812_2050)" stroke-width="0.87125"/>
<path d="M36.0606 22L36.0239 50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 36H50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_812_2050" x1="77.6757" y1="64.5405" x2="35.9839" y2="53.5747" gradientUnits="userSpaceOnUse">
<stop stop-color="#CBEFFF" stop-opacity="0.16"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 752 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long