From 9f2e8dae6f069330d9b63025e8587963024583d2 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Thu, 8 Sep 2022 10:55:20 +0100 Subject: [PATCH 01/42] add send notify function --- .../migration/service.d/casaos/migration.list | 1 + cmd/migration-tool/log.go | 10 --- cmd/migration-tool/main.go | 1 + cmd/migration-tool/migration-034-035.go | 10 +-- cmd/migration-tool/migration-036.go | 74 +++++++++++++++++++ common/notify.go | 67 +++++++++++++++++ main.go | 14 +++- route/route.go | 9 ++- route/v1/docker.go | 4 +- route/v1/notiry.go | 16 ++++ service/notify.go | 16 ++++ 11 files changed, 203 insertions(+), 19 deletions(-) create mode 100644 cmd/migration-tool/migration-036.go create mode 100644 common/notify.go create mode 100644 route/v1/notiry.go diff --git a/build/scripts/migration/service.d/casaos/migration.list b/build/scripts/migration/service.d/casaos/migration.list index 2035e42..d3ce03f 100644 --- a/build/scripts/migration/service.d/casaos/migration.list +++ b/build/scripts/migration/service.d/casaos/migration.list @@ -1,3 +1,4 @@ LEGACY_WITHOUT_VERSION v0.3.6 v0.3.5 v0.3.6 v0.3.5.1 v0.3.6 +v0.3.6 v0.3.7 diff --git a/cmd/migration-tool/log.go b/cmd/migration-tool/log.go index e20da69..ed69983 100644 --- a/cmd/migration-tool/log.go +++ b/cmd/migration-tool/log.go @@ -1,13 +1,3 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2022-08-30 22:15:30 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-30 22:15:47 - * @FilePath: /CasaOS/cmd/migration-tool/log.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ package main import ( diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go index a09d5b8..5f7c60b 100644 --- a/cmd/migration-tool/main.go +++ b/cmd/migration-tool/main.go @@ -80,6 +80,7 @@ func main() { migrationTools := []interfaces.MigrationTool{ NewMigrationToolFor_035(), + NewMigrationToolFor_036(), } var selectedMigrationTool interfaces.MigrationTool diff --git a/cmd/migration-tool/migration-034-035.go b/cmd/migration-tool/migration-034-035.go index 4fa2ed3..3dfed60 100644 --- a/cmd/migration-tool/migration-034-035.go +++ b/cmd/migration-tool/migration-034-035.go @@ -25,9 +25,9 @@ import ( "github.com/IceWhaleTech/CasaOS/service" ) -type migrationTool struct{} +type migrationTool036 struct{} -func (u *migrationTool) IsMigrationNeeded() (bool, error) { +func (u *migrationTool036) IsMigrationNeeded() (bool, error) { majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() if err != nil { @@ -55,12 +55,12 @@ func (u *migrationTool) IsMigrationNeeded() (bool, error) { } -func (u *migrationTool) PreMigrate() error { +func (u *migrationTool036) PreMigrate() error { return nil } -func (u *migrationTool) Migrate() error { +func (u *migrationTool036) Migrate() error { if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { service.MyService.System().UpdateUSBAutoMount("False") @@ -173,7 +173,7 @@ func (u *migrationTool) Migrate() error { return nil } -func (u *migrationTool) PostMigrate() error { +func (u *migrationTool036) PostMigrate() error { return nil } diff --git a/cmd/migration-tool/migration-036.go b/cmd/migration-tool/migration-036.go new file mode 100644 index 0000000..b6d5410 --- /dev/null +++ b/cmd/migration-tool/migration-036.go @@ -0,0 +1,74 @@ +/* + * @Author: LinkLeong link@icewhale.org + * @Date: 2022-08-24 17:36:00 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-09-05 11:24:27 + * @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package main + +import ( + "strings" + + interfaces "github.com/IceWhaleTech/CasaOS-Common" + "github.com/IceWhaleTech/CasaOS-Common/utils/version" + "github.com/IceWhaleTech/CasaOS/pkg/config" + "github.com/IceWhaleTech/CasaOS/service" +) + +type migrationTool struct{} + +func (u *migrationTool) IsMigrationNeeded() (bool, error) { + + majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() + if err != nil { + if err == version.ErrLegacyVersionNotFound { + return false, nil + } + + return false, err + } + + if majorVersion > 0 { + return false, nil + } + + if minorVersion > 3 { + return false, nil + } + + if minorVersion == 3 && patchVersion > 5 { + return false, nil + } + + _logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...") + return true, nil + +} + +func (u *migrationTool) PreMigrate() error { + + return nil +} + +func (u *migrationTool) Migrate() error { + + if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { + service.MyService.System().UpdateUSBAutoMount("False") + service.MyService.System().ExecUSBAutoMountShell("False") + } + + _logger.Info("update done") + return nil +} + +func (u *migrationTool) PostMigrate() error { + return nil +} + +func NewMigrationToolFor_036() interfaces.MigrationTool { + return &migrationTool{} +} diff --git a/common/notify.go b/common/notify.go new file mode 100644 index 0000000..4a003d0 --- /dev/null +++ b/common/notify.go @@ -0,0 +1,67 @@ +package common + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "path/filepath" + "strings" +) + +const ( + CasaOSURLFilename = "casaos.url" + APICasaOSNotify = "/v1/notiry" +) + +type NotifyService interface { + SendNotify(path string, message map[string]interface{}) error +} +type notifyService struct { + address string +} + +func (n *notifyService) SendNotify(path string, message map[string]interface{}) error { + + url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify + "/" + path + body, err := json.Marshal(message) + if err != nil { + return err + } + response, err := http.Post(url, "application/json", bytes.NewBuffer(body)) + if err != nil { + return err + } + + if response.StatusCode != http.StatusCreated { + return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") + } + return nil + +} + +func NewNotifyService(runtimePath string) (NotifyService, error) { + casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename) + + buf, err := os.ReadFile(casaosAddressFile) + if err != nil { + return nil, err + } + + address := string(buf) + + response, err := http.Get(address + "/ping") + if err != nil { + return nil, err + } + + if response.StatusCode != 200 { + return nil, errors.New("failed to ping casaos service") + } + + return ¬ifyService{ + address: address, + }, nil +} diff --git a/main.go b/main.go index b616e52..6ff7af8 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "net/http" + "path/filepath" "time" "github.com/IceWhaleTech/CasaOS-Gateway/common" @@ -12,10 +13,12 @@ import ( "github.com/IceWhaleTech/CasaOS/pkg/cache" "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/sqlite" + "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/types" + "go.uber.org/zap" "github.com/robfig/cron" "gorm.io/gorm" @@ -107,7 +110,7 @@ func main() { if err != nil { panic(err) } - routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba"} + routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba", "notify"} for _, v := range routers { err = service.MyService.Gateway().CreateRoute(&common.Route{ Path: "/v1/" + v, @@ -141,6 +144,15 @@ func main() { // MaxHeaderBytes: 1 << 20, // } // s.ListenAndServe() + urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url") + err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()) + if err != nil { + loger.Error("Management service is listening...", + zap.Any("address", listener.Addr().String()), + zap.Any("filepath", urlFilePath), + ) + } + err = http.Serve(listener, r) if err != nil { panic(err) diff --git a/route/route.go b/route/route.go index 2ce2dc3..39d011b 100644 --- a/route/route.go +++ b/route/route.go @@ -40,7 +40,9 @@ func InitRouter() *gin.Engine { r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion) - + r.GET("/ping", func(ctx *gin.Context) { + ctx.String(200, "pong") + }) v1Group := r.Group("/v1") v1Group.Use(jwt2.JWT()) @@ -238,6 +240,11 @@ func InitRouter() *gin.Engine { v1SharesGroup.GET("/status", v1.GetSambaStatus) } } + v1NotifyGroup := v1Group.Group("/notify") + v1NotifyGroup.Use() + { + v1NotifyGroup.POST("/:path", v1.PostNotifyMssage) + } } return r } diff --git a/route/v1/docker.go b/route/v1/docker.go index 6eb5344..684ca75 100644 --- a/route/v1/docker.go +++ b/route/v1/docker.go @@ -38,7 +38,7 @@ var upgrader = websocket.Upgrader{ HandshakeTimeout: time.Duration(time.Second * 5), } -//打开docker的terminal +// 打开docker的terminal func DockerTerminal(c *gin.Context) { col := c.DefaultQuery("cols", "100") row := c.DefaultQuery("rows", "30") @@ -877,7 +877,7 @@ func UpdateSetting(c *gin.Context) { if err != nil { service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id) service.MyService.Docker().DockerContainerStart(id) - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)}) + 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 } // echo -e "hellow\nworld" >> diff --git a/route/v1/notiry.go b/route/v1/notiry.go new file mode 100644 index 0000000..c818aab --- /dev/null +++ b/route/v1/notiry.go @@ -0,0 +1,16 @@ +package v1 + +import ( + "github.com/IceWhaleTech/CasaOS/model" + "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" + "github.com/IceWhaleTech/CasaOS/service" + "github.com/gin-gonic/gin" +) + +func PostNotifyMssage(c *gin.Context) { + path := c.Param("path") + message := make(map[string]interface{}) + c.ShouldBind(&message) + service.MyService.Notify().SendNotify(path, message) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} diff --git a/service/notify.go b/service/notify.go index 3981e55..154d45a 100644 --- a/service/notify.go +++ b/service/notify.go @@ -37,12 +37,28 @@ type NotifyServer interface { SendInstallAppBySocket(app notify.Application) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) SendStorageBySocket(message notify.StorageMessage) + SendNotify(path string, message map[string]interface{}) } type notifyServer struct { db *gorm.DB } +func (i *notifyServer) SendNotify(path string, message map[string]interface{}) { + + msg := gosf.Message{} + msg.Body = message + msg.Success = true + msg.Text = path + + notify := notify.Message{} + notify.Path = path + notify.Msg = msg + + NotifyMsg <- notify + +} + func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) { body := make(map[string]interface{}) body["data"] = message From 4ccae3f67f91843ee812e875cff3b4327c688e32 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Fri, 9 Sep 2022 04:12:34 +0100 Subject: [PATCH 02/42] add shell script --- .../sysroot/usr/share/casaos/shell/helper.sh | 388 ++++++++++++++++++ .../sysroot/usr/share/casaos/shell/update.sh | 12 + .../usr/share/casaos/shell/usb-mount.sh | 136 ++++++ 3 files changed, 536 insertions(+) create mode 100644 build/sysroot/usr/share/casaos/shell/helper.sh create mode 100644 build/sysroot/usr/share/casaos/shell/update.sh create mode 100644 build/sysroot/usr/share/casaos/shell/usb-mount.sh diff --git a/build/sysroot/usr/share/casaos/shell/helper.sh b/build/sysroot/usr/share/casaos/shell/helper.sh new file mode 100644 index 0000000..cfb001d --- /dev/null +++ b/build/sysroot/usr/share/casaos/shell/helper.sh @@ -0,0 +1,388 @@ +#!/bin/bash + +# 获取系统信息 +GetSysInfo() { + if [ -s "/etc/redhat-release" ]; then + SYS_VERSION=$(cat /etc/redhat-release) + elif [ -s "/etc/issue" ]; then + SYS_VERSION=$(cat /etc/issue) + fi + SYS_INFO=$(uname -a) + SYS_BIT=$(getconf LONG_BIT) + MEM_TOTAL=$(free -m | grep Mem | awk '{print $2}') + CPU_INFO=$(getconf _NPROCESSORS_ONLN) + + echo -e ${SYS_VERSION} + echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO} + echo -e ${SYS_INFO} +} + +#获取网卡信息 +GetNetCard() { + if [ "$1" == "1" ]; then + if [ -d "/sys/devices/virtual/net" ]; then + ls /sys/devices/virtual/net + fi + else + if [ -d "/sys/devices/virtual/net" ] && [ -d "/sys/class/net" ]; then + ls /sys/class/net/ | grep -v "$(ls /sys/devices/virtual/net/)" + fi + fi +} + + +GetTimeZone(){ + timedatectl | grep "Time zone" | awk '{printf $3}' +} + +#查看网卡状态 +#param 网卡名称 +CatNetCardState() { + if [ -e "/sys/class/net/$1/operstate" ]; then + cat /sys/class/net/$1/operstate + fi +} + +#获取docker根目录 +GetDockerRootDir() { + if hash docker 2>/dev/null; then + docker info | grep 'Docker Root Dir' | awk -F ':' '{print $2}' + else + echo "" + fi +} + +#删除安装应用文件夹 +#param 需要删除的文件夹路径 +DelAppConfigDir() { + if [ -d $1 ]; then + rm -fr $1 + fi +} + +#zerotier本机已加入的网络 +#result start,end,sectors +GetLocalJoinNetworks() { + zerotier-cli listnetworks -j +} + +#移除挂载点,删除已挂在的文件夹 +UMountPorintAndRemoveDir() { + DEVICE=$1 + MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }') + if [[ -z ${MOUNT_POINT} ]]; then + ${log} "Warning: ${DEVICE} is not mounted" + else + umount -lf ${DEVICE} + /bin/rmdir "${MOUNT_POINT}" + fi +} + +#格式化fat32磁盘 +#param 需要格式化的目录 /dev/sda1 +#param 格式 +FormatDisk() { + if [ "$2" == "fat32" ]; then + mkfs.vfat -F 32 $1 + elif [ "$2" == "ntfs" ]; then + mkfs.ntfs $1 + elif [ "$2" == "ext4" ]; then + mkfs.ext4 -m 1 -F $1 + elif [ "$2" == "exfat" ]; then + mkfs.exfat $1 + else + mkfs.ext4 -m 1 -F $1 + fi +} + +#删除分区 +#param 路径 /dev/sdb +#param 删除分区的区号 +DelPartition() { + fdisk $1 </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 +} + +# $1=sda1 +do_umount() { + log="logger -t usb-mount.sh -s " + DEVBASE=$1 + DEVICE="${DEVBASE}" + MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }') + + if [[ -z ${MOUNT_POINT} ]]; then + ${log} "Warning: ${DEVICE} is not mounted" + else + /bin/kill -9 $(lsof ${MOUNT_POINT}) + umount -l ${DEVICE} + ${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}" + if [ "`ls -A ${MOUNT_POINT}`" = "" ]; then + /bin/rm -fr "${MOUNT_POINT}" + fi + + sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track + fi + +} +# $1=/mnt/volume1/data.img +# $2=100G +PackageDocker() { + image=$1 + docker="/mnt/casa_docker" + #判断目录docker存在不存在则创建,存在检查是否为空 + + if [ ! -d "$docker" ]; then + mkdir ${docker} + fi + + if [ "$(ls -A $docker)" = "" ]; then + echo "$docker count is 0" + else + mkdir ${docker}_bak + mv -r ${docker} ${docker}_bak + fi + + daemon="/etc/docker/daemon.json" + #1创建img文件在挂载的目录 + fallocate -l $2 $image + #2初始化img文件 + mkfs -t ext4 $image + #3挂载img文件 + sudo mount -o loop $image $docker + #4给移动/var/lib/docker数据到img挂载的目录 + systemctl stop docker.socket + systemctl stop docker + cp -r /var/lib/docker/* ${docker}/ + #5在/etc/docker写入daemon.json(需要检查) + if [ -d "$daemon" ]; then + mv -r $daemon ${daemon}.bak + fi + echo "{\"data-root\": \"$docker\"}" >$daemon + #删除老数据腾出空间 + #rm -fr /var/lib/docker + systemctl start docker.socket + systemctl start docker +} + +DockerImgMove() { + image=$1 + systemctl stop docker.socket + systemctl stop docker + sudo umount -f $image +} + +GetDockerDataRoot() { + docker info | grep "Docker Root Dir:" +} + +SetLink() { + ln -s /mnt/casa_sda1/AppData /DATA/AppData + #删除所有软链 + find /DATA -type l -delete +} + +#压缩文件夹 + +TarFolder() { + #压缩 + tar -zcvf data.tar.gz -C/DATA/ AppDataBak/ + + #解压 + tar zxvf data.tar.gz + + #查看某文件夹下的所有包括子文件夹文件 + ls /DATA/Media -lR | grep "^-" | wc -l + # ls -lR|grep "^d"| wc -l 查看某个文件夹下文件夹的个数,包括子文件夹下的文件夹个数。 + + #查看固定文件夹大小 + du -sh /DATA +} + +USB_Start_Auto() { + ((EUID)) && sudo_cmd="sudo" + $sudo_cmd systemctl enable devmon@devmon + $sudo_cmd systemctl start devmon@devmon +} + +USB_Stop_Auto() { + ((EUID)) && sudo_cmd="sudo" + $sudo_cmd systemctl stop devmon@devmon + $sudo_cmd systemctl disable devmon@devmon + $sudo_cmd udevil clean +} + +GetDeviceTree(){ + cat /proc/device-tree/model +} + +# restart samba service +RestartSMBD(){ + $sudo_cmd systemctl restart smbd +} + +# edit user password $1:username +EditSmabaUserPassword(){ + $sudo_cmd smbpasswd $1 +} + +AddSmabaUser(){ + $sudo_cmd useradd $1 + $sudo_cmd smbpasswd -a $1 <>"/var/log/usb-mount.track" + # fi + # + # ${log} "Mounted ${DEVICE} at ${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 +} + +do_umount() { + + if [[ -z ${MOUNT_POINT} ]]; then + ${log} "Warning: ${DEVICE} is not mounted" + else + #/bin/kill -9 $(lsof ${MOUNT_POINT}) + umount -l ${DEVICE} + ${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}" + if [ "`ls -A ${MOUNT_POINT}`" = "" ]; then + /bin/rm -fr "${MOUNT_POINT}" + fi + sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track + fi + +} + +case "${ACTION}" in +add) + do_mount + ;; +remove) + do_umount + ;; +*) + exit 1 + ;; +esac From 4776b76b1601a4a055ee5a4fa50175c22911536b Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Tue, 13 Sep 2022 07:22:24 +0100 Subject: [PATCH 03/42] add system notiry --- common/notify.go | 18 ++++++++++++++++++ route/route.go | 2 ++ route/v1/notiry.go | 6 ++++++ service/notify.go | 20 ++++++++++++++------ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/common/notify.go b/common/notify.go index 4a003d0..c36cea0 100644 --- a/common/notify.go +++ b/common/notify.go @@ -18,6 +18,7 @@ const ( type NotifyService interface { SendNotify(path string, message map[string]interface{}) error + SendSystemNotify(message map[string]interface{}) error } type notifyService struct { address string @@ -41,7 +42,24 @@ func (n *notifyService) SendNotify(path string, message map[string]interface{}) return nil } +func (n *notifyService) SendSystemNotify(message map[string]interface{}) error { + url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify + body, err := json.Marshal(message) + if err != nil { + return err + } + response, err := http.Post(url, "application/json", bytes.NewBuffer(body)) + if err != nil { + return err + } + + if response.StatusCode != http.StatusCreated { + return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") + } + return nil + +} func NewNotifyService(runtimePath string) (NotifyService, error) { casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename) diff --git a/route/route.go b/route/route.go index 39d011b..0bfcbfc 100644 --- a/route/route.go +++ b/route/route.go @@ -244,6 +244,8 @@ func InitRouter() *gin.Engine { v1NotifyGroup.Use() { v1NotifyGroup.POST("/:path", v1.PostNotifyMssage) + //merge to system + v1NotifyGroup.POST("", v1.PostSystemNotyfiy) } } return r diff --git a/route/v1/notiry.go b/route/v1/notiry.go index c818aab..54e86fd 100644 --- a/route/v1/notiry.go +++ b/route/v1/notiry.go @@ -14,3 +14,9 @@ func PostNotifyMssage(c *gin.Context) { service.MyService.Notify().SendNotify(path, message) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) } +func PostSystemNotyfiy(c *gin.Context) { + message := make(map[string]interface{}) + c.ShouldBind(&message) + service.MyService.Notify().SettingSystemTempData(message) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} diff --git a/service/notify.go b/service/notify.go index 154d45a..fe93d83 100644 --- a/service/notify.go +++ b/service/notify.go @@ -38,14 +38,21 @@ type NotifyServer interface { SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) SendStorageBySocket(message notify.StorageMessage) SendNotify(path string, message map[string]interface{}) + SettingSystemTempData(message map[string]interface{}) } type notifyServer struct { - db *gorm.DB + db *gorm.DB + SystemTempMap map[string]interface{} +} + +func (i *notifyServer) SettingSystemTempData(message map[string]interface{}) { + for k, v := range message { + i.SystemTempMap[k] = v + } } func (i *notifyServer) SendNotify(path string, message map[string]interface{}) { - msg := gosf.Message{} msg.Body = message msg.Success = true @@ -77,9 +84,6 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) { func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) { body := make(map[string]interface{}) - body["sys_disk"] = disk - - body["sys_usb"] = list body["sys_mem"] = mem @@ -87,6 +91,10 @@ func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list [ body["sys_net"] = netList + for k, v := range i.SystemTempMap { + body[k] = v + } + msg := gosf.Message{} msg.Body = body msg.Success = true @@ -470,5 +478,5 @@ func SendMeg() { // } func NewNotifyService(db *gorm.DB) NotifyServer { - return ¬ifyServer{db: db} + return ¬ifyServer{db: db, SystemTempMap: make(map[string]interface{})} } From 7f4562629a43c5715664eb29d5e20cb50f92a49c Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Thu, 15 Sep 2022 08:13:07 +0100 Subject: [PATCH 04/42] remove disk and test common package --- common/notify.go | 14 +- common/notify_test.go | 29 ++ go.mod | 1 - go.sum | 2 - main.go | 3 +- model/disk.go | 98 ------- model/docker.go | 4 + model/receive/app.go | 1 - pkg/sqlite/db.go | 2 +- route/init.go | 46 --- route/periodical.go | 257 +++-------------- route/route.go | 47 +-- route/v1/app.go | 53 ++++ route/v1/disk.go | 622 ---------------------------------------- route/v1/file.go | 27 +- route/v1/notiry.go | 5 +- route/v1/storage.go | 109 ------- route/v1/system.go | 147 +--------- service/disk.go | 285 ------------------ service/docker.go | 74 +++-- service/model/o_disk.go | 25 -- service/notify.go | 38 +-- service/service.go | 7 - 23 files changed, 186 insertions(+), 1710 deletions(-) create mode 100644 common/notify_test.go delete mode 100644 model/disk.go delete mode 100644 model/receive/app.go delete mode 100644 route/v1/disk.go delete mode 100644 route/v1/storage.go delete mode 100644 service/disk.go delete mode 100644 service/model/o_disk.go diff --git a/common/notify.go b/common/notify.go index c36cea0..82d3394 100644 --- a/common/notify.go +++ b/common/notify.go @@ -13,12 +13,12 @@ import ( const ( CasaOSURLFilename = "casaos.url" - APICasaOSNotify = "/v1/notiry" + APICasaOSNotify = "/v1/notify" ) type NotifyService interface { SendNotify(path string, message map[string]interface{}) error - SendSystemNotify(message map[string]interface{}) error + SendSystemStatusNotify(message map[string]interface{}) error } type notifyService struct { address string @@ -26,7 +26,7 @@ type notifyService struct { func (n *notifyService) SendNotify(path string, message map[string]interface{}) error { - url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify + "/" + path + url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/" + path body, err := json.Marshal(message) if err != nil { return err @@ -42,9 +42,13 @@ func (n *notifyService) SendNotify(path string, message map[string]interface{}) return nil } -func (n *notifyService) SendSystemNotify(message map[string]interface{}) error { - url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify +// disk: "sys_disk":{"size":56866869248,"avail":5855485952,"health":true,"used":48099700736} +// usb: "sys_usb":[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}] +func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) error { + + url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/system_status" + fmt.Println(url) body, err := json.Marshal(message) if err != nil { return err diff --git a/common/notify_test.go b/common/notify_test.go new file mode 100644 index 0000000..1e9c543 --- /dev/null +++ b/common/notify_test.go @@ -0,0 +1,29 @@ +package common + +import "testing" + +func TestSendNotify(t *testing.T) { + notify, err := NewNotifyService("/var/run/casaos") + if err != nil { + t.Fatal(err) + } + err = notify.SendNotify("test", map[string]interface{}{ + "test": "test", + }) + if err != nil { + t.Fatal(err) + } +} + +func TestSendSystemStatusNotify(t *testing.T) { + notify, err := NewNotifyService("/var/run/casaos") + if err != nil { + t.Fatal(err) + } + err = notify.SendSystemStatusNotify(map[string]interface{}{ + "sys_usb": `[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]`, + }) + if err != nil { + t.Fatal(err) + } +} diff --git a/go.mod b/go.mod index 6af729f..b68d268 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,6 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/pilebones/go-udev v0.9.0 github.com/pkg/errors v0.9.1 github.com/robfig/cron v1.2.0 github.com/satori/go.uuid v1.2.0 diff --git a/go.sum b/go.sum index 45192e2..5baa719 100644 --- a/go.sum +++ b/go.sum @@ -813,8 +813,6 @@ github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZO github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q= -github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/main.go b/main.go index 6ff7af8..f02afca 100644 --- a/main.go +++ b/main.go @@ -80,7 +80,6 @@ func main() { return } go route.SocketInit(service.NotifyMsg) - go route.MonitoryUSB() //model.Setup() //gredis.Setup() @@ -110,7 +109,7 @@ func main() { if err != nil { panic(err) } - routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba", "notify"} + routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "samba", "notify"} for _, v := range routers { err = service.MyService.Gateway().CreateRoute(&common.Route{ Path: "/v1/" + v, diff --git a/model/disk.go b/model/disk.go deleted file mode 100644 index 75d3bc5..0000000 --- a/model/disk.go +++ /dev/null @@ -1,98 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2022-07-13 10:43:45 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-03 14:45:35 - * @FilePath: /CasaOS/model/disk.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package model - -type LSBLKModel struct { - Name string `json:"name"` - FsType string `json:"fstype"` - Size uint64 `json:"size"` - FSSize string `json:"fssize"` - Path string `json:"path"` - Model string `json:"model"` //设备标识符 - RM bool `json:"rm"` //是否为可移动设备 - RO bool `json:"ro"` //是否为只读设备 - State string `json:"state"` - PhySec int `json:"phy-sec"` //物理扇区大小 - Type string `json:"type"` - Vendor string `json:"vendor"` //供应商 - Rev string `json:"rev"` //修订版本 - FSAvail string `json:"fsavail"` //可用空间 - FSUse string `json:"fsuse%"` //已用百分比 - MountPoint string `json:"mountpoint"` - Format string `json:"format"` - Health string `json:"health"` - HotPlug bool `json:"hotplug"` - UUID string `json:"uuid"` - FSUsed string `json:"fsused"` - Temperature int `json:"temperature"` - Tran string `json:"tran"` - MinIO uint64 `json:"min-io"` - UsedPercent float64 `json:"used_percent"` - Serial string `json:"serial"` - Children []LSBLKModel `json:"children"` - SubSystems string `json:"subsystems"` - Label string `json:"label"` - //详情特有 - StartSector uint64 `json:"start_sector,omitempty"` - Rota bool `json:"rota"` //true(hhd) false(ssd) - DiskType string `json:"disk_type"` - EndSector uint64 `json:"end_sector,omitempty"` -} - -type Drive struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Model string `json:"model"` - Health string `json:"health"` - Temperature int `json:"temperature"` - DiskType string `json:"disk_type"` - NeedFormat bool `json:"need_format"` - Serial string `json:"serial"` - Path string `json:"path"` - ChildrenNumber int `json:"children_number"` -} - -type DriveUSB struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Model string `json:"model"` - Avail uint64 `json:"avail"` - Children []USBChildren `json:"children"` -} -type USBChildren struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Avail uint64 `json:"avail"` - MountPoint string `json:"mount_point"` -} - -type Storage struct { - MountPoint string `json:"mount_point"` - Size string `json:"size"` - Avail string `json:"avail"` //可用空间 - Type string `json:"type"` - Path string `json:"path"` - DriveName string `json:"drive_name"` - Label string `json:"label"` -} -type Storages struct { - DiskName string `json:"disk_name"` - Size uint64 `json:"size"` - Path string `json:"path"` - Children []Storage `json:"children"` -} - -type Summary struct { - Size uint64 `json:"size"` - Avail uint64 `json:"avail"` //可用空间 - Health bool `json:"health"` - Used uint64 `json:"used"` -} diff --git a/model/docker.go b/model/docker.go index a083319..20b68cc 100644 --- a/model/docker.go +++ b/model/docker.go @@ -16,3 +16,7 @@ type DockerStatsModel struct { Data interface{} `json:"data"` Previous interface{} `json:"previous"` } + +type DeckerDaemonModel struct { + Graph string `json:"graph"` +} diff --git a/model/receive/app.go b/model/receive/app.go deleted file mode 100644 index 3ccae50..0000000 --- a/model/receive/app.go +++ /dev/null @@ -1 +0,0 @@ -package receive diff --git a/pkg/sqlite/db.go b/pkg/sqlite/db.go index 819da65..e5d7595 100644 --- a/pkg/sqlite/db.go +++ b/pkg/sqlite/db.go @@ -43,7 +43,7 @@ func GetDb(dbPath string) *gorm.DB { } gdb = db - err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}) + err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}) db.Exec("DROP TABLE IF EXISTS o_application") db.Exec("DROP TABLE IF EXISTS o_friend") db.Exec("DROP TABLE IF EXISTS o_person_download") diff --git a/route/init.go b/route/init.go index e2d09c7..a35de29 100644 --- a/route/init.go +++ b/route/init.go @@ -3,65 +3,19 @@ package route import ( "fmt" "os" - "strconv" "strings" "time" - "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/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" - model2 "github.com/IceWhaleTech/CasaOS/service/model" "go.uber.org/zap" ) func InitFunction() { - CheckSerialDiskMount() go InitNetworkMount() } - -func CheckSerialDiskMount() { - // check mount point - dbList := service.MyService.Disk().GetSerialAll() - - list := service.MyService.Disk().LSBLK(true) - mountPoint := make(map[string]string, len(dbList)) - //remount - for _, v := range dbList { - mountPoint[v.UUID] = v.MountPoint - } - for _, v := range list { - 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) - } - } - 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().RemoveLSBLKCache() - command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;AutoRemoveUnuseDir") -} - func InitNetworkMount() { time.Sleep(time.Second * 10) connections := service.MyService.Connections().GetConnectionsList() diff --git a/route/periodical.go b/route/periodical.go index 6fbdd74..7d12ca2 100644 --- a/route/periodical.go +++ b/route/periodical.go @@ -14,20 +14,12 @@ package route import ( - "os" - "os/signal" - "reflect" - "strconv" "strings" - "syscall" "time" "unsafe" "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" - "github.com/pilebones/go-udev/netlink" - "go.uber.org/zap" ) func SendNetINfoBySocket() { @@ -61,104 +53,6 @@ func SendMemBySocket() { service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo()) } -func SendDiskBySocket() { - list := service.MyService.Disk().LSBLK(true) - - 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" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - healthy = true - } else { - healthy = temp.SmartStatus.Passed - } - - //list[i].Temperature = temp.Temperature.Current - - 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 - service.MyService.Notify().SendDiskInfoBySocket(summary) -} - -func SendUSBBySocket() { - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - - } - } - if isMount { - usb = append(usb, temp) - } - } - } - service.MyService.Notify().SendUSBInfoBySocket(usb) -} - func SendAllHardwareStatusBySocket() { netList := service.MyService.System().GetNetInfo() @@ -183,131 +77,44 @@ func SendAllHardwareStatusBySocket() { cpuData["temperature"] = service.MyService.System().GetCPUTemperature() cpuData["power"] = service.MyService.System().GetCPUPower() - list := service.MyService.Disk().LSBLK(true) - - 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" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - healthy = true - } else { - healthy = temp.SmartStatus.Passed - } - 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 - - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - } - } - if isMount { - usb = append(usb, temp) - } - - } - } memInfo := service.MyService.System().GetMemInfo() - service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet) + service.MyService.Notify().SendAllHardwareStatusBySocket(memInfo, cpuData, newNet) } -func MonitoryUSB() { - var matcher netlink.Matcher - conn := new(netlink.UEventConn) - if err := conn.Connect(netlink.UdevEvent); err != nil { - loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err)) - } - defer conn.Close() +// func MonitoryUSB() { +// var matcher netlink.Matcher - queue := make(chan netlink.UEvent) - errors := make(chan error) - quit := conn.Monitor(queue, errors, matcher) +// conn := new(netlink.UEventConn) +// if err := conn.Connect(netlink.UdevEvent); err != nil { +// loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err)) +// } +// defer conn.Close() - signals := make(chan os.Signal, 1) - signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - go func() { - <-signals - close(quit) - os.Exit(0) - }() +// queue := make(chan netlink.UEvent) +// errors := make(chan error) +// quit := conn.Monitor(queue, errors, matcher) - for { - select { - case uevent := <-queue: - if uevent.Env["DEVTYPE"] == "disk" { - time.Sleep(time.Microsecond * 500) - SendUSBBySocket() - continue - } - case err := <-errors: - loger.Error("udev err", zap.Any("err", err)) - } - } +// signals := make(chan os.Signal, 1) +// signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) +// go func() { +// <-signals +// close(quit) +// os.Exit(0) +// }() -} +// for { +// select { +// case uevent := <-queue: +// if uevent.Env["DEVTYPE"] == "disk" { +// time.Sleep(time.Microsecond * 500) +// SendUSBBySocket() +// continue +// } +// case err := <-errors: +// loger.Error("udev err", zap.Any("err", err)) +// } +// } + +// } diff --git a/route/route.go b/route/route.go index 0bfcbfc..110fd69 100644 --- a/route/route.go +++ b/route/route.go @@ -1,7 +1,7 @@ package route import ( - jwt2 "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" "github.com/IceWhaleTech/CasaOS/middleware" "github.com/IceWhaleTech/CasaOS/pkg/config" v1 "github.com/IceWhaleTech/CasaOS/route/v1" @@ -45,7 +45,7 @@ func InitRouter() *gin.Engine { }) v1Group := r.Group("/v1") - v1Group.Use(jwt2.JWT()) + v1Group.Use(jwt.ExceptLocalhost()) { // v1UsersGroup := v1Group.Group("/users") // v1UsersGroup.Use() @@ -79,6 +79,7 @@ func InitRouter() *gin.Engine { v1ContainerGroup := v1Group.Group("/container") v1ContainerGroup.Use() { + v1ContainerGroup.GET("", v1.MyAppList) ///my/list v1ContainerGroup.GET("/usage", v1.AppUsageList) v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info @@ -99,6 +100,8 @@ func InitRouter() *gin.Engine { v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate) //Not used v1ContainerGroup.POST("/share", v1.ShareAppFile) + v1ContainerGroup.GET("/info", v1.GetcontainerInfo) + v1ContainerGroup.PUT("/info", v1.PutcontainerInfo) } v1AppCategoriesGroup := v1Group.Group("/app-categories") @@ -185,42 +188,6 @@ func InitRouter() *gin.Engine { { v1ImageGroup.GET("", v1.GetFileImage) } - - v1DisksGroup := v1Group.Group("/disks") - v1DisksGroup.Use() - { - //v1DiskGroup.GET("/check", v1.GetDiskCheck) //delete - //v1DisksGroup.GET("", v1.GetDiskInfo) - - //v1DisksGroup.POST("", v1.PostMountDisk) - v1DisksGroup.GET("", v1.GetDiskList) - v1DisksGroup.GET("/usb", v1.GetDisksUSBList) - v1DisksGroup.DELETE("/usb", v1.DeleteDiskUSB) - v1DisksGroup.DELETE("", v1.DeleteDisksUmount) - // //format storage - // v1DiskGroup.POST("/format", v1.PostDiskFormat) - - // //mount SATA disk - // v1DiskGroup.POST("/mount", v1.PostMountDisk) - - // //umount sata disk - // v1DiskGroup.POST("/umount", v1.PostDiskUmount) - - //v1DiskGroup.GET("/type", v1.FormatDiskType)//delete - - v1DisksGroup.DELETE("/part", v1.RemovePartition) //disk/delpart - } - - v1StorageGroup := v1Group.Group("/storage") - v1StorageGroup.Use() - { - v1StorageGroup.POST("", v1.PostDiskAddPartition) - - v1StorageGroup.PUT("", v1.PostDiskFormat) - - v1StorageGroup.DELETE("", v1.PostDiskUmount) - v1StorageGroup.GET("", v1.GetStorageList) - } v1SambaGroup := v1Group.Group("/samba") v1SambaGroup.Use() { @@ -243,9 +210,9 @@ func InitRouter() *gin.Engine { v1NotifyGroup := v1Group.Group("/notify") v1NotifyGroup.Use() { - v1NotifyGroup.POST("/:path", v1.PostNotifyMssage) + v1NotifyGroup.POST("/:path", v1.PostNotifyMessage) //merge to system - v1NotifyGroup.POST("", v1.PostSystemNotyfiy) + v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify) } } return r diff --git a/route/v1/app.go b/route/v1/app.go index 1a9f278..cc2ee00 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -2,10 +2,12 @@ package v1 import ( "encoding/json" + "fmt" "io/ioutil" "strconv" "github.com/IceWhaleTech/CasaOS/model" + "github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" @@ -262,3 +264,54 @@ func ShareAppFile(c *gin.Context) { content := service.MyService.Casa().ShareAppFile(str) c.JSON(common_err.SUCCESS, json.RawMessage(content)) } + +func GetcontainerInfo(c *gin.Context) { + // info, err := service.MyService.Docker().GetDockerInfo() + // 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 + // } + daemon := model.DeckerDaemonModel{} + data := make(map[string]interface{}, 1) + data["docker_root_dir"] = "" + if file.Exists("/etc/docker/daemon.json") { + byteResult := file.ReadFullFile("/etc/docker/daemon.json") + err := json.Unmarshal(byteResult, &daemon) + if err != nil { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + return + } + data["docker_root_dir"] = daemon.Graph + } + c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) +} +func PutcontainerInfo(c *gin.Context) { + js := make(map[string]interface{}) + err := c.BindJSON(&js) + if err != nil { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + return + } + dockerRootDir := js["docker_root_dir"].(string) + daemon := model.DeckerDaemonModel{} + if file.Exists("/etc/docker/daemon.json") { + byteResult := file.ReadFullFile("/etc/docker/daemon.json") + err := json.Unmarshal(byteResult, &daemon) + if err != nil { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + return + } + } + if !file.Exists(dockerRootDir) { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) + return + } + daemon.Graph = dockerRootDir + byteMode, _ := json.Marshal(daemon) + file.WriteToPath(byteMode, "/etc/docker", "daemon.json") + + fmt.Println(command.ExecResultStr("systemctl daemon-reload")) + fmt.Println(command.ExecResultStr("systemctl restart docker")) + + c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) +} diff --git a/route/v1/disk.go b/route/v1/disk.go deleted file mode 100644 index e72e3ff..0000000 --- a/route/v1/disk.go +++ /dev/null @@ -1,622 +0,0 @@ -package v1 - -import ( - "fmt" - "net/http" - "path/filepath" - "reflect" - "strconv" - "strings" - "time" - - "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/model/notify" - "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" - "github.com/IceWhaleTech/CasaOS/pkg/utils/encryption" - "github.com/IceWhaleTech/CasaOS/pkg/utils/file" - - "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" - "github.com/IceWhaleTech/CasaOS/service" - model2 "github.com/IceWhaleTech/CasaOS/service/model" - "github.com/gin-gonic/gin" - "github.com/shirou/gopsutil/v3/disk" -) - -var diskMap = make(map[string]string) - -// @Summary disk list -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/list [get] -func GetDiskList(c *gin.Context) { - path := c.Query("path") - if len(path) > 0 { - m := service.MyService.Disk().GetDiskInfo(path) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m}) - return - } - t := c.DefaultQuery("type", "") - list := service.MyService.Disk().LSBLK(false) - if t == "usb" { - data := []model.DriveUSB{} - for _, v := range list { - if v.Tran == "usb" { - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - } - } - data = append(data, temp) - } - } - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) - return - } - - dbList := service.MyService.Disk().GetSerialAll() - part := make(map[string]int64, len(dbList)) - for _, v := range dbList { - part[v.MountPoint] = v.CreatedAt - } - findSystem := 0 - - disks := []model.Drive{} - storage := []model.Storage{} - avail := []model.Drive{} - for i := 0; i < len(list); i++ { - disk := model.Drive{} - if list[i].Rota { - disk.DiskType = "HDD" - } else { - disk.DiskType = "SSD" - } - disk.Serial = list[i].Serial - disk.Name = list[i].Name - disk.Size = list[i].Size - disk.Path = list[i].Path - disk.Model = list[i].Model - disk.ChildrenNumber = len(list[i].Children) - if len(list[i].Children) > 0 && findSystem == 0 { - for j := 0; j < len(list[i].Children); j++ { - if len(list[i].Children[j].Children) > 0 { - for _, v := range list[i].Children[j].Children { - if v.MountPoint == "/" { - stor := model.Storage{} - stor.MountPoint = v.MountPoint - stor.Size = v.FSSize - stor.Avail = v.FSAvail - stor.Path = v.Path - stor.Type = v.FsType - stor.DriveName = "System" - disk.Model = "System" - if strings.Contains(v.SubSystems, "mmc") { - disk.DiskType = "MMC" - } else if strings.Contains(v.SubSystems, "usb") { - disk.DiskType = "USB" - } - disk.Health = "true" - - disks = append(disks, disk) - storage = append(storage, stor) - findSystem = 1 - break - } - } - } else { - if list[i].Children[j].MountPoint == "/" { - stor := model.Storage{} - stor.MountPoint = list[i].Children[j].MountPoint - stor.Size = list[i].Children[j].FSSize - stor.Avail = list[i].Children[j].FSAvail - stor.Path = list[i].Children[j].Path - stor.Type = list[i].Children[j].FsType - stor.DriveName = "System" - disk.Model = "System" - if strings.Contains(list[i].Children[j].SubSystems, "mmc") { - disk.DiskType = "MMC" - } else if strings.Contains(list[i].Children[j].SubSystems, "usb") { - disk.DiskType = "USB" - } - disk.Health = "true" - - disks = append(disks, disk) - storage = append(storage, stor) - findSystem = 1 - break - } - } - - } - } - if findSystem == 1 { - findSystem += 1 - continue - } - - if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - temp.SmartStatus.Passed = true - } - isAvail := true - for _, v := range list[i].Children { - if v.MountPoint != "" { - stor := model.Storage{} - stor.MountPoint = v.MountPoint - stor.Size = v.FSSize - stor.Avail = v.FSAvail - stor.Path = v.Path - stor.Type = v.FsType - stor.DriveName = list[i].Name - storage = append(storage, stor) - isAvail = false - } - } - - if isAvail { - //if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" { - disk.NeedFormat = false - avail = append(avail, disk) - // } else { - // disk.NeedFormat = true - // avail = append(avail, disk) - // } - } - - disk.Temperature = temp.Temperature.Current - disk.Health = strconv.FormatBool(temp.SmartStatus.Passed) - - disks = append(disks, disk) - } - } - data := make(map[string]interface{}, 3) - data["drive"] = disks - data["storage"] = storage - data["avail"] = avail - - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) -} - -// @Summary disk list -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/list [get] -func GetDisksUSBList(c *gin.Context) { - list := service.MyService.Disk().LSBLK(false) - data := []model.DriveUSB{} - for _, v := range list { - if v.Tran == "usb" { - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Label - if temp.Name == "" { - temp.Name = v.Name - } - temp.Size = v.Size - children := []model.USBChildren{} - for _, child := range v.Children { - - if len(child.MountPoint) > 0 { - tempChildren := model.USBChildren{} - tempChildren.MountPoint = child.MountPoint - tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64) - tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64) - tempChildren.Name = child.Label - if len(tempChildren.Name) == 0 { - tempChildren.Name = filepath.Base(child.MountPoint) - } - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - children = append(children, tempChildren) - temp.Avail += avail - } - } - - temp.Children = children - data = append(data, temp) - } - } - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) - -} - -func DeleteDisksUmount(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - - path := js["path"] - pwd := js["password"] - - if len(path) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - token := c.GetHeader("Authorization") - if len(token) == 0 { - token = c.Query("token") - } - claims, err := jwt.ParseToken(token, true) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if encryption.GetMD5ByStr(pwd) != claims.Password { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - - diskInfo := service.MyService.Disk().GetDiskInfo(path) - for _, v := range diskInfo.Children { - service.MyService.Disk().UmountPointAndRemoveDir(v.Path) - //delete data - service.MyService.Disk().DeleteMountPoint(v.Path, v.MountPoint) - - service.MyService.Shares().DeleteShareByPath(v.MountPoint) - } - - service.MyService.Disk().RemoveLSBLKCache() - - //send notify to client - msg := notify.StorageMessage{} - msg.Action = "REMOVED" - msg.Path = path - msg.Volume = "" - msg.Size = 0 - msg.Type = "" - service.MyService.Notify().SendStorageBySocket(msg) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: path}) -} - -func DeleteDiskUSB(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - mountPoint := js["mount_point"] - if file.CheckNotExist(mountPoint) { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) - return - } - service.MyService.Disk().UmountUSB(mountPoint) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint}) -} - -// @Summary get disk list -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/lists [get] -func GetPlugInDisks(c *gin.Context) { - - list := service.MyService.Disk().LSBLK(true) - var result []*disk.UsageStat - for _, item := range list { - result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path)) - } - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result}) -} - -// @Summary disk detail -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Param path query string true "for example /dev/sda" -// @Success 200 {string} string "ok" -// @Router /disk/info [get] -func GetDiskInfo(c *gin.Context) { - path := c.Query("path") - if len(path) == 0 { - c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - } - m := service.MyService.Disk().GetDiskInfo(path) - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m}) -} - -// @Summary 获取支持的格式 -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/type [get] -func FormatDiskType(c *gin.Context) { - var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"} - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr}) - -} - -// @Summary 删除分区 -// @Produce application/json -// @Accept multipart/form-data -// @Tags disk -// @Security ApiKeyAuth -// @Param path formData string true "磁盘路径 例如/dev/sda1" -// @Success 200 {string} string "ok" -// @Router /disk/delpart [delete] -func RemovePartition(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - path := js["path"] - - if len(path) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - } - var p = path[:len(path)-1] - var n = path[len(path)-1:] - service.MyService.Disk().DelPartition(p, n) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary add storage -// @Produce application/json -// @Accept multipart/form-data -// @Tags disk -// @Security ApiKeyAuth -// @Param path formData string true "disk path e.g. /dev/sda" -// @Param serial formData string true "serial" -// @Param name formData string true "name" -// @Param format formData bool true "need format(true)" -// @Success 200 {string} string "ok" -// @Router /disk/storage [post] -func PostDiskAddPartition(c *gin.Context) { - - js := make(map[string]interface{}) - c.ShouldBind(&js) - path := js["path"].(string) - name := js["name"].(string) - format := js["format"].(bool) - - if len(path) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - - //diskInfo := service.MyService.Disk().GetDiskInfo(path) - - // if !file.CheckNotExist("/DATA/" + name) { - // // /mnt/name exist - // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)}) - // return - // } - diskMap[path] = "busying" - currentDisk := service.MyService.Disk().GetDiskInfo(path) - if format { - // format := service.MyService.Disk().FormatDisk(path+"1", "ext4") - // if len(format) == 0 { - // delete(diskMap, path) - // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)}) - // return - // } - service.MyService.Disk().AddPartition(path) - } - - // formatBool := true - // for formatBool { - // currentDisk = service.MyService.Disk().GetDiskInfo(path) - // if len(currentDisk.Children) > 0 { - // formatBool = false - // break - // } - // time.Sleep(time.Second) - // } - currentDisk = service.MyService.Disk().GetDiskInfo(path) - // if len(currentDisk.Children) != 1 { - // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)}) - // return - // } - fmt.Println(name) - if len(name) == 0 { - name = "Storage" - } - fmt.Println(name) - for i := 0; i < len(currentDisk.Children); i++ { - childrenName := currentDisk.Children[i].Label - if len(childrenName) == 0 { - //childrenName = name + "_" + currentDisk.Children[i].Name - childrenName = name + "_" + strconv.Itoa(i+1) - } - mountPath := "/DATA/" + childrenName - if !file.CheckNotExist(mountPath) { - ls := service.MyService.System().GetDirPath(mountPath) - if len(ls) > 0 { - // exist - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)}) - return - } - } - m := model2.SerialDisk{} - m.MountPoint = mountPath - m.Path = currentDisk.Children[i].Path - m.UUID = currentDisk.Children[i].UUID - m.State = 0 - m.CreatedAt = time.Now().Unix() - service.MyService.Disk().SaveMountPoint(m) - //mount dir - service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath) - } - - service.MyService.Disk().RemoveLSBLKCache() - - delete(diskMap, path) - - //send notify to client - msg := notify.StorageMessage{} - msg.Action = "ADDED" - msg.Path = currentDisk.Children[0].Path - msg.Volume = "/DATA/" - msg.Size = currentDisk.Children[0].Size - msg.Type = currentDisk.Children[0].Tran - service.MyService.Notify().SendStorageBySocket(msg) - - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Param pwd formData string true "user password" -// @Param volume formData string true "mount point" -// @Success 200 {string} string "ok" -// @Router /disk/format [post] -func PostDiskFormat(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - path := js["path"] - t := "ext4" - pwd := js["password"] - volume := js["volume"] - token := c.GetHeader("Authorization") - if len(token) == 0 { - token = c.Query("token") - } - claims, err := jwt.ParseToken(token, true) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if encryption.GetMD5ByStr(pwd) != claims.Password { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if len(path) == 0 || len(t) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - diskMap[path] = "busying" - service.MyService.Disk().UmountPointAndRemoveDir(path) - format := service.MyService.Disk().FormatDisk(path, t) - if len(format) == 0 { - delete(diskMap, path) - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)}) - return - } - service.MyService.Disk().MountDisk(path, volume) - service.MyService.Disk().RemoveLSBLKCache() - delete(diskMap, path) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary remove mount point -// @Produce application/json -// @Accept multipart/form-data -// @Tags disk -// @Security ApiKeyAuth -// @Param path formData string true "e.g. /dev/sda1" -// @Param mount_point formData string true "e.g. /mnt/volume1" -// @Param pwd formData string true "user password" -// @Success 200 {string} string "ok" -// @Router /disk/umount [post] -func PostDiskUmount(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - - path := js["path"] - mountPoint := js["volume"] - pwd := js["password"] - - if len(path) == 0 || len(mountPoint) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - token := c.GetHeader("Authorization") - if len(token) == 0 { - token = c.Query("token") - } - claims, err := jwt.ParseToken(token, true) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if encryption.GetMD5ByStr(pwd) != claims.Password { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - - service.MyService.Disk().UmountPointAndRemoveDir(path) - //delete data - service.MyService.Disk().DeleteMountPoint(path, mountPoint) - service.MyService.Disk().RemoveLSBLKCache() - - //send notify to client - msg := notify.StorageMessage{} - msg.Action = "REMOVED" - msg.Path = path - msg.Volume = mountPoint - msg.Size = 0 - msg.Type = "" - service.MyService.Notify().SendStorageBySocket(msg) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary confirm delete disk -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Param id path string true "id" -// @Success 200 {string} string "ok" -// @Router /disk/remove/{id} [delete] -func DeleteDisk(c *gin.Context) { - id := c.Param("id") - service.MyService.Disk().DeleteMount(id) - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary check mount point -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/init [get] -func GetDiskCheck(c *gin.Context) { - - dbList := service.MyService.Disk().GetSerialAll() - list := service.MyService.Disk().LSBLK(true) - - mapList := make(map[string]string) - - for _, v := range list { - mapList[v.Serial] = "1" - } - - for _, v := range dbList { - if _, ok := mapList[v.UUID]; !ok { - //disk undefind - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"}) - return - } - } - - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} diff --git a/route/v1/file.go b/route/v1/file.go index 0b2dbc7..548ee4a 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -236,33 +236,8 @@ func DirPath(c *gin.Context) { info[i].Type = "application" } } - } else if path == "/DATA" { - disk := make(map[string]string) - lsblk := service.MyService.Disk().LSBLK(true) - for _, v := range lsblk { - if len(v.Children) > 0 { - t := v.Tran - for _, c := range v.Children { - if len(c.Children) > 0 { - for _, gc := range c.Children { - if len(gc.MountPoint) > 0 { - disk[gc.MountPoint] = t - } - } - } - if len(c.MountPoint) > 0 { - disk[c.MountPoint] = t - } - } - - } - } - for i := 0; i < len(info); i++ { - if v, ok := disk[info[i].Path]; ok { - info[i].Type = v - } - } } + for i := 0; i < len(info); i++ { if v, ok := sharesMap[info[i].Path]; ok { ex := make(map[string]interface{}) diff --git a/route/v1/notiry.go b/route/v1/notiry.go index 54e86fd..eef2a1b 100644 --- a/route/v1/notiry.go +++ b/route/v1/notiry.go @@ -7,14 +7,15 @@ import ( "github.com/gin-gonic/gin" ) -func PostNotifyMssage(c *gin.Context) { +func PostNotifyMessage(c *gin.Context) { path := c.Param("path") message := make(map[string]interface{}) c.ShouldBind(&message) service.MyService.Notify().SendNotify(path, message) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) } -func PostSystemNotyfiy(c *gin.Context) { + +func PostSystemStatusNotify(c *gin.Context) { message := make(map[string]interface{}) c.ShouldBind(&message) service.MyService.Notify().SettingSystemTempData(message) diff --git a/route/v1/storage.go b/route/v1/storage.go deleted file mode 100644 index b6bb3e3..0000000 --- a/route/v1/storage.go +++ /dev/null @@ -1,109 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2022-07-11 16:02:29 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-17 19:14:50 - * @FilePath: /CasaOS/route/v1/storage.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package v1 - -import ( - "path/filepath" - "reflect" - - "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" - "github.com/IceWhaleTech/CasaOS/service" - "github.com/gin-gonic/gin" -) - -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 { - 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{}) { - temp.SmartStatus.Passed = true - } - 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 - stor.Avail = v.FSAvail - stor.Path = v.Path - stor.Type = v.FsType - stor.DriveName = v.Name - if len(v.Label) == 0 { - if stor.MountPoint == "/" { - stor.Label = "System" - } else { - stor.Label = filepath.Base(stor.MountPoint) - } - - children += 1 - } else { - stor.Label = v.Label - } - storageArr = append(storageArr, stor) - } - } - - if len(storageArr) > 0 { - 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 9f908d2..29fbcf2 100644 --- a/route/v1/system.go +++ b/route/v1/system.go @@ -7,7 +7,6 @@ import ( "io/ioutil" "net/http" "os" - "reflect" "strconv" "strings" "time" @@ -16,14 +15,12 @@ import ( "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" 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" "github.com/IceWhaleTech/CasaOS/types" "github.com/gin-gonic/gin" - "go.uber.org/zap" ) // @Summary check version @@ -79,7 +76,7 @@ func GetCasaOSErrorLogs(c *gin.Context) { c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)}) } -//系统配置 +// 系统配置 func GetSystemConfigDebug(c *gin.Context) { array := service.MyService.System().GetSystemConfigDebug() disk := service.MyService.System().GetDiskInfo() @@ -185,31 +182,6 @@ func PutSystemUSBAutoMount(c *gin.Context) { service.MyService.System().UpdateUSBAutoMount("False") service.MyService.System().ExecUSBAutoMountShell("False") } - go func() { - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - - } - } - if isMount { - usb = append(usb, temp) - } - } - } - service.MyService.Notify().SendUSBInfoBySocket(usb) - }() c.JSON(common_err.SUCCESS, model.Result{ Success: common_err.SUCCESS, @@ -229,31 +201,6 @@ func GetSystemUSBAutoMount(c *gin.Context) { if config.ServerInfo.USBAutoMount == "False" { state = "False" } - go func() { - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - - } - } - if isMount { - usb = append(usb, temp) - } - } - } - service.MyService.Notify().SendUSBInfoBySocket(usb) - }() c.JSON(common_err.SUCCESS, model.Result{ Success: common_err.SUCCESS, @@ -324,98 +271,6 @@ func GetSystemHardwareInfo(c *gin.Context) { // @Router /sys/utilization [get] func GetSystemUtilization(c *gin.Context) { var data = make(map[string]interface{}, 6) - - list := service.MyService.Disk().LSBLK(true) - - 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) - loger.Info("disk info", zap.Any("/ total:", s)) - loger.Info("disk path", zap.Any("path", v.Path)) - 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) - loger.Info("disk info", zap.Any("/ total:", s)) - loger.Info("disk path", zap.Any("path", list[i].Path)) - 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" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - healthy = true - } else { - healthy = temp.SmartStatus.Passed - } - 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) - loger.Info("disk info", zap.Any("/ total:", s)) - loger.Info("disk path", zap.Any("path", list[i].Path)) - 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 - - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - } - } - usb = append(usb, temp) - } - } - data["usb"] = usb cpu := service.MyService.System().GetCpuPercent() num := service.MyService.System().GetCpuCoreNum() cpuData := make(map[string]interface{}) diff --git a/service/disk.go b/service/disk.go deleted file mode 100644 index dfe8219..0000000 --- a/service/disk.go +++ /dev/null @@ -1,285 +0,0 @@ -package service - -import ( - json2 "encoding/json" - "fmt" - "reflect" - "strconv" - "strings" - "time" - - "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/config" - command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" - model2 "github.com/IceWhaleTech/CasaOS/service/model" - "github.com/shirou/gopsutil/v3/disk" - "github.com/tidwall/gjson" - "go.uber.org/zap" - "gorm.io/gorm" -) - -type DiskService interface { - GetPlugInDisk() []string - LSBLK(isUseCache bool) []model.LSBLKModel - SmartCTL(path string) model.SmartctlA - FormatDisk(path, format string) []string - UmountPointAndRemoveDir(path string) []string - GetDiskInfo(path string) model.LSBLKModel - DelPartition(path, num string) string - AddPartition(path string) string - GetDiskInfoByPath(path string) *disk.UsageStat - MountDisk(path, volume string) - GetSerialAll() []model2.SerialDisk - SaveMountPoint(m model2.SerialDisk) - DeleteMountPoint(path, mountPoint string) - DeleteMount(id string) - UpdateMountPoint(m model2.SerialDisk) - RemoveLSBLKCache() - UmountUSB(path string) -} -type diskService struct { - db *gorm.DB -} - -func (d *diskService) RemoveLSBLKCache() { - key := "system_lsblk" - Cache.Delete(key) -} -func (d *diskService) UmountUSB(path string) { - r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path) - fmt.Println(r) -} -func (d *diskService) SmartCTL(path string) model.SmartctlA { - - key := "system_smart_" + path - if result, ok := Cache.Get(key); ok { - - res, ok := result.(model.SmartctlA) - if ok { - return res - } - } - var m model.SmartctlA - str := command2.ExecSmartCTLByPath(path) - if str == nil { - loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error")) - Cache.Add(key, m, time.Minute*10) - return m - } - - err := json2.Unmarshal([]byte(str), &m) - if err != nil { - loger.Error("Failed to unmarshal json", zap.Any("err", err)) - } - if !reflect.DeepEqual(m, model.SmartctlA{}) { - Cache.Add(key, m, time.Hour*24) - } - return m -} - -//通过脚本获取外挂磁盘 -func (d *diskService) GetPlugInDisk() []string { - return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPlugInDisk") -} - -//格式化硬盘 -func (d *diskService) FormatDisk(path, format string) []string { - r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;FormatDisk " + path + " " + format) - return r -} - -//移除挂载点,删除目录 -func (d *diskService) UmountPointAndRemoveDir(path string) []string { - r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + path) - return r -} - -//删除分区 -func (d *diskService) DelPartition(path, num string) string { - r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;DelPartition " + path + " " + num) - fmt.Println(r) - return "" -} - -//part -func (d *diskService) AddPartition(path string) string { - command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;AddPartition " + path) - return "" -} - -func (d *diskService) AddAllPartition(path string) { - -} - -//获取硬盘详情 -func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat { - diskInfo, err := disk.Usage(path + "1") - - if err != nil { - fmt.Println(err) - } - diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64) - diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64) - return diskInfo -} - -//get disk details -func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel { - key := "system_lsblk" - var n []model.LSBLKModel - - if result, ok := Cache.Get(key); ok && isUseCache { - - res, ok := result.([]model.LSBLKModel) - if ok { - return res - } - } - - str := command2.ExecLSBLK() - if str == nil { - loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error")) - return nil - } - var m []model.LSBLKModel - err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m) - if err != nil { - loger.Error("Failed to unmarshal json", zap.Any("err", err)) - } - - var c []model.LSBLKModel - - var fsused uint64 - - var health = true - for _, i := range m { - if i.Type != "loop" && !i.RO { - fsused = 0 - for _, child := range i.Children { - if child.RM { - child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskHealthState " + child.Path)) - if strings.ToLower(strings.TrimSpace(child.State)) != "ok" { - health = false - } - f, _ := strconv.ParseUint(child.FSUsed, 10, 64) - fsused += f - } else { - health = false - } - c = append(c, child) - } - //i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskType " + i.Path)) - if health { - i.Health = "OK" - } - i.FSUsed = strconv.FormatUint(fsused, 10) - i.Children = c - if fsused > 0 { - i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64) - if err != nil { - loger.Error("Failed to parse float", zap.Any("err", err)) - } - } - n = append(n, i) - health = true - c = []model.LSBLKModel{} - fsused = 0 - } - } - if len(n) > 0 { - Cache.Add(key, n, time.Second*100) - } - return n -} - -func (d *diskService) GetDiskInfo(path string) model.LSBLKModel { - str := command2.ExecLSBLKByPath(path) - if str == nil { - loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error")) - return model.LSBLKModel{} - } - - var ml []model.LSBLKModel - err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml) - if err != nil { - loger.Error("Failed to unmarshal json", zap.Any("err", err)) - return model.LSBLKModel{} - } - - m := model.LSBLKModel{} - if len(ml) > 0 { - m = ml[0] - } - return m - // 下面为计算是否可以继续分区的部分,暂时不需要 - chiArr := make(map[string]string) - chiList := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPartitionSectors " + m.Path) - if len(chiList) == 0 { - loger.Error("chiList length error", zap.Any("err", "chiList length error")) - } - for i := 0; i < len(chiList); i++ { - tempArr := strings.Split(chiList[i], ",") - chiArr[tempArr[0]] = chiList[i] - } - var maxSector uint64 = 0 - for i := 0; i < len(m.Children); i++ { - tempArr := strings.Split(chiArr[m.Children[i].Path], ",") - m.Children[i].StartSector, _ = strconv.ParseUint(tempArr[1], 10, 64) - m.Children[i].EndSector, _ = strconv.ParseUint(tempArr[2], 10, 64) - if m.Children[i].EndSector > maxSector { - maxSector = m.Children[i].EndSector - } - - } - diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskSizeAndSectors " + m.Path) - - if len(diskEndSector) < 2 { - loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error")) - } - diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64) - if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 { - //添加可以分区情况 - p := model.LSBLKModel{} - p.Path = "可以添加" - m.Children = append(m.Children, p) - } - return m -} - -func (d *diskService) MountDisk(path, volume string) { - //fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume) - r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume) - fmt.Println(r) -} - -func (d *diskService) SaveMountPoint(m model2.SerialDisk) { - d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{}) - d.db.Create(&m) -} - -func (d *diskService) UpdateMountPoint(m model2.SerialDisk) { - d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint) -} - -func (d *diskService) DeleteMount(id string) { - - d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id) -} - -func (d *diskService) DeleteMountPoint(path, mountPoint string) { - - d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{}) - - command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;do_umount " + path) -} - -func (d *diskService) GetSerialAll() []model2.SerialDisk { - var m []model2.SerialDisk - d.db.Find(&m) - return m -} - -func NewDiskService(db *gorm.DB) DiskService { - return &diskService{db: db} -} diff --git a/service/docker.go b/service/docker.go index 9fe885f..812fb8a 100644 --- a/service/docker.go +++ b/service/docker.go @@ -59,6 +59,7 @@ type DockerService interface { DockerImageInfo(image string) (types.ImageInspect, error) GetNetWorkNameByNetWorkID(id string) (string, error) ContainerExecShell(container_id string) string + GetDockerInfo() (types.Info, error) } type dockerService struct { @@ -94,7 +95,7 @@ func (ds *dockerService) ContainerExecShell(container_id string) string { return exec.ID } -//创建默认网络 +// 创建默认网络 func DockerNetwork() { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -109,7 +110,7 @@ func DockerNetwork() { cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{}) } -//根据网络id获取网络名 +// 根据网络id获取网络名 func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) { cli, _ := client2.NewClientWithOpts(client2.FromEnv) defer cli.Close() @@ -122,7 +123,7 @@ func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) { return "", err } -//拉取镜像 +// 拉取镜像 func DockerPull() { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -141,7 +142,7 @@ func DockerPull() { } -//拉取镜像 +// 拉取镜像 func DockerEx() { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -292,7 +293,7 @@ func DockerLogs() { //正式内容 -//检查镜像是否存在 +// 检查镜像是否存在 func (ds *dockerService) IsExistImage(imageName string) bool { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -311,7 +312,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool { return false } -//安装镜像 +// 安装镜像 func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -365,12 +366,12 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c return container.ID, err } -//param imageName 镜像名称 -//param containerDbId 数据库的id -//param port 容器内部主端口 -//param mapPort 容器主端口映射到外部的端口 -//param tcp 容器其他tcp端口 -//param udp 容器其他udp端口 +// param imageName 镜像名称 +// param containerDbId 数据库的id +// param port 容器内部主端口 +// param mapPort 容器主端口映射到外部的端口 +// param tcp 容器其他tcp端口 +// param udp 容器其他udp端口 func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) { if len(m.NetworkModel) == 0 { m.NetworkModel = "bridge" @@ -581,7 +582,7 @@ func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id return containerDb.ID, err } -//删除容器 +// 删除容器 func (ds *dockerService) DockerContainerRemove(name string, update bool) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -605,7 +606,7 @@ func (ds *dockerService) DockerContainerRemove(name string, update bool) error { return err } -//删除镜像 +// 删除镜像 func (ds *dockerService) DockerImageRemove(name string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -653,7 +654,7 @@ Loop: return err } -//停止镜像 +// 停止镜像 func (ds *dockerService) DockerContainerStop(id string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -664,7 +665,7 @@ func (ds *dockerService) DockerContainerStop(id string) error { return err } -//启动容器 +// 启动容器 func (ds *dockerService) DockerContainerStart(name string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -675,7 +676,7 @@ func (ds *dockerService) DockerContainerStart(name string) error { return err } -//查看日志 +// 查看日志 func (ds *dockerService) DockerContainerLog(name string) (string, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -714,7 +715,7 @@ func DockerContainerStats1() error { return nil } -//获取容器状态 +// 获取容器状态 func (ds *dockerService) DockerContainerStats(name string) (string, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -733,7 +734,7 @@ func (ds *dockerService) DockerContainerStats(name string) (string, error) { return string(sts), nil } -//备份容器 +// 备份容器 func (ds *dockerService) DockerContainerCommit(name string) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -778,7 +779,7 @@ func (ds *dockerService) DockerListByImage(image, version string) (*types.Contai return &containers[0], nil } -//获取容器详情 +// 获取容器详情 func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) @@ -793,13 +794,13 @@ func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, return &d, nil } -//更新容器 -//param shares cpu优先级 -//param containerDbId 数据库的id -//param port 容器内部主端口 -//param mapPort 容器主端口映射到外部的端口 -//param tcp 容器其他tcp端口 -//param udp 容器其他udp端口 +// 更新容器 +// param shares cpu优先级 +// param containerDbId 数据库的id +// param port 容器内部主端口 +// param mapPort 容器主端口映射到外部的端口 +// param tcp 容器其他tcp端口 +// param udp 容器其他udp端口 func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -834,9 +835,9 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id return } -//更新容器名称 -//param name 容器名称 -//param id 老的容器名称 +// 更新容器名称 +// param name 容器名称 +// param id 老的容器名称 func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -851,7 +852,7 @@ func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) return } -//获取网络列表 +// 获取网络列表 func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -863,6 +864,17 @@ func NewDockerService() DockerService { return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)} } +func (ds *dockerService) GetDockerInfo() (types.Info, error) { + cli, err := client2.NewClientWithOpts(client2.FromEnv) + if err != nil { + return types.Info{}, err + } + defer cli.Close() + + return cli.Info(context.Background()) + +} + // ---------------------------------------test------------------------------------ //func ServiceCreate() { // cli, err := client2.NewClientWithOpts(client2.FromEnv) diff --git a/service/model/o_disk.go b/service/model/o_disk.go deleted file mode 100644 index 1121e87..0000000 --- a/service/model/o_disk.go +++ /dev/null @@ -1,25 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2021-12-07 17:14:41 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-17 18:46:43 - * @FilePath: /CasaOS/service/model/o_disk.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package model - -//SerialAdvanced Technology Attachment (STAT) -type SerialDisk struct { - Id uint `gorm:"column:id;primary_key" json:"id"` - UUID string `json:"uuid"` - Path string `json:"path"` - State int `json:"state"` - MountPoint string `json:"mount_point"` - CreatedAt int64 `json:"created_at"` -} - -func (p *SerialDisk) TableName() string { - return "o_disk" -} diff --git a/service/notify.go b/service/notify.go index fe93d83..05d3162 100644 --- a/service/notify.go +++ b/service/notify.go @@ -31,11 +31,9 @@ type NotifyServer interface { SendNetInfoBySocket(netList []model2.IOCountersStat) SendCPUInfoBySocket(cpu map[string]interface{}) SendMemInfoBySocket(mem map[string]interface{}) - SendUSBInfoBySocket(list []model2.DriveUSB) - SendDiskInfoBySocket(disk model2.Summary) SendFileOperateNotify(nowSend bool) SendInstallAppBySocket(app notify.Application) - SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) + SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) SendStorageBySocket(message notify.StorageMessage) SendNotify(path string, message map[string]interface{}) SettingSystemTempData(message map[string]interface{}) @@ -81,7 +79,7 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) { NotifyMsg <- notify } -func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) { +func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) { body := make(map[string]interface{}) @@ -263,38 +261,6 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) { } -func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) { - body := make(map[string]interface{}) - body["data"] = disk - - msg := gosf.Message{} - msg.Body = body - msg.Success = true - msg.Text = "sys_disk" - - notify := notify.Message{} - notify.Path = "sys_disk" - notify.Msg = msg - - NotifyMsg <- notify -} - -func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) { - body := make(map[string]interface{}) - body["data"] = list - - msg := gosf.Message{} - msg.Body = body - msg.Success = true - msg.Text = "sys_usb" - - notify := notify.Message{} - notify.Path = "sys_usb" - notify.Msg = msg - - NotifyMsg <- notify -} - func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) { body := make(map[string]interface{}) body["data"] = mem diff --git a/service/service.go b/service/service.go index 16594b9..e2164c0 100644 --- a/service/service.go +++ b/service/service.go @@ -30,7 +30,6 @@ type Repository interface { //User() UserService Docker() DockerService Casa() CasaService - Disk() DiskService Notify() NotifyServer Rely() RelyService System() SystemService @@ -51,7 +50,6 @@ func NewService(db *gorm.DB, RuntimePath string) Repository { app: NewAppService(db), docker: NewDockerService(), casa: NewCasaService(), - disk: NewDiskService(db), notify: NewNotifyService(db), rely: NewRelyService(db), system: NewSystemService(), @@ -65,7 +63,6 @@ type store struct { app AppService docker DockerService casa CasaService - disk DiskService notify NotifyServer rely RelyService system SystemService @@ -107,7 +104,3 @@ func (c *store) Docker() DockerService { func (c *store) Casa() CasaService { return c.casa } - -func (c *store) Disk() DiskService { - return c.disk -} From 582f85c3ba58749d37db4006c688e3927eeb1640 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Fri, 16 Sep 2022 04:47:42 +0100 Subject: [PATCH 05/42] update http status --- common/notify.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/notify.go b/common/notify.go index 82d3394..a5cee48 100644 --- a/common/notify.go +++ b/common/notify.go @@ -36,7 +36,7 @@ func (n *notifyService) SendNotify(path string, message map[string]interface{}) return err } - if response.StatusCode != http.StatusCreated { + if response.StatusCode != http.StatusOK { return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") } return nil @@ -58,7 +58,7 @@ func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) e return err } - if response.StatusCode != http.StatusCreated { + if response.StatusCode != http.StatusOK { return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") } return nil From 84dfa7f5bfeebdfe6ec216555d17abd9d61fd5dd Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Mon, 19 Sep 2022 10:09:04 +0100 Subject: [PATCH 06/42] add share function to common --- common/share.go | 78 ++++++++++++++++++++++++++++++++++++++++++++ common/share_test.go | 14 ++++++++ 2 files changed, 92 insertions(+) create mode 100644 common/share.go create mode 100644 common/share_test.go diff --git a/common/share.go b/common/share.go new file mode 100644 index 0000000..a0da4b2 --- /dev/null +++ b/common/share.go @@ -0,0 +1,78 @@ +package common + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "path/filepath" + "strings" +) + +const ( + APICasaOSShare = "/v1/samba/shares" +) + +type ShareService interface { + DeleteShare(id string) error +} +type shareService struct { + address string +} + +func (n *shareService) DeleteShare(id string) error { + url := strings.TrimSuffix(n.address, "/") + APICasaOSShare + "/" + id + fmt.Println(url) + message := "{}" + body, err := json.Marshal(message) + if err != nil { + return err + } + + client := &http.Client{} + + // Create request + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(body)) + if err != nil { + return err + } + + // Fetch Request + response, err := client.Do(req) + if err != nil { + return err + } + defer response.Body.Close() + + if response.StatusCode != http.StatusOK { + return errors.New("failed to send share (status code: " + fmt.Sprint(response.StatusCode) + ")") + } + return nil + +} + +func NewShareService(runtimePath string) (ShareService, error) { + casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename) + + buf, err := os.ReadFile(casaosAddressFile) + if err != nil { + return nil, err + } + + address := string(buf) + + response, err := http.Get(address + "/ping") + if err != nil { + return nil, err + } + + if response.StatusCode != 200 { + return nil, errors.New("failed to ping casaos service") + } + + return &shareService{ + address: address, + }, nil +} diff --git a/common/share_test.go b/common/share_test.go new file mode 100644 index 0000000..ce79e03 --- /dev/null +++ b/common/share_test.go @@ -0,0 +1,14 @@ +package common + +import "testing" + +func TestDeleteShare(t *testing.T) { + share, err := NewShareService("/var/run/casaos") + if err != nil { + t.Fatal(err) + } + err = share.DeleteShare("1") + if err != nil { + t.Fatal(err) + } +} From 4bace9b16a748ad2e7dbd8576b88635c5a9cd99e Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Wed, 28 Sep 2022 16:13:42 +0100 Subject: [PATCH 07/42] remove temp path --- .gitignore | 3 ++- .../migration/script.d/03-migrate-casaos.sh | 7 ++++--- build/sysroot/etc/casaos/casaos.conf.sample | 1 - conf/conf.conf.sample | 1 - model/sys_common.go | 11 +++++------ pkg/config/init.go | 13 +++++-------- route/v1/docker.go | 2 +- route/v1/file.go | 8 +++++--- service/casa.go | 8 -------- service/docker.go | 17 ++++++++++------- 10 files changed, 32 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 51d11d0..411aba3 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ __debug_bin main github.com .all-contributorsrc -dist \ No newline at end of file +dist +CasaOS \ No newline at end of file diff --git a/build/scripts/migration/script.d/03-migrate-casaos.sh b/build/scripts/migration/script.d/03-migrate-casaos.sh index ba64e4d..a48c437 100644 --- a/build/scripts/migration/script.d/03-migrate-casaos.sh +++ b/build/scripts/migration/script.d/03-migrate-casaos.sh @@ -60,8 +60,8 @@ BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../.. SOURCE_ROOT=${BUILD_PATH}/sysroot APP_NAME="casaos" -# APP_NAME_FORMAL="CasaOS" -APP_NAME_FORMAL="casaos-alpha" +APP_NAME_FORMAL="CasaOS" +#APP_NAME_FORMAL="casaos-alpha" # check if migration is needed SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin @@ -153,7 +153,8 @@ pushd "${MIGRATION_SERVICE_DIR}" continue fi - MIGRATION_TOOL_URL=https://github.com/LinkLeong/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz + # MIGRATION_TOOL_URL=http://192.168.2.197:8000/v1/package/migration?type=release&name="${APP_NAME_FORMAL}"&version=${VER2}&arch=${ARCH} + MIGRATION_TOOL_URL=https://github.com/IceWhaleTech/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz echo "Dowloading ${MIGRATION_TOOL_URL}..." curl -sL -O "${MIGRATION_TOOL_URL}" done diff --git a/build/sysroot/etc/casaos/casaos.conf.sample b/build/sysroot/etc/casaos/casaos.conf.sample index 3e64508..e51f0fa 100644 --- a/build/sysroot/etc/casaos/casaos.conf.sample +++ b/build/sysroot/etc/casaos/casaos.conf.sample @@ -11,7 +11,6 @@ DateFormat = 2006-01-02 DBPath = /var/lib/casaos ShellPath = /usr/share/casaos/shell UserDataPath = /var/lib/casaos/conf -TempPath = /var/lib/casaos/temp [server] RunMode = release diff --git a/conf/conf.conf.sample b/conf/conf.conf.sample index 5ce1d0e..1364418 100644 --- a/conf/conf.conf.sample +++ b/conf/conf.conf.sample @@ -11,7 +11,6 @@ DateFormat = 2006-01-02 DBPath = /var/lib/casaos ShellPath = /usr/share/casaos/shell UserDataPath = /var/lib/casaos/conf -TempPath = /var/lib/casaos/temp [server] RunMode = release diff --git a/model/sys_common.go b/model/sys_common.go index 1a78867..73316b0 100644 --- a/model/sys_common.go +++ b/model/sys_common.go @@ -12,12 +12,12 @@ package model import "time" -//系统配置 +// 系统配置 type SysInfoModel struct { Name string //系统名称 } -//服务配置 +// 服务配置 type ServerModel struct { HttpPort string RunMode string @@ -28,7 +28,7 @@ type ServerModel struct { SocketPort string } -//服务配置 +// 服务配置 type APPModel struct { LogPath string LogSaveName string @@ -40,20 +40,19 @@ type APPModel struct { DateFormat string DBPath string ShellPath string - TempPath string } type CommonModel struct { RuntimePath string } -//公共返回模型 +// 公共返回模型 type Result struct { Success int `json:"success" example:"200"` Message string `json:"message" example:"ok"` Data interface{} `json:"data" example:"返回结果"` } -//redis配置文件 +// redis配置文件 type RedisModel struct { Host string Password string diff --git a/pkg/config/init.go b/pkg/config/init.go index c79d71f..b2de00f 100644 --- a/pkg/config/init.go +++ b/pkg/config/init.go @@ -23,17 +23,17 @@ import ( "github.com/go-ini/ini" ) -//系统配置 +// 系统配置 var SysInfo = &model.SysInfoModel{} -//用户相关 +// 用户相关 var AppInfo = &model.APPModel{} var CommonInfo = &model.CommonModel{} //var RedisInfo = &model.RedisModel{} -//server相关 +// server相关 var ServerInfo = &model.ServerModel{} var SystemConfigInfo = &model.SystemConfig{} @@ -44,7 +44,7 @@ var FileSettingInfo = &model.FileSetting{} var Cfg *ini.File -//初始化设置,获取系统的部分信息。 +// 初始化设置,获取系统的部分信息。 func InitSetup(config string) { var configDir = USERCONFIGURL @@ -86,9 +86,6 @@ func InitSetup(config string) { if len(AppInfo.UserDataPath) == 0 { AppInfo.UserDataPath = "/var/lib/casaos/conf" } - if len(AppInfo.TempPath) == 0 { - AppInfo.TempPath = "/var/lib/casaos/temp" - } if len(CommonInfo.RuntimePath) == 0 { CommonInfo.RuntimePath = "/var/run/casaos" } @@ -97,7 +94,7 @@ func InitSetup(config string) { } -//映射 +// 映射 func mapTo(section string, v interface{}) { err := Cfg.Section(section).MapTo(v) if err != nil { diff --git a/route/v1/docker.go b/route/v1/docker.go index 684ca75..60d33a3 100644 --- a/route/v1/docker.go +++ b/route/v1/docker.go @@ -761,7 +761,7 @@ func ChangAppState(c *gin.Context) { func ContainerLog(c *gin.Context) { appId := c.Param("id") log, _ := service.MyService.Docker().DockerContainerLog(appId) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: log}) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(log)}) } // @Summary 获取容器状态 diff --git a/route/v1/file.go b/route/v1/file.go index 548ee4a..396074d 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -16,7 +16,6 @@ import ( "sync" "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/service" @@ -267,6 +266,9 @@ func DirPath(c *gin.Context) { pathList := []model.Path{} for i := 0; i < len(info); i++ { + if info[i].Name == ".temp" && info[i].IsDir { + continue + } if _, ok := fileQueue[info[i].Path]; !ok { pathList = append(pathList, info[i]) } @@ -367,7 +369,7 @@ func GetFileUpload(c *gin.Context) { path := c.Query("path") dirPath := "" hash := file.GetHashByContent([]byte(fileName)) - tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/" + tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" if fileName != relative { dirPath = strings.TrimSuffix(relative, fileName) tempDir += dirPath @@ -406,7 +408,7 @@ func PostFileUpload(c *gin.Context) { c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return } - tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/" + tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" if fileName != relative { dirPath = strings.TrimSuffix(relative, fileName) diff --git a/service/casa.go b/service/casa.go index f5a71d3..4d80bf4 100644 --- a/service/casa.go +++ b/service/casa.go @@ -130,10 +130,6 @@ func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollec errr := json2.Unmarshal(results, &collection) if errr != nil { loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results))) - } else { - if collection.Version == o.GetCasaosVersion().Version { - return collection, err - } } head := make(map[string]string) @@ -204,10 +200,6 @@ func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error) err := json2.Unmarshal(results, &list) if err != nil { loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results))) - } else { - if list.Version == o.GetCasaosVersion().Version { - return list.Item, nil - } } item := []model.CategoryList{} head := make(map[string]string) diff --git a/service/docker.go b/service/docker.go index 812fb8a..f453c0b 100644 --- a/service/docker.go +++ b/service/docker.go @@ -52,7 +52,7 @@ type DockerService interface { DockerContainerStop(id string) error DockerContainerUpdateName(name, id string) (err error) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) - DockerContainerLog(name string) (string, error) + DockerContainerLog(name string) ([]byte, error) DockerContainerCommit(name string) DockerContainerList() []types.Container DockerNetworkModelList() []types.NetworkResource @@ -677,23 +677,26 @@ func (ds *dockerService) DockerContainerStart(name string) error { } // 查看日志 -func (ds *dockerService) DockerContainerLog(name string) (string, error) { +func (ds *dockerService) DockerContainerLog(name string) ([]byte, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { - return "", err + return []byte(""), err } defer cli.Close() - body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStderr: true, ShowStdout: true}) + //body, err := cli.ContainerAttach(context.Background(), name, types.ContainerAttachOptions{Logs: true, Stream: false, Stdin: false, Stdout: false, Stderr: false}) + body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) + if err != nil { - return "", err + return []byte(""), err } defer body.Close() content, err := ioutil.ReadAll(body) + //content, err := ioutil.ReadAll(body) if err != nil { - return "", err + return []byte(""), err } - return string(content), nil + return content, nil } func DockerContainerStats1() error { From d9c6a5c87588e742358f43cf556e151ba7d77c34 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 11:14:19 -0400 Subject: [PATCH 08/42] remove /DATA directory initialization - moved to local-storage (#578) --- cmd/migration-tool/main.go | 18 +++++++++++------- main.go | 30 +++++++++++++++--------------- pkg/config/update.go | 32 -------------------------------- 3 files changed, 26 insertions(+), 54 deletions(-) delete mode 100644 pkg/config/update.go diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go index 5f7c60b..93b065d 100644 --- a/cmd/migration-tool/main.go +++ b/cmd/migration-tool/main.go @@ -28,25 +28,29 @@ const ( casaosServiceName = "casaos.service" ) -var _logger *Logger -var sqliteDB *gorm.DB +var ( + _logger *Logger + sqliteDB *gorm.DB +) -var configFlag = "" -var dbFlag = "" +var ( + configFlag = "" + dbFlag = "" +) func init() { config.InitSetup(configFlag) - config.UpdateSetup() if len(dbFlag) == 0 { dbFlag = config.AppInfo.DBPath + "/db" } sqliteDB = sqlite.GetDb(dbFlag) - //gredis.GetRedisConn(config.RedisInfo), + // gredis.GetRedisConn(config.RedisInfo), service.MyService = service.NewService(sqliteDB, "") } + func main() { versionFlag := flag.Bool("v", false, "version") debugFlag := flag.Bool("d", true, "debug") @@ -113,6 +117,6 @@ func main() { selectedMigrationTool.PostMigrate() _logger.Info("casaos migration ok") - //panic(err) + // panic(err) } diff --git a/main.go b/main.go index f02afca..32b1c01 100644 --- a/main.go +++ b/main.go @@ -28,9 +28,11 @@ const LOCALHOST = "127.0.0.1" var sqliteDB *gorm.DB -var configFlag = flag.String("c", "", "config address") -var dbFlag = flag.String("db", "", "db path") -var versionFlag = flag.Bool("v", false, "version") +var ( + configFlag = flag.String("c", "", "config address") + dbFlag = flag.String("db", "", "db path") + versionFlag = flag.Bool("v", false, "version") +) func init() { flag.Parse() @@ -39,7 +41,6 @@ func init() { return } config.InitSetup(*configFlag) - config.UpdateSetup() loger.LogInit() if len(*dbFlag) == 0 { @@ -47,7 +48,7 @@ func init() { } sqliteDB = sqlite.GetDb(*dbFlag) - //gredis.GetRedisConn(config.RedisInfo), + // gredis.GetRedisConn(config.RedisInfo), service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath) @@ -60,7 +61,6 @@ func init() { // go service.LoopFriend() // go service.MyService.App().CheckNewImage() - } // @title casaOS API @@ -80,21 +80,21 @@ func main() { return } go route.SocketInit(service.NotifyMsg) - //model.Setup() - //gredis.Setup() + // model.Setup() + // gredis.Setup() r := route.InitRouter() - //service.SyncTask(sqliteDB) + // service.SyncTask(sqliteDB) cron2 := cron.New() - //every day execution + // every day execution err := cron2.AddFunc("0/5 * * * * *", func() { if service.ClientCount > 0 { - //route.SendNetINfoBySocket() - //route.SendCPUBySocket() - //route.SendMemBySocket() + // route.SendNetINfoBySocket() + // route.SendCPUBySocket() + // route.SendMemBySocket() // route.SendDiskBySocket() - //route.SendUSBBySocket() + // route.SendUSBBySocket() route.SendAllHardwareStatusBySocket() } }) @@ -123,7 +123,7 @@ func main() { } go func() { time.Sleep(time.Second * 2) - //v0.3.6 + // v0.3.6 if config.ServerInfo.HttpPort != "" { changePort := common.ChangePortRequest{} changePort.Port = config.ServerInfo.HttpPort diff --git a/pkg/config/update.go b/pkg/config/update.go deleted file mode 100644 index 7dbae82..0000000 --- a/pkg/config/update.go +++ /dev/null @@ -1,32 +0,0 @@ -package config - -import ( - "runtime" - - "github.com/IceWhaleTech/CasaOS/pkg/utils/file" -) - -//检查目录是否存在 -func mkdirDATAAll() { - sysType := runtime.GOOS - var dirArray []string - if sysType == "linux" { - dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"} - } - - if sysType == "windows" { - dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"} - } - if sysType == "darwin" { - dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"} - } - - for _, v := range dirArray { - file.IsNotExistMkDir(v) - } - -} - -func UpdateSetup() { - mkdirDATAAll() -} From 50d68f3f768d98781be280173c82882a25699799 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 12:21:44 -0400 Subject: [PATCH 09/42] update goreleaser configuration --- .goreleaser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 949e04f..690519d 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -117,7 +117,7 @@ builds: goarch: - arm goarm: - - "7" + - "7" archives: - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}" id: casaos @@ -159,9 +159,9 @@ changelog: # name_template: "v{{ .Version }}" release: github: - owner: LinkLeong - name: casaos-alpha + owner: IceWhaleTech + name: CasaOS draft: true prerelease: auto mode: replace - name_template: "v{{ .Version }}" \ No newline at end of file + name_template: "v{{ .Version }}" From ec7f6573ad5a3efb611107edc66554a6724145c6 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 17:56:28 -0400 Subject: [PATCH 10/42] wip --- .../usr/lib/systemd/system/casaos.service | 3 ++- go.mod | 1 + main.go | 24 ++++++++++++------- types/system.go | 19 +++++++-------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/build/sysroot/usr/lib/systemd/system/casaos.service b/build/sysroot/usr/lib/systemd/system/casaos.service index 249d72c..aa7ad32 100644 --- a/build/sysroot/usr/lib/systemd/system/casaos.service +++ b/build/sysroot/usr/lib/systemd/system/casaos.service @@ -1,12 +1,13 @@ [Unit] After=casaos-gateway.service ConditionFileNotEmpty=/etc/casaos/casaos.conf -Description=CasaOS Service +Description=CasaOS Main Service [Service] ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf PIDFile=/var/run/casaos/casaos.pid Restart=always +Type=notify [Install] WantedBy=multi-user.target diff --git a/go.mod b/go.mod index b68d268..106f2ba 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109 github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect github.com/containerd/containerd v1.5.7 // indirect + github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e github.com/disintegration/imaging v1.6.2 github.com/docker/distribution v2.8.0+incompatible // indirect github.com/docker/docker v20.10.7+incompatible diff --git a/main.go b/main.go index 32b1c01..ede006d 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ import ( "github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/types" + "github.com/coreos/go-systemd/daemon" "go.uber.org/zap" "github.com/robfig/cron" @@ -135,14 +136,6 @@ func main() { } }() - // s := &http.Server{ - // Addr: listener.Addr().String(), //fmt.Sprintf(":%v", config.ServerInfo.HttpPort), - // Handler: r, - // ReadTimeout: 60 * time.Second, - // WriteTimeout: 60 * time.Second, - // MaxHeaderBytes: 1 << 20, - // } - // s.ListenAndServe() urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url") err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()) if err != nil { @@ -152,7 +145,20 @@ func main() { ) } - err = http.Serve(listener, r) + if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { + loger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err)) + } else if supported { + loger.Info("Notified systemd that casaos main service is ready") + } else { + loger.Info("This process is not running as a systemd service.") + } + + s := &http.Server{ + Handler: r, + ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec) + } + + err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec) if err != nil { panic(err) } diff --git a/types/system.go b/types/system.go index 24ef182..e77a7d6 100644 --- a/types/system.go +++ b/types/system.go @@ -1,15 +1,14 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2022-02-17 18:53:22 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-09-06 14:27:42 - * @FilePath: /CasaOS/types/system.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. +/*@Author: LinkLeong link@icewhale.com + *@Date: 2022-02-17 18:53:22 + *@LastEditors: LinkLeong + *@LastEditTime: 2022-09-06 14:27:42 + *@FilePath: /CasaOS/types/system.go + *@Description: + *@Website: https://www.casaos.io + *Copyright (c) 2022 by icewhale, All Rights Reserved. */ package types -const CURRENTVERSION = "0.3.6" +const CURRENTVERSION = "0.3.7" const BODY = " " From 3787c7bf990d6de6bd5f6cddd116e7daa973c37f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 18:19:31 -0400 Subject: [PATCH 11/42] change service type to notify for systemd so its status is OK only when service is initialized successfully --- build/scripts/setup/service.d/casaos/debian/setup-casaos.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh index a13b6e1..e083373 100644 --- a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh +++ b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh @@ -40,6 +40,6 @@ else echo "Enabling service..." systemctl enable --force --no-ask-password "${APP_NAME}.service" - echo "Starting service..." - systemctl start --force --no-ask-password "${APP_NAME}.service" + #echo "Starting service..." + #systemctl start --force --no-ask-password "${APP_NAME}.service" fi \ No newline at end of file From a51bf70b793debd782cdfa5165257f33f729de0d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 29 Sep 2022 00:05:12 -0400 Subject: [PATCH 12/42] update CasaOS-Common to fix runtime error --- .goreleaser.debug.yaml | 167 +++++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 3 +- middleware/gin.go | 12 +-- 4 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 .goreleaser.debug.yaml diff --git a/.goreleaser.debug.yaml b/.goreleaser.debug.yaml new file mode 100644 index 0000000..885e3a0 --- /dev/null +++ b/.goreleaser.debug.yaml @@ -0,0 +1,167 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +project_name: casaos +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy +builds: + - id: casaos-amd64 + binary: build/sysroot/usr/bin/casaos + env: + - CGO_ENABLED=1 + - CC=x86_64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - amd64 + hooks: + post: + - find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest + - id: casaos-arm64 + binary: build/sysroot/usr/bin/casaos + env: + - CGO_ENABLED=1 + - CC=aarch64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm64 + hooks: + post: + - find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest + - id: casaos-arm-7 + binary: build/sysroot/usr/bin/casaos + env: + - CGO_ENABLED=1 + - CC=arm-linux-gnueabihf-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm + goarm: + - "7" + hooks: + post: + - find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest + - id: casaos-migration-tool-amd64 + binary: build/sysroot/usr/bin/casaos-migration-tool + main: ./cmd/migration-tool + env: + - CGO_ENABLED=1 + - CC=x86_64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - amd64 + - id: casaos-migration-tool-arm64 + binary: build/sysroot/usr/bin/casaos-migration-tool + main: ./cmd/migration-tool + env: + - CGO_ENABLED=1 + - CC=aarch64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm64 + - id: casaos-migration-tool-arm-7 + binary: build/sysroot/usr/bin/casaos-migration-tool + main: ./cmd/migration-tool + env: + - CGO_ENABLED=1 + - CC=arm-linux-gnueabihf-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm + goarm: + - "7" +archives: + - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}" + id: casaos + builds: + - casaos-amd64 + - casaos-arm64 + - casaos-arm-7 + replacements: + arm: arm-7 + files: + - build/**/* + - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}" + id: casaos-migration-tool + builds: + - casaos-migration-tool-amd64 + - casaos-migration-tool-arm64 + - casaos-migration-tool-arm-7 + replacements: + arm: arm-7 + files: + - build/sysroot/etc/**/* +checksum: + name_template: "checksums.txt" +snapshot: + name_template: "{{ incpatch .Version }}" +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" +# release: +# github: +# owner: IceWhaleTech +# name: CasaOS +# draft: true +# prerelease: auto +# mode: replace +# name_template: "v{{ .Version }}" +release: + github: + owner: IceWhaleTech + name: CasaOS + draft: true + prerelease: auto + mode: replace + name_template: "v{{ .Version }}" diff --git a/go.mod b/go.mod index 106f2ba..6c454be 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d - github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220901034123-ca130f6b5ce9 + github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8 github.com/IceWhaleTech/CasaOS-Gateway v0.3.6 github.com/Microsoft/go-winio v0.5.0 // indirect github.com/ambelovsky/go-structs v1.1.0 // indirect diff --git a/go.sum b/go.sum index 5baa719..0bf42e2 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,9 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU= github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220901034123-ca130f6b5ce9 h1:q4I/lSsCooxdd6LxinGy90y0n6V8EcaPBV1JCfpEnV4= github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220901034123-ca130f6b5ce9/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk= +github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8 h1:r8nhgQ6tnrn6ikXN9aLH/K4H4H64Nc0hZ6jyW2B22x0= +github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk= github.com/IceWhaleTech/CasaOS-Gateway v0.3.6 h1:2tQQo85+jzbbjqIsKKn77QlAA73bc7vZsVCFvWnK4mg= github.com/IceWhaleTech/CasaOS-Gateway v0.3.6/go.mod h1:hnZwGUzcOyiufMpVO7l3gu2gAm6Ws4TY4Nlj3kMshXA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= diff --git a/middleware/gin.go b/middleware/gin.go index d8fd836..a9b07b6 100644 --- a/middleware/gin.go +++ b/middleware/gin.go @@ -13,6 +13,7 @@ package middleware import ( "fmt" "net/http" + "runtime/debug" "strings" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" @@ -26,18 +27,18 @@ func Cors() gin.HandlerFunc { c.Header("Access-Control-Allow-Origin", "*") 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,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With") // 允许浏览器(客户端)可以解析的头部 (重要) c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") - //c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With") - //设置缓存时间 + // c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With") + // 设置缓存时间 c.Header("Access-Control-Max-Age", "172800") c.Header("Access-Control-Allow-Credentials", "true") c.Set("Content-Type", "application/json") //} - //允许类型校验 + // 允许类型校验 if method == "OPTIONS" { c.JSON(http.StatusOK, "ok!") } @@ -45,18 +46,19 @@ func Cors() gin.HandlerFunc { defer func() { if err := recover(); err != nil { fmt.Println(err) + debug.PrintStack() } }() c.Next() } } + func WriteLog() gin.HandlerFunc { return func(c *gin.Context) { if !strings.Contains(c.Request.URL.String(), "password") { loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method)) c.Next() } - } } From 42ebd5f32561ee574468037c7316944545cf1e17 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Oct 2022 00:19:02 -0400 Subject: [PATCH 13/42] wip --- model/docker.go | 6 +- pkg/docker/helper.go | 72 ++++++++++----------- pkg/utils/command/command_helper.go | 13 ++-- pkg/utils/file/file.go | 39 +++++++----- route/route.go | 63 +++++++++--------- route/v1/app.go | 99 ++++++++++++++++++++--------- 6 files changed, 170 insertions(+), 122 deletions(-) diff --git a/model/docker.go b/model/docker.go index 20b68cc..34412cd 100644 --- a/model/docker.go +++ b/model/docker.go @@ -17,6 +17,8 @@ type DockerStatsModel struct { Previous interface{} `json:"previous"` } -type DeckerDaemonModel struct { - Graph string `json:"graph"` +// reference - https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file +type DockerDaemonConfigurationModel struct { + // e.g. `/var/lib/docker` + Root string `json:"data-root,omitempty"` } diff --git a/pkg/docker/helper.go b/pkg/docker/helper.go index be76b7d..0aef117 100644 --- a/pkg/docker/helper.go +++ b/pkg/docker/helper.go @@ -15,7 +15,6 @@ import ( ) func NewSshClient(user, password string, port string) (*ssh.Client, error) { - // connet to ssh // addr = fmt.Sprintf("%s:%d", host, port) @@ -23,10 +22,10 @@ func NewSshClient(user, password string, port string) (*ssh.Client, error) { Timeout: time.Second * 5, User: user, HostKeyCallback: ssh.InsecureIgnoreHostKey(), - //HostKeyCallback: , - //HostKeyCallback: hostKeyCallBackFunc(h.Host), + // HostKeyCallback: , + // HostKeyCallback: hostKeyCallBackFunc(h.Host), } - //if h.Type == "password" { + // if h.Type == "password" { config.Auth = []ssh.AuthMethod{ssh.Password(password)} //} else { // config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)} @@ -90,11 +89,11 @@ func (w *wsBufferWriter) Write(p []byte) (int, error) { defer w.mu.Unlock() return w.buffer.Write(p) } + func (s *SshConn) Close() { if s.Session != nil { s.Session.Close() } - } const ( @@ -102,16 +101,15 @@ const ( wsMsgResize = "resize" ) -//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin +// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { - //tells other go routine quit + // tells other go routine quit username := "" for { - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { - return "" } @@ -125,8 +123,8 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { //} switch msgObj.Type { case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) decodeBytes := []byte(msgObj.Cmd) if msgObj.Cmd == "\u007f" { if len(username) == 0 { @@ -144,7 +142,7 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil { logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed") } - //write input cmd to log buffer + // write input cmd to log buffer if _, err := logBuff.Write(decodeBytes); err != nil { logrus.WithError(err).Error("write received cmd into log buffer failed") } @@ -154,11 +152,11 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { } func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { - //tells other go routine quit + // tells other go routine quit password := "" for { - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { logrus.WithError(err).Error("reading webSocket message failed") @@ -175,8 +173,8 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string //} switch msgObj.Type { case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) if msgObj.Cmd == "\r" { return password } @@ -194,16 +192,16 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string } } -//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin +// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) { - //tells other go routine quit + // tells other go routine quit defer setQuit(exitCh) for { select { case <-exitCh: return default: - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { logrus.WithError(err).Error("reading webSocket message failed") @@ -227,15 +225,15 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe switch msgObj.Type { case wsMsgResize: - //handle xterm.js size change + // handle xterm.js size change if msgObj.Cols > 0 && msgObj.Rows > 0 { if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil { logrus.WithError(err).Error("ssh pty change windows size failed") } } case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) decodeBytes := []byte(msgObj.Cmd) if err != nil { logrus.WithError(err).Error("websock cmd string base64 decoding failed") @@ -243,7 +241,7 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil { logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed") } - //write input cmd to log buffer + // write input cmd to log buffer if _, err := logBuff.Write(decodeBytes); err != nil { logrus.WithError(err).Error("write received cmd into log buffer failed") } @@ -253,17 +251,17 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe } func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) { - //tells other go routine quit - //defer setQuit(exitCh) + // tells other go routine quit + // defer setQuit(exitCh) - //every 120ms write combine output bytes into websocket response + // every 120ms write combine output bytes into websocket response tick := time.NewTicker(time.Millisecond * time.Duration(120)) - //for range time.Tick(120 * time.Millisecond){} + // for range time.Tick(120 * time.Millisecond){} defer tick.Stop() for { select { case <-tick.C: - //write combine output bytes into websocket response + // write combine output bytes into websocket response if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil { logrus.WithError(err).Error("ssh sending combo output to webSocket failed") return @@ -273,6 +271,7 @@ func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) } } } + func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error { if w.buffer.Len() != 0 { err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes()) @@ -284,16 +283,16 @@ func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error { return nil } -//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin +// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) { - //tells other go routine quit + // tells other go routine quit defer setQuit(exitCh) for { select { case <-exitCh: return default: - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { logrus.WithError(err).Error("reading webSocket message failed") @@ -317,15 +316,15 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit switch msgObj.Type { case wsMsgResize: - //handle xterm.js size change + // handle xterm.js size change if msgObj.Cols > 0 && msgObj.Rows > 0 { if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil { logrus.WithError(err).Error("ssh pty change windows size failed") } } case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) decodeBytes := []byte(msgObj.Cmd) if err != nil { logrus.WithError(err).Error("websock cmd string base64 decoding failed") @@ -333,7 +332,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil { logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed") } - //write input cmd to log buffer + // write input cmd to log buffer if _, err := logBuff.Write(decodeBytes); err != nil { logrus.WithError(err).Error("write received cmd into log buffer failed") } @@ -341,6 +340,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit } } } + func (ssConn *SshConn) SessionWait(quitChan chan bool) { if err := ssConn.Session.Wait(); err != nil { logrus.WithError(err).Error("ssh session wait failed") @@ -395,7 +395,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) { if err = json2.Unmarshal(p, &msgObj); err != nil { writer.Write(p) } else if msgObj.Type == wsMsgResize { - //writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r")) + // writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r")) } } } diff --git a/pkg/utils/command/command_helper.go b/pkg/utils/command/command_helper.go index 9a2fded..a47b288 100644 --- a/pkg/utils/command/command_helper.go +++ b/pkg/utils/command/command_helper.go @@ -35,8 +35,8 @@ func ExecResultStrArray(cmdStr string) []string { fmt.Println(err) return nil } - //str, err := ioutil.ReadAll(stdout) - var networklist = []string{} + // str, err := ioutil.ReadAll(stdout) + networklist := []string{} outputBuf := bufio.NewReader(stdout) for { output, _, err := outputBuf.ReadLine() @@ -54,6 +54,8 @@ func ExecResultStrArray(cmdStr string) []string { func ExecResultStr(cmdStr string) string { cmd := exec.Command("/bin/bash", "-c", cmdStr) + println(cmd.String()) + stdout, err := cmd.StdoutPipe() if err != nil { fmt.Println(err) @@ -73,7 +75,7 @@ func ExecResultStr(cmdStr string) string { return string(str) } -//执行 lsblk 命令 +// 执行 lsblk 命令 func ExecLSBLK() []byte { output, err := exec.Command("lsblk", "-O", "-J", "-b").Output() if err != nil { @@ -83,7 +85,7 @@ func ExecLSBLK() []byte { return output } -//执行 lsblk 命令 +// 执行 lsblk 命令 func ExecLSBLKByPath(path string) []byte { output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output() if err != nil { @@ -93,7 +95,7 @@ func ExecLSBLKByPath(path string) []byte { return output } -//exec smart +// exec smart func ExecSmartCTLByPath(path string) []byte { timeout := 3 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) @@ -107,6 +109,5 @@ func ExecSmartCTLByPath(path string) []byte { } func ExecEnabledSMART(path string) { - exec.Command("smartctl", "-s on", path).Output() } diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go index b08dcda..e7fed65 100644 --- a/pkg/utils/file/file.go +++ b/pkg/utils/file/file.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "log" "mime/multipart" @@ -60,7 +61,7 @@ func MkDir(src string) error { if err != nil { return err } - os.Chmod(src, 0777) + os.Chmod(src, 0o777) return nil } @@ -103,7 +104,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) { return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err) } - f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) + f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644) if err != nil { return nil, fmt.Errorf("Fail to OpenFile :%v", err) } @@ -113,7 +114,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) { // 判断所给路径文件/文件夹是否存在 func Exists(path string) bool { - _, err := os.Stat(path) //os.Stat获取文件信息 + _, err := os.Stat(path) // os.Stat获取文件信息 if err != nil { if os.IsExist(err) { return true @@ -147,7 +148,7 @@ func CreateFile(path string) error { } func CreateFileAndWriteContent(path string, content string) error { - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666) if err != nil { return err } @@ -163,7 +164,7 @@ func CreateFileAndWriteContent(path string, content string) error { // IsNotExistMkDir create a directory if it does not exist func IsNotExistCreateFile(src string) error { - if notExist := CheckNotExist(src); notExist == true { + if notExist := CheckNotExist(src); notExist { if err := CreateFile(src); err != nil { return err } @@ -267,7 +268,7 @@ func CopySingleFile(src, dst, style string) error { return os.Chmod(dst, srcinfo.Mode()) } -//Check for duplicate file names +// Check for duplicate file names func GetNoDuplicateFileName(fullPath string) string { path, fileName := filepath.Split(fullPath) fileSuffix := path2.Ext(fileName) @@ -293,7 +294,7 @@ func CopyDir(src string, dst string, style string) error { } return nil } - //dstPath := dst + // dstPath := dst lastPath := src[strings.LastIndex(src, "/")+1:] dst += "/" + lastPath // for i := 0; Exists(dst); i++ { @@ -314,7 +315,7 @@ func CopyDir(src string, dst string, style string) error { } for _, fd := range fds { srcfp := path.Join(src, fd.Name()) - dstfp := dst //path.Join(dst, fd.Name()) + dstfp := dst // path.Join(dst, fd.Name()) if fd.IsDir() { if err = CopyDir(srcfp, dstfp, style); err != nil { @@ -336,10 +337,17 @@ func WriteToPath(data []byte, path, name string) error { } else { fullPath += "/" + name } - IsNotExistCreateFile(fullPath) + return WriteToFullPath(data, fullPath, 0o666) +} + +func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error { + if err := IsNotExistCreateFile(fullPath); err != nil { + return err + } + file, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, - 0666, + perm, ) if err != nil { return err @@ -350,16 +358,15 @@ func WriteToPath(data []byte, path, name string) error { return err } -//最终拼接 +// 最终拼接 func SpliceFiles(dir, path string, length int, startPoint int) error { - fullPath := path IsNotExistCreateFile(fullPath) file, _ := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, - 0666, + 0o666, ) defer file.Close() bufferedWriter := bufio.NewWriter(file) @@ -380,7 +387,6 @@ func SpliceFiles(dir, path string, length int, startPoint int) error { } func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) { - switch t { case "zip", "": return ".zip", archiver.NewZip(), nil @@ -400,8 +406,8 @@ func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) { return "", nil, errors.New("format not implemented") } } -func AddFile(ar archiver.Writer, path, commonPath string) error { +func AddFile(ar archiver.Writer, path, commonPath string) error { info, err := os.Stat(path) if err != nil { return err @@ -447,6 +453,7 @@ func AddFile(ar archiver.Writer, path, commonPath string) error { return nil } + func CommonPrefix(sep byte, paths ...string) string { // Handle special cases. switch len(paths) { @@ -513,7 +520,7 @@ func GetFileOrDirSize(path string) (int64, error) { return fileInfo.Size(), nil } -//getFileSize get file size by path(B) +// getFileSize get file size by path(B) func DirSizeB(path string) (int64, error) { var size int64 err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { diff --git a/route/route.go b/route/route.go index 110fd69..8b254f8 100644 --- a/route/route.go +++ b/route/route.go @@ -11,7 +11,6 @@ import ( ) func InitRouter() *gin.Engine { - r := gin.Default() r.Use(middleware.Cors()) @@ -35,7 +34,7 @@ func InitRouter() *gin.Engine { // r.GET("/v1/users/image", v1.GetUserImage) // r.GET("/v1/users/status", v1.GetUserStatus) //init/check - //r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check + // r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port @@ -73,7 +72,7 @@ func InitRouter() *gin.Engine { v1AppsGroup := v1Group.Group("/apps") v1AppsGroup.Use() { - v1AppsGroup.GET("", v1.AppList) //list + v1AppsGroup.GET("", v1.AppList) // list v1AppsGroup.GET("/:id", v1.AppInfo) } v1ContainerGroup := v1Group.Group("/container") @@ -84,24 +83,24 @@ func InitRouter() *gin.Engine { v1ContainerGroup.GET("/usage", v1.AppUsageList) v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id - v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config + v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) // app/install/config - v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress + v1ContainerGroup.GET("/:id/state", v1.GetContainerState) // app/state/:id ?state=install_progress // there are problems, temporarily do not deal with - v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id - v1ContainerGroup.POST("", v1.InstallApp) //app/install - //v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id + v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) // app/terminal/:id + v1ContainerGroup.POST("", v1.InstallApp) // app/install + // v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id - v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) //app/uninstall/:id - //Not used + v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) // app/uninstall/:id + // Not used v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate) - //Not used + // Not used v1ContainerGroup.POST("/share", v1.ShareAppFile) - v1ContainerGroup.GET("/info", v1.GetcontainerInfo) - v1ContainerGroup.PUT("/info", v1.PutcontainerInfo) + v1ContainerGroup.GET("/info", v1.GetDockerDaemonConfiguration) + v1ContainerGroup.PUT("/info", v1.PutDockerDaemonConfiguration) } v1AppCategoriesGroup := v1Group.Group("/app-categories") @@ -113,19 +112,19 @@ func InitRouter() *gin.Engine { v1SysGroup := v1Group.Group("/sys") v1SysGroup.Use() { - v1SysGroup.GET("/version", v1.GetSystemCheckVersion) //version/check + v1SysGroup.GET("/version", v1.GetSystemCheckVersion) // version/check v1SysGroup.POST("/update", v1.SystemUpdate) - v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info + v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) // hardware/info v1SysGroup.GET("/wsssh", v1.WsSsh) v1SysGroup.POST("/ssh-login", v1.PostSshLogin) - //v1SysGroup.GET("/config", v1.GetSystemConfig) //delete - //v1SysGroup.POST("/config", v1.PostSetSystemConfig) - v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs - //v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete - //v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete + // v1SysGroup.GET("/config", v1.GetSystemConfig) //delete + // v1SysGroup.POST("/config", v1.PostSetSystemConfig) + v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) // error/logs + // v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete + // v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete v1SysGroup.POST("/stop", v1.PostKillCasaOS) @@ -141,31 +140,31 @@ func InitRouter() *gin.Engine { v1SysGroup.GET("/server-info", nil) v1SysGroup.PUT("/server-info", nil) v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus) - //v1SysGroup.GET("/port", v1.GetCasaOSPort) - //v1SysGroup.PUT("/port", v1.PutCasaOSPort) + // v1SysGroup.GET("/port", v1.GetCasaOSPort) + // v1SysGroup.PUT("/port", v1.PutCasaOSPort) v1SysGroup.GET("/proxy", v1.GetSystemProxy) } v1PortGroup := v1Group.Group("/port") v1PortGroup.Use() { - v1PortGroup.GET("/", v1.GetPort) //app/port - v1PortGroup.GET("/state/:port", v1.PortCheck) //app/check/:port + v1PortGroup.GET("/", v1.GetPort) // app/port + v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port } v1FileGroup := v1Group.Group("/file") v1FileGroup.Use() { - v1FileGroup.GET("", v1.GetDownloadSingleFile) //download/:path + v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path v1FileGroup.POST("", v1.PostCreateFile) v1FileGroup.PUT("", v1.PutFileContent) v1FileGroup.PUT("/name", v1.RenamePath) - //file/rename - v1FileGroup.GET("/content", v1.GetFilerContent) //file/read + // file/rename + v1FileGroup.GET("/content", v1.GetFilerContent) // file/read - //File uploads need to be handled separately, and will not be modified here + // File uploads need to be handled separately, and will not be modified here v1FileGroup.POST("/upload", v1.PostFileUpload) v1FileGroup.GET("/upload", v1.GetFileUpload) - //v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) + // v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) } v1FolderGroup := v1Group.Group("/folder") v1FolderGroup.Use() @@ -178,9 +177,9 @@ func InitRouter() *gin.Engine { v1BatchGroup.Use() { - v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete + v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir) - v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate + v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate v1BatchGroup.GET("", v1.GetDownloadFile) } v1ImageGroup := v1Group.Group("/image") @@ -211,7 +210,7 @@ func InitRouter() *gin.Engine { v1NotifyGroup.Use() { v1NotifyGroup.POST("/:path", v1.PostNotifyMessage) - //merge to system + // merge to system v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify) } } diff --git a/route/v1/app.go b/route/v1/app.go index cc2ee00..dec60ef 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -2,8 +2,9 @@ package v1 import ( "encoding/json" - "fmt" "io/ioutil" + "net/http" + "path/filepath" "strconv" "github.com/IceWhaleTech/CasaOS/model" @@ -16,6 +17,10 @@ import ( "github.com/gin-gonic/gin" ) +const ( + dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json" +) + // @Summary 获取远程列表 // @Produce application/json // @Accept application/json @@ -29,8 +34,7 @@ import ( // @Success 200 {string} string "ok" // @Router /app/list [get] func AppList(c *gin.Context) { - - //service.MyService.Docker().DockerContainerCommit("test2") + // service.MyService.Docker().DockerContainerCommit("test2") index := c.DefaultQuery("index", "1") size := c.DefaultQuery("size", "10000") @@ -139,7 +143,7 @@ func MyAppList(c *gin.Context) { func AppUsageList(c *gin.Context) { list := service.MyService.App().GetHardwareUsage() c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list}) - //c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil}) + // c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil}) } // @Summary 应用详情 @@ -151,7 +155,6 @@ func AppUsageList(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /app/appinfo/{id} [get] func AppInfo(c *gin.Context) { - id := c.Param("id") language := c.GetHeader("Language") info, err := service.MyService.Casa().GetServerAppInfo(id, "", language) @@ -213,7 +216,7 @@ func AppInfo(c *gin.Context) { // return c1.Type < c2.Type // } - //sort + // sort // if info.NetworkModel != "host" { // sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts) // sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts) @@ -265,53 +268,89 @@ func ShareAppFile(c *gin.Context) { c.JSON(common_err.SUCCESS, json.RawMessage(content)) } -func GetcontainerInfo(c *gin.Context) { +func GetDockerDaemonConfiguration(c *gin.Context) { // info, err := service.MyService.Docker().GetDockerInfo() // 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 // } - daemon := model.DeckerDaemonModel{} + dockerConfig := model.DockerDaemonConfigurationModel{} data := make(map[string]interface{}, 1) data["docker_root_dir"] = "" - if file.Exists("/etc/docker/daemon.json") { - byteResult := file.ReadFullFile("/etc/docker/daemon.json") - err := json.Unmarshal(byteResult, &daemon) + + // TODO read dockerRootDir from /etc/casaos/casaos.conf + if file.Exists(dockerDaemonConfigurationFilePath) { + byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) + err := json.Unmarshal(byteResult, &dockerConfig) if err != nil { c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) return } - data["docker_root_dir"] = daemon.Graph + + if dockerConfig.Root != "" { + data["docker_root_dir"] = dockerConfig.Root + } else { + data["docker_root_dir"] = "/var/lib/docker" + } } c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) } -func PutcontainerInfo(c *gin.Context) { + +func PutDockerDaemonConfiguration(c *gin.Context) { js := make(map[string]interface{}) - err := c.BindJSON(&js) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + if err := c.BindJSON(&js); err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) return } - dockerRootDir := js["docker_root_dir"].(string) - daemon := model.DeckerDaemonModel{} - if file.Exists("/etc/docker/daemon.json") { - byteResult := file.ReadFullFile("/etc/docker/daemon.json") - err := json.Unmarshal(byteResult, &daemon) + + value, ok := js["docker_root_dir"] + if !ok { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "`docker_root_dir` should not empty"}) + return + } + + dockerConfig := model.DockerDaemonConfigurationModel{} + if file.Exists(dockerDaemonConfigurationFilePath) { + byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) + err := json.Unmarshal(byteResult, &dockerConfig) if err != nil { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err.Error()}) return } } - if !file.Exists(dockerRootDir) { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) + + dockerRootDir := value.(string) + if dockerRootDir == "/" { + dockerConfig.Root = "" // omitempty - empty string will not be serialized + } else { + if !file.Exists(dockerRootDir) { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) + return + } + + dockerConfig.Root = filepath.Join(dockerRootDir, "docker") + + if err := file.IsNotExistMkDir(dockerConfig.Root); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err.Error()}) + return + } + } + + byteMode, err := json.Marshal(dockerConfig) + if err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker config", Data: dockerConfig}) return } - daemon.Graph = dockerRootDir - byteMode, _ := json.Marshal(daemon) - file.WriteToPath(byteMode, "/etc/docker", "daemon.json") - fmt.Println(command.ExecResultStr("systemctl daemon-reload")) - fmt.Println(command.ExecResultStr("systemctl restart docker")) + if err := file.WriteToFullPath(byteMode, dockerDaemonConfigurationFilePath, 0o644); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err.Error()}) + return + } - c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) + // TODO also write dockerRootDir to /etc/casaos/casaos.conf + + println(command.ExecResultStr("systemctl daemon-reload")) + println(command.ExecResultStr("systemctl restart docker")) + + c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) } From d14381e6a2498c7a9bffa79c4e4927947e1237f7 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Thu, 8 Sep 2022 10:55:20 +0100 Subject: [PATCH 14/42] add send notify function --- .../migration/service.d/casaos/migration.list | 1 + cmd/migration-tool/log.go | 10 --- cmd/migration-tool/main.go | 1 + cmd/migration-tool/migration-034-035.go | 10 +-- cmd/migration-tool/migration-036.go | 74 +++++++++++++++++++ common/notify.go | 67 +++++++++++++++++ main.go | 14 +++- route/route.go | 9 ++- route/v1/docker.go | 2 +- route/v1/notiry.go | 16 ++++ service/notify.go | 16 ++++ 11 files changed, 202 insertions(+), 18 deletions(-) create mode 100644 cmd/migration-tool/migration-036.go create mode 100644 common/notify.go create mode 100644 route/v1/notiry.go diff --git a/build/scripts/migration/service.d/casaos/migration.list b/build/scripts/migration/service.d/casaos/migration.list index 2035e42..d3ce03f 100644 --- a/build/scripts/migration/service.d/casaos/migration.list +++ b/build/scripts/migration/service.d/casaos/migration.list @@ -1,3 +1,4 @@ LEGACY_WITHOUT_VERSION v0.3.6 v0.3.5 v0.3.6 v0.3.5.1 v0.3.6 +v0.3.6 v0.3.7 diff --git a/cmd/migration-tool/log.go b/cmd/migration-tool/log.go index e20da69..ed69983 100644 --- a/cmd/migration-tool/log.go +++ b/cmd/migration-tool/log.go @@ -1,13 +1,3 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2022-08-30 22:15:30 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-30 22:15:47 - * @FilePath: /CasaOS/cmd/migration-tool/log.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ package main import ( diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go index a09d5b8..5f7c60b 100644 --- a/cmd/migration-tool/main.go +++ b/cmd/migration-tool/main.go @@ -80,6 +80,7 @@ func main() { migrationTools := []interfaces.MigrationTool{ NewMigrationToolFor_035(), + NewMigrationToolFor_036(), } var selectedMigrationTool interfaces.MigrationTool diff --git a/cmd/migration-tool/migration-034-035.go b/cmd/migration-tool/migration-034-035.go index 4fa2ed3..3dfed60 100644 --- a/cmd/migration-tool/migration-034-035.go +++ b/cmd/migration-tool/migration-034-035.go @@ -25,9 +25,9 @@ import ( "github.com/IceWhaleTech/CasaOS/service" ) -type migrationTool struct{} +type migrationTool036 struct{} -func (u *migrationTool) IsMigrationNeeded() (bool, error) { +func (u *migrationTool036) IsMigrationNeeded() (bool, error) { majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() if err != nil { @@ -55,12 +55,12 @@ func (u *migrationTool) IsMigrationNeeded() (bool, error) { } -func (u *migrationTool) PreMigrate() error { +func (u *migrationTool036) PreMigrate() error { return nil } -func (u *migrationTool) Migrate() error { +func (u *migrationTool036) Migrate() error { if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { service.MyService.System().UpdateUSBAutoMount("False") @@ -173,7 +173,7 @@ func (u *migrationTool) Migrate() error { return nil } -func (u *migrationTool) PostMigrate() error { +func (u *migrationTool036) PostMigrate() error { return nil } diff --git a/cmd/migration-tool/migration-036.go b/cmd/migration-tool/migration-036.go new file mode 100644 index 0000000..b6d5410 --- /dev/null +++ b/cmd/migration-tool/migration-036.go @@ -0,0 +1,74 @@ +/* + * @Author: LinkLeong link@icewhale.org + * @Date: 2022-08-24 17:36:00 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-09-05 11:24:27 + * @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package main + +import ( + "strings" + + interfaces "github.com/IceWhaleTech/CasaOS-Common" + "github.com/IceWhaleTech/CasaOS-Common/utils/version" + "github.com/IceWhaleTech/CasaOS/pkg/config" + "github.com/IceWhaleTech/CasaOS/service" +) + +type migrationTool struct{} + +func (u *migrationTool) IsMigrationNeeded() (bool, error) { + + majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() + if err != nil { + if err == version.ErrLegacyVersionNotFound { + return false, nil + } + + return false, err + } + + if majorVersion > 0 { + return false, nil + } + + if minorVersion > 3 { + return false, nil + } + + if minorVersion == 3 && patchVersion > 5 { + return false, nil + } + + _logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...") + return true, nil + +} + +func (u *migrationTool) PreMigrate() error { + + return nil +} + +func (u *migrationTool) Migrate() error { + + if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { + service.MyService.System().UpdateUSBAutoMount("False") + service.MyService.System().ExecUSBAutoMountShell("False") + } + + _logger.Info("update done") + return nil +} + +func (u *migrationTool) PostMigrate() error { + return nil +} + +func NewMigrationToolFor_036() interfaces.MigrationTool { + return &migrationTool{} +} diff --git a/common/notify.go b/common/notify.go new file mode 100644 index 0000000..4a003d0 --- /dev/null +++ b/common/notify.go @@ -0,0 +1,67 @@ +package common + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "path/filepath" + "strings" +) + +const ( + CasaOSURLFilename = "casaos.url" + APICasaOSNotify = "/v1/notiry" +) + +type NotifyService interface { + SendNotify(path string, message map[string]interface{}) error +} +type notifyService struct { + address string +} + +func (n *notifyService) SendNotify(path string, message map[string]interface{}) error { + + url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify + "/" + path + body, err := json.Marshal(message) + if err != nil { + return err + } + response, err := http.Post(url, "application/json", bytes.NewBuffer(body)) + if err != nil { + return err + } + + if response.StatusCode != http.StatusCreated { + return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") + } + return nil + +} + +func NewNotifyService(runtimePath string) (NotifyService, error) { + casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename) + + buf, err := os.ReadFile(casaosAddressFile) + if err != nil { + return nil, err + } + + address := string(buf) + + response, err := http.Get(address + "/ping") + if err != nil { + return nil, err + } + + if response.StatusCode != 200 { + return nil, errors.New("failed to ping casaos service") + } + + return ¬ifyService{ + address: address, + }, nil +} diff --git a/main.go b/main.go index b616e52..6ff7af8 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "net/http" + "path/filepath" "time" "github.com/IceWhaleTech/CasaOS-Gateway/common" @@ -12,10 +13,12 @@ import ( "github.com/IceWhaleTech/CasaOS/pkg/cache" "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/sqlite" + "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/types" + "go.uber.org/zap" "github.com/robfig/cron" "gorm.io/gorm" @@ -107,7 +110,7 @@ func main() { if err != nil { panic(err) } - routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba"} + routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba", "notify"} for _, v := range routers { err = service.MyService.Gateway().CreateRoute(&common.Route{ Path: "/v1/" + v, @@ -141,6 +144,15 @@ func main() { // MaxHeaderBytes: 1 << 20, // } // s.ListenAndServe() + urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url") + err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()) + if err != nil { + loger.Error("Management service is listening...", + zap.Any("address", listener.Addr().String()), + zap.Any("filepath", urlFilePath), + ) + } + err = http.Serve(listener, r) if err != nil { panic(err) diff --git a/route/route.go b/route/route.go index 2ce2dc3..39d011b 100644 --- a/route/route.go +++ b/route/route.go @@ -40,7 +40,9 @@ func InitRouter() *gin.Engine { r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion) - + r.GET("/ping", func(ctx *gin.Context) { + ctx.String(200, "pong") + }) v1Group := r.Group("/v1") v1Group.Use(jwt2.JWT()) @@ -238,6 +240,11 @@ func InitRouter() *gin.Engine { v1SharesGroup.GET("/status", v1.GetSambaStatus) } } + v1NotifyGroup := v1Group.Group("/notify") + v1NotifyGroup.Use() + { + v1NotifyGroup.POST("/:path", v1.PostNotifyMssage) + } } return r } diff --git a/route/v1/docker.go b/route/v1/docker.go index 05ebddf..8c1254f 100644 --- a/route/v1/docker.go +++ b/route/v1/docker.go @@ -877,7 +877,7 @@ func UpdateSetting(c *gin.Context) { if err != nil { service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id) service.MyService.Docker().DockerContainerStart(id) - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)}) + 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 } // echo -e "hellow\nworld" >> diff --git a/route/v1/notiry.go b/route/v1/notiry.go new file mode 100644 index 0000000..c818aab --- /dev/null +++ b/route/v1/notiry.go @@ -0,0 +1,16 @@ +package v1 + +import ( + "github.com/IceWhaleTech/CasaOS/model" + "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" + "github.com/IceWhaleTech/CasaOS/service" + "github.com/gin-gonic/gin" +) + +func PostNotifyMssage(c *gin.Context) { + path := c.Param("path") + message := make(map[string]interface{}) + c.ShouldBind(&message) + service.MyService.Notify().SendNotify(path, message) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} diff --git a/service/notify.go b/service/notify.go index 3981e55..154d45a 100644 --- a/service/notify.go +++ b/service/notify.go @@ -37,12 +37,28 @@ type NotifyServer interface { SendInstallAppBySocket(app notify.Application) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) SendStorageBySocket(message notify.StorageMessage) + SendNotify(path string, message map[string]interface{}) } type notifyServer struct { db *gorm.DB } +func (i *notifyServer) SendNotify(path string, message map[string]interface{}) { + + msg := gosf.Message{} + msg.Body = message + msg.Success = true + msg.Text = path + + notify := notify.Message{} + notify.Path = path + notify.Msg = msg + + NotifyMsg <- notify + +} + func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) { body := make(map[string]interface{}) body["data"] = message From 3935489d8bb1b657a9ae4e41c10aba1ba93177bb Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Fri, 9 Sep 2022 04:12:34 +0100 Subject: [PATCH 15/42] add shell script --- build/sysroot/usr/share/casaos/shell/update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/sysroot/usr/share/casaos/shell/update.sh b/build/sysroot/usr/share/casaos/shell/update.sh index 3802105..c01abb4 100644 --- a/build/sysroot/usr/share/casaos/shell/update.sh +++ b/build/sysroot/usr/share/casaos/shell/update.sh @@ -9,4 +9,4 @@ ### -curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash \ No newline at end of file +curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash From 4f491fa22f1b7b6c10d1c842155a800fdad4ead3 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Tue, 13 Sep 2022 07:22:24 +0100 Subject: [PATCH 16/42] add system notiry --- common/notify.go | 18 ++++++++++++++++++ route/route.go | 2 ++ route/v1/notiry.go | 6 ++++++ service/notify.go | 20 ++++++++++++++------ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/common/notify.go b/common/notify.go index 4a003d0..c36cea0 100644 --- a/common/notify.go +++ b/common/notify.go @@ -18,6 +18,7 @@ const ( type NotifyService interface { SendNotify(path string, message map[string]interface{}) error + SendSystemNotify(message map[string]interface{}) error } type notifyService struct { address string @@ -41,7 +42,24 @@ func (n *notifyService) SendNotify(path string, message map[string]interface{}) return nil } +func (n *notifyService) SendSystemNotify(message map[string]interface{}) error { + url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify + body, err := json.Marshal(message) + if err != nil { + return err + } + response, err := http.Post(url, "application/json", bytes.NewBuffer(body)) + if err != nil { + return err + } + + if response.StatusCode != http.StatusCreated { + return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") + } + return nil + +} func NewNotifyService(runtimePath string) (NotifyService, error) { casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename) diff --git a/route/route.go b/route/route.go index 39d011b..0bfcbfc 100644 --- a/route/route.go +++ b/route/route.go @@ -244,6 +244,8 @@ func InitRouter() *gin.Engine { v1NotifyGroup.Use() { v1NotifyGroup.POST("/:path", v1.PostNotifyMssage) + //merge to system + v1NotifyGroup.POST("", v1.PostSystemNotyfiy) } } return r diff --git a/route/v1/notiry.go b/route/v1/notiry.go index c818aab..54e86fd 100644 --- a/route/v1/notiry.go +++ b/route/v1/notiry.go @@ -14,3 +14,9 @@ func PostNotifyMssage(c *gin.Context) { service.MyService.Notify().SendNotify(path, message) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) } +func PostSystemNotyfiy(c *gin.Context) { + message := make(map[string]interface{}) + c.ShouldBind(&message) + service.MyService.Notify().SettingSystemTempData(message) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} diff --git a/service/notify.go b/service/notify.go index 154d45a..fe93d83 100644 --- a/service/notify.go +++ b/service/notify.go @@ -38,14 +38,21 @@ type NotifyServer interface { SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) SendStorageBySocket(message notify.StorageMessage) SendNotify(path string, message map[string]interface{}) + SettingSystemTempData(message map[string]interface{}) } type notifyServer struct { - db *gorm.DB + db *gorm.DB + SystemTempMap map[string]interface{} +} + +func (i *notifyServer) SettingSystemTempData(message map[string]interface{}) { + for k, v := range message { + i.SystemTempMap[k] = v + } } func (i *notifyServer) SendNotify(path string, message map[string]interface{}) { - msg := gosf.Message{} msg.Body = message msg.Success = true @@ -77,9 +84,6 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) { func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) { body := make(map[string]interface{}) - body["sys_disk"] = disk - - body["sys_usb"] = list body["sys_mem"] = mem @@ -87,6 +91,10 @@ func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list [ body["sys_net"] = netList + for k, v := range i.SystemTempMap { + body[k] = v + } + msg := gosf.Message{} msg.Body = body msg.Success = true @@ -470,5 +478,5 @@ func SendMeg() { // } func NewNotifyService(db *gorm.DB) NotifyServer { - return ¬ifyServer{db: db} + return ¬ifyServer{db: db, SystemTempMap: make(map[string]interface{})} } From 8113f51cf7aa1a8f1ff09eec36cd07862638411b Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Thu, 15 Sep 2022 08:13:07 +0100 Subject: [PATCH 17/42] remove disk and test common package --- common/notify.go | 14 +- common/notify_test.go | 29 ++ go.mod | 1 - go.sum | 2 - main.go | 3 +- model/disk.go | 98 ------- model/docker.go | 4 + model/receive/app.go | 1 - pkg/sqlite/db.go | 2 +- route/init.go | 46 --- route/periodical.go | 257 +++-------------- route/route.go | 47 +-- route/v1/app.go | 53 ++++ route/v1/disk.go | 622 ---------------------------------------- route/v1/file.go | 27 +- route/v1/notiry.go | 5 +- route/v1/storage.go | 109 ------- route/v1/system.go | 147 +--------- service/disk.go | 285 ------------------ service/docker.go | 74 +++-- service/model/o_disk.go | 25 -- service/notify.go | 38 +-- service/service.go | 7 - 23 files changed, 186 insertions(+), 1710 deletions(-) create mode 100644 common/notify_test.go delete mode 100644 model/disk.go delete mode 100644 model/receive/app.go delete mode 100644 route/v1/disk.go delete mode 100644 route/v1/storage.go delete mode 100644 service/disk.go delete mode 100644 service/model/o_disk.go diff --git a/common/notify.go b/common/notify.go index c36cea0..82d3394 100644 --- a/common/notify.go +++ b/common/notify.go @@ -13,12 +13,12 @@ import ( const ( CasaOSURLFilename = "casaos.url" - APICasaOSNotify = "/v1/notiry" + APICasaOSNotify = "/v1/notify" ) type NotifyService interface { SendNotify(path string, message map[string]interface{}) error - SendSystemNotify(message map[string]interface{}) error + SendSystemStatusNotify(message map[string]interface{}) error } type notifyService struct { address string @@ -26,7 +26,7 @@ type notifyService struct { func (n *notifyService) SendNotify(path string, message map[string]interface{}) error { - url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify + "/" + path + url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/" + path body, err := json.Marshal(message) if err != nil { return err @@ -42,9 +42,13 @@ func (n *notifyService) SendNotify(path string, message map[string]interface{}) return nil } -func (n *notifyService) SendSystemNotify(message map[string]interface{}) error { - url := strings.TrimSuffix(n.address, "/") + "/" + APICasaOSNotify +// disk: "sys_disk":{"size":56866869248,"avail":5855485952,"health":true,"used":48099700736} +// usb: "sys_usb":[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}] +func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) error { + + url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/system_status" + fmt.Println(url) body, err := json.Marshal(message) if err != nil { return err diff --git a/common/notify_test.go b/common/notify_test.go new file mode 100644 index 0000000..1e9c543 --- /dev/null +++ b/common/notify_test.go @@ -0,0 +1,29 @@ +package common + +import "testing" + +func TestSendNotify(t *testing.T) { + notify, err := NewNotifyService("/var/run/casaos") + if err != nil { + t.Fatal(err) + } + err = notify.SendNotify("test", map[string]interface{}{ + "test": "test", + }) + if err != nil { + t.Fatal(err) + } +} + +func TestSendSystemStatusNotify(t *testing.T) { + notify, err := NewNotifyService("/var/run/casaos") + if err != nil { + t.Fatal(err) + } + err = notify.SendSystemStatusNotify(map[string]interface{}{ + "sys_usb": `[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]`, + }) + if err != nil { + t.Fatal(err) + } +} diff --git a/go.mod b/go.mod index 6209c3e..cfcc59b 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,6 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/pilebones/go-udev v0.9.0 github.com/pkg/errors v0.9.1 github.com/robfig/cron v1.2.0 github.com/satori/go.uuid v1.2.0 diff --git a/go.sum b/go.sum index 9e68d0e..49a1770 100644 --- a/go.sum +++ b/go.sum @@ -814,8 +814,6 @@ github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZO github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q= -github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/main.go b/main.go index 6ff7af8..f02afca 100644 --- a/main.go +++ b/main.go @@ -80,7 +80,6 @@ func main() { return } go route.SocketInit(service.NotifyMsg) - go route.MonitoryUSB() //model.Setup() //gredis.Setup() @@ -110,7 +109,7 @@ func main() { if err != nil { panic(err) } - routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba", "notify"} + routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "samba", "notify"} for _, v := range routers { err = service.MyService.Gateway().CreateRoute(&common.Route{ Path: "/v1/" + v, diff --git a/model/disk.go b/model/disk.go deleted file mode 100644 index 75d3bc5..0000000 --- a/model/disk.go +++ /dev/null @@ -1,98 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2022-07-13 10:43:45 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-03 14:45:35 - * @FilePath: /CasaOS/model/disk.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package model - -type LSBLKModel struct { - Name string `json:"name"` - FsType string `json:"fstype"` - Size uint64 `json:"size"` - FSSize string `json:"fssize"` - Path string `json:"path"` - Model string `json:"model"` //设备标识符 - RM bool `json:"rm"` //是否为可移动设备 - RO bool `json:"ro"` //是否为只读设备 - State string `json:"state"` - PhySec int `json:"phy-sec"` //物理扇区大小 - Type string `json:"type"` - Vendor string `json:"vendor"` //供应商 - Rev string `json:"rev"` //修订版本 - FSAvail string `json:"fsavail"` //可用空间 - FSUse string `json:"fsuse%"` //已用百分比 - MountPoint string `json:"mountpoint"` - Format string `json:"format"` - Health string `json:"health"` - HotPlug bool `json:"hotplug"` - UUID string `json:"uuid"` - FSUsed string `json:"fsused"` - Temperature int `json:"temperature"` - Tran string `json:"tran"` - MinIO uint64 `json:"min-io"` - UsedPercent float64 `json:"used_percent"` - Serial string `json:"serial"` - Children []LSBLKModel `json:"children"` - SubSystems string `json:"subsystems"` - Label string `json:"label"` - //详情特有 - StartSector uint64 `json:"start_sector,omitempty"` - Rota bool `json:"rota"` //true(hhd) false(ssd) - DiskType string `json:"disk_type"` - EndSector uint64 `json:"end_sector,omitempty"` -} - -type Drive struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Model string `json:"model"` - Health string `json:"health"` - Temperature int `json:"temperature"` - DiskType string `json:"disk_type"` - NeedFormat bool `json:"need_format"` - Serial string `json:"serial"` - Path string `json:"path"` - ChildrenNumber int `json:"children_number"` -} - -type DriveUSB struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Model string `json:"model"` - Avail uint64 `json:"avail"` - Children []USBChildren `json:"children"` -} -type USBChildren struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Avail uint64 `json:"avail"` - MountPoint string `json:"mount_point"` -} - -type Storage struct { - MountPoint string `json:"mount_point"` - Size string `json:"size"` - Avail string `json:"avail"` //可用空间 - Type string `json:"type"` - Path string `json:"path"` - DriveName string `json:"drive_name"` - Label string `json:"label"` -} -type Storages struct { - DiskName string `json:"disk_name"` - Size uint64 `json:"size"` - Path string `json:"path"` - Children []Storage `json:"children"` -} - -type Summary struct { - Size uint64 `json:"size"` - Avail uint64 `json:"avail"` //可用空间 - Health bool `json:"health"` - Used uint64 `json:"used"` -} diff --git a/model/docker.go b/model/docker.go index a083319..20b68cc 100644 --- a/model/docker.go +++ b/model/docker.go @@ -16,3 +16,7 @@ type DockerStatsModel struct { Data interface{} `json:"data"` Previous interface{} `json:"previous"` } + +type DeckerDaemonModel struct { + Graph string `json:"graph"` +} diff --git a/model/receive/app.go b/model/receive/app.go deleted file mode 100644 index 3ccae50..0000000 --- a/model/receive/app.go +++ /dev/null @@ -1 +0,0 @@ -package receive diff --git a/pkg/sqlite/db.go b/pkg/sqlite/db.go index 819da65..e5d7595 100644 --- a/pkg/sqlite/db.go +++ b/pkg/sqlite/db.go @@ -43,7 +43,7 @@ func GetDb(dbPath string) *gorm.DB { } gdb = db - err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}) + err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}) db.Exec("DROP TABLE IF EXISTS o_application") db.Exec("DROP TABLE IF EXISTS o_friend") db.Exec("DROP TABLE IF EXISTS o_person_download") diff --git a/route/init.go b/route/init.go index e2d09c7..a35de29 100644 --- a/route/init.go +++ b/route/init.go @@ -3,65 +3,19 @@ package route import ( "fmt" "os" - "strconv" "strings" "time" - "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/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" - model2 "github.com/IceWhaleTech/CasaOS/service/model" "go.uber.org/zap" ) func InitFunction() { - CheckSerialDiskMount() go InitNetworkMount() } - -func CheckSerialDiskMount() { - // check mount point - dbList := service.MyService.Disk().GetSerialAll() - - list := service.MyService.Disk().LSBLK(true) - mountPoint := make(map[string]string, len(dbList)) - //remount - for _, v := range dbList { - mountPoint[v.UUID] = v.MountPoint - } - for _, v := range list { - 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) - } - } - 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().RemoveLSBLKCache() - command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;AutoRemoveUnuseDir") -} - func InitNetworkMount() { time.Sleep(time.Second * 10) connections := service.MyService.Connections().GetConnectionsList() diff --git a/route/periodical.go b/route/periodical.go index 6fbdd74..7d12ca2 100644 --- a/route/periodical.go +++ b/route/periodical.go @@ -14,20 +14,12 @@ package route import ( - "os" - "os/signal" - "reflect" - "strconv" "strings" - "syscall" "time" "unsafe" "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" - "github.com/pilebones/go-udev/netlink" - "go.uber.org/zap" ) func SendNetINfoBySocket() { @@ -61,104 +53,6 @@ func SendMemBySocket() { service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo()) } -func SendDiskBySocket() { - list := service.MyService.Disk().LSBLK(true) - - 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" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - healthy = true - } else { - healthy = temp.SmartStatus.Passed - } - - //list[i].Temperature = temp.Temperature.Current - - 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 - service.MyService.Notify().SendDiskInfoBySocket(summary) -} - -func SendUSBBySocket() { - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - - } - } - if isMount { - usb = append(usb, temp) - } - } - } - service.MyService.Notify().SendUSBInfoBySocket(usb) -} - func SendAllHardwareStatusBySocket() { netList := service.MyService.System().GetNetInfo() @@ -183,131 +77,44 @@ func SendAllHardwareStatusBySocket() { cpuData["temperature"] = service.MyService.System().GetCPUTemperature() cpuData["power"] = service.MyService.System().GetCPUPower() - list := service.MyService.Disk().LSBLK(true) - - 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" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - healthy = true - } else { - healthy = temp.SmartStatus.Passed - } - 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 - - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - } - } - if isMount { - usb = append(usb, temp) - } - - } - } memInfo := service.MyService.System().GetMemInfo() - service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet) + service.MyService.Notify().SendAllHardwareStatusBySocket(memInfo, cpuData, newNet) } -func MonitoryUSB() { - var matcher netlink.Matcher - conn := new(netlink.UEventConn) - if err := conn.Connect(netlink.UdevEvent); err != nil { - loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err)) - } - defer conn.Close() +// func MonitoryUSB() { +// var matcher netlink.Matcher - queue := make(chan netlink.UEvent) - errors := make(chan error) - quit := conn.Monitor(queue, errors, matcher) +// conn := new(netlink.UEventConn) +// if err := conn.Connect(netlink.UdevEvent); err != nil { +// loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err)) +// } +// defer conn.Close() - signals := make(chan os.Signal, 1) - signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - go func() { - <-signals - close(quit) - os.Exit(0) - }() +// queue := make(chan netlink.UEvent) +// errors := make(chan error) +// quit := conn.Monitor(queue, errors, matcher) - for { - select { - case uevent := <-queue: - if uevent.Env["DEVTYPE"] == "disk" { - time.Sleep(time.Microsecond * 500) - SendUSBBySocket() - continue - } - case err := <-errors: - loger.Error("udev err", zap.Any("err", err)) - } - } +// signals := make(chan os.Signal, 1) +// signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) +// go func() { +// <-signals +// close(quit) +// os.Exit(0) +// }() -} +// for { +// select { +// case uevent := <-queue: +// if uevent.Env["DEVTYPE"] == "disk" { +// time.Sleep(time.Microsecond * 500) +// SendUSBBySocket() +// continue +// } +// case err := <-errors: +// loger.Error("udev err", zap.Any("err", err)) +// } +// } + +// } diff --git a/route/route.go b/route/route.go index 0bfcbfc..110fd69 100644 --- a/route/route.go +++ b/route/route.go @@ -1,7 +1,7 @@ package route import ( - jwt2 "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" "github.com/IceWhaleTech/CasaOS/middleware" "github.com/IceWhaleTech/CasaOS/pkg/config" v1 "github.com/IceWhaleTech/CasaOS/route/v1" @@ -45,7 +45,7 @@ func InitRouter() *gin.Engine { }) v1Group := r.Group("/v1") - v1Group.Use(jwt2.JWT()) + v1Group.Use(jwt.ExceptLocalhost()) { // v1UsersGroup := v1Group.Group("/users") // v1UsersGroup.Use() @@ -79,6 +79,7 @@ func InitRouter() *gin.Engine { v1ContainerGroup := v1Group.Group("/container") v1ContainerGroup.Use() { + v1ContainerGroup.GET("", v1.MyAppList) ///my/list v1ContainerGroup.GET("/usage", v1.AppUsageList) v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info @@ -99,6 +100,8 @@ func InitRouter() *gin.Engine { v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate) //Not used v1ContainerGroup.POST("/share", v1.ShareAppFile) + v1ContainerGroup.GET("/info", v1.GetcontainerInfo) + v1ContainerGroup.PUT("/info", v1.PutcontainerInfo) } v1AppCategoriesGroup := v1Group.Group("/app-categories") @@ -185,42 +188,6 @@ func InitRouter() *gin.Engine { { v1ImageGroup.GET("", v1.GetFileImage) } - - v1DisksGroup := v1Group.Group("/disks") - v1DisksGroup.Use() - { - //v1DiskGroup.GET("/check", v1.GetDiskCheck) //delete - //v1DisksGroup.GET("", v1.GetDiskInfo) - - //v1DisksGroup.POST("", v1.PostMountDisk) - v1DisksGroup.GET("", v1.GetDiskList) - v1DisksGroup.GET("/usb", v1.GetDisksUSBList) - v1DisksGroup.DELETE("/usb", v1.DeleteDiskUSB) - v1DisksGroup.DELETE("", v1.DeleteDisksUmount) - // //format storage - // v1DiskGroup.POST("/format", v1.PostDiskFormat) - - // //mount SATA disk - // v1DiskGroup.POST("/mount", v1.PostMountDisk) - - // //umount sata disk - // v1DiskGroup.POST("/umount", v1.PostDiskUmount) - - //v1DiskGroup.GET("/type", v1.FormatDiskType)//delete - - v1DisksGroup.DELETE("/part", v1.RemovePartition) //disk/delpart - } - - v1StorageGroup := v1Group.Group("/storage") - v1StorageGroup.Use() - { - v1StorageGroup.POST("", v1.PostDiskAddPartition) - - v1StorageGroup.PUT("", v1.PostDiskFormat) - - v1StorageGroup.DELETE("", v1.PostDiskUmount) - v1StorageGroup.GET("", v1.GetStorageList) - } v1SambaGroup := v1Group.Group("/samba") v1SambaGroup.Use() { @@ -243,9 +210,9 @@ func InitRouter() *gin.Engine { v1NotifyGroup := v1Group.Group("/notify") v1NotifyGroup.Use() { - v1NotifyGroup.POST("/:path", v1.PostNotifyMssage) + v1NotifyGroup.POST("/:path", v1.PostNotifyMessage) //merge to system - v1NotifyGroup.POST("", v1.PostSystemNotyfiy) + v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify) } } return r diff --git a/route/v1/app.go b/route/v1/app.go index 1a9f278..cc2ee00 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -2,10 +2,12 @@ package v1 import ( "encoding/json" + "fmt" "io/ioutil" "strconv" "github.com/IceWhaleTech/CasaOS/model" + "github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" @@ -262,3 +264,54 @@ func ShareAppFile(c *gin.Context) { content := service.MyService.Casa().ShareAppFile(str) c.JSON(common_err.SUCCESS, json.RawMessage(content)) } + +func GetcontainerInfo(c *gin.Context) { + // info, err := service.MyService.Docker().GetDockerInfo() + // 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 + // } + daemon := model.DeckerDaemonModel{} + data := make(map[string]interface{}, 1) + data["docker_root_dir"] = "" + if file.Exists("/etc/docker/daemon.json") { + byteResult := file.ReadFullFile("/etc/docker/daemon.json") + err := json.Unmarshal(byteResult, &daemon) + if err != nil { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + return + } + data["docker_root_dir"] = daemon.Graph + } + c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) +} +func PutcontainerInfo(c *gin.Context) { + js := make(map[string]interface{}) + err := c.BindJSON(&js) + if err != nil { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + return + } + dockerRootDir := js["docker_root_dir"].(string) + daemon := model.DeckerDaemonModel{} + if file.Exists("/etc/docker/daemon.json") { + byteResult := file.ReadFullFile("/etc/docker/daemon.json") + err := json.Unmarshal(byteResult, &daemon) + if err != nil { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + return + } + } + if !file.Exists(dockerRootDir) { + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) + return + } + daemon.Graph = dockerRootDir + byteMode, _ := json.Marshal(daemon) + file.WriteToPath(byteMode, "/etc/docker", "daemon.json") + + fmt.Println(command.ExecResultStr("systemctl daemon-reload")) + fmt.Println(command.ExecResultStr("systemctl restart docker")) + + c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) +} diff --git a/route/v1/disk.go b/route/v1/disk.go deleted file mode 100644 index e72e3ff..0000000 --- a/route/v1/disk.go +++ /dev/null @@ -1,622 +0,0 @@ -package v1 - -import ( - "fmt" - "net/http" - "path/filepath" - "reflect" - "strconv" - "strings" - "time" - - "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/model/notify" - "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" - "github.com/IceWhaleTech/CasaOS/pkg/utils/encryption" - "github.com/IceWhaleTech/CasaOS/pkg/utils/file" - - "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" - "github.com/IceWhaleTech/CasaOS/service" - model2 "github.com/IceWhaleTech/CasaOS/service/model" - "github.com/gin-gonic/gin" - "github.com/shirou/gopsutil/v3/disk" -) - -var diskMap = make(map[string]string) - -// @Summary disk list -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/list [get] -func GetDiskList(c *gin.Context) { - path := c.Query("path") - if len(path) > 0 { - m := service.MyService.Disk().GetDiskInfo(path) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m}) - return - } - t := c.DefaultQuery("type", "") - list := service.MyService.Disk().LSBLK(false) - if t == "usb" { - data := []model.DriveUSB{} - for _, v := range list { - if v.Tran == "usb" { - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - } - } - data = append(data, temp) - } - } - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) - return - } - - dbList := service.MyService.Disk().GetSerialAll() - part := make(map[string]int64, len(dbList)) - for _, v := range dbList { - part[v.MountPoint] = v.CreatedAt - } - findSystem := 0 - - disks := []model.Drive{} - storage := []model.Storage{} - avail := []model.Drive{} - for i := 0; i < len(list); i++ { - disk := model.Drive{} - if list[i].Rota { - disk.DiskType = "HDD" - } else { - disk.DiskType = "SSD" - } - disk.Serial = list[i].Serial - disk.Name = list[i].Name - disk.Size = list[i].Size - disk.Path = list[i].Path - disk.Model = list[i].Model - disk.ChildrenNumber = len(list[i].Children) - if len(list[i].Children) > 0 && findSystem == 0 { - for j := 0; j < len(list[i].Children); j++ { - if len(list[i].Children[j].Children) > 0 { - for _, v := range list[i].Children[j].Children { - if v.MountPoint == "/" { - stor := model.Storage{} - stor.MountPoint = v.MountPoint - stor.Size = v.FSSize - stor.Avail = v.FSAvail - stor.Path = v.Path - stor.Type = v.FsType - stor.DriveName = "System" - disk.Model = "System" - if strings.Contains(v.SubSystems, "mmc") { - disk.DiskType = "MMC" - } else if strings.Contains(v.SubSystems, "usb") { - disk.DiskType = "USB" - } - disk.Health = "true" - - disks = append(disks, disk) - storage = append(storage, stor) - findSystem = 1 - break - } - } - } else { - if list[i].Children[j].MountPoint == "/" { - stor := model.Storage{} - stor.MountPoint = list[i].Children[j].MountPoint - stor.Size = list[i].Children[j].FSSize - stor.Avail = list[i].Children[j].FSAvail - stor.Path = list[i].Children[j].Path - stor.Type = list[i].Children[j].FsType - stor.DriveName = "System" - disk.Model = "System" - if strings.Contains(list[i].Children[j].SubSystems, "mmc") { - disk.DiskType = "MMC" - } else if strings.Contains(list[i].Children[j].SubSystems, "usb") { - disk.DiskType = "USB" - } - disk.Health = "true" - - disks = append(disks, disk) - storage = append(storage, stor) - findSystem = 1 - break - } - } - - } - } - if findSystem == 1 { - findSystem += 1 - continue - } - - if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - temp.SmartStatus.Passed = true - } - isAvail := true - for _, v := range list[i].Children { - if v.MountPoint != "" { - stor := model.Storage{} - stor.MountPoint = v.MountPoint - stor.Size = v.FSSize - stor.Avail = v.FSAvail - stor.Path = v.Path - stor.Type = v.FsType - stor.DriveName = list[i].Name - storage = append(storage, stor) - isAvail = false - } - } - - if isAvail { - //if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" { - disk.NeedFormat = false - avail = append(avail, disk) - // } else { - // disk.NeedFormat = true - // avail = append(avail, disk) - // } - } - - disk.Temperature = temp.Temperature.Current - disk.Health = strconv.FormatBool(temp.SmartStatus.Passed) - - disks = append(disks, disk) - } - } - data := make(map[string]interface{}, 3) - data["drive"] = disks - data["storage"] = storage - data["avail"] = avail - - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) -} - -// @Summary disk list -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/list [get] -func GetDisksUSBList(c *gin.Context) { - list := service.MyService.Disk().LSBLK(false) - data := []model.DriveUSB{} - for _, v := range list { - if v.Tran == "usb" { - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Label - if temp.Name == "" { - temp.Name = v.Name - } - temp.Size = v.Size - children := []model.USBChildren{} - for _, child := range v.Children { - - if len(child.MountPoint) > 0 { - tempChildren := model.USBChildren{} - tempChildren.MountPoint = child.MountPoint - tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64) - tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64) - tempChildren.Name = child.Label - if len(tempChildren.Name) == 0 { - tempChildren.Name = filepath.Base(child.MountPoint) - } - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - children = append(children, tempChildren) - temp.Avail += avail - } - } - - temp.Children = children - data = append(data, temp) - } - } - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) - -} - -func DeleteDisksUmount(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - - path := js["path"] - pwd := js["password"] - - if len(path) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - token := c.GetHeader("Authorization") - if len(token) == 0 { - token = c.Query("token") - } - claims, err := jwt.ParseToken(token, true) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if encryption.GetMD5ByStr(pwd) != claims.Password { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - - diskInfo := service.MyService.Disk().GetDiskInfo(path) - for _, v := range diskInfo.Children { - service.MyService.Disk().UmountPointAndRemoveDir(v.Path) - //delete data - service.MyService.Disk().DeleteMountPoint(v.Path, v.MountPoint) - - service.MyService.Shares().DeleteShareByPath(v.MountPoint) - } - - service.MyService.Disk().RemoveLSBLKCache() - - //send notify to client - msg := notify.StorageMessage{} - msg.Action = "REMOVED" - msg.Path = path - msg.Volume = "" - msg.Size = 0 - msg.Type = "" - service.MyService.Notify().SendStorageBySocket(msg) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: path}) -} - -func DeleteDiskUSB(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - mountPoint := js["mount_point"] - if file.CheckNotExist(mountPoint) { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) - return - } - service.MyService.Disk().UmountUSB(mountPoint) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint}) -} - -// @Summary get disk list -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/lists [get] -func GetPlugInDisks(c *gin.Context) { - - list := service.MyService.Disk().LSBLK(true) - var result []*disk.UsageStat - for _, item := range list { - result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path)) - } - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result}) -} - -// @Summary disk detail -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Param path query string true "for example /dev/sda" -// @Success 200 {string} string "ok" -// @Router /disk/info [get] -func GetDiskInfo(c *gin.Context) { - path := c.Query("path") - if len(path) == 0 { - c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - } - m := service.MyService.Disk().GetDiskInfo(path) - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m}) -} - -// @Summary 获取支持的格式 -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/type [get] -func FormatDiskType(c *gin.Context) { - var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"} - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr}) - -} - -// @Summary 删除分区 -// @Produce application/json -// @Accept multipart/form-data -// @Tags disk -// @Security ApiKeyAuth -// @Param path formData string true "磁盘路径 例如/dev/sda1" -// @Success 200 {string} string "ok" -// @Router /disk/delpart [delete] -func RemovePartition(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - path := js["path"] - - if len(path) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - } - var p = path[:len(path)-1] - var n = path[len(path)-1:] - service.MyService.Disk().DelPartition(p, n) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary add storage -// @Produce application/json -// @Accept multipart/form-data -// @Tags disk -// @Security ApiKeyAuth -// @Param path formData string true "disk path e.g. /dev/sda" -// @Param serial formData string true "serial" -// @Param name formData string true "name" -// @Param format formData bool true "need format(true)" -// @Success 200 {string} string "ok" -// @Router /disk/storage [post] -func PostDiskAddPartition(c *gin.Context) { - - js := make(map[string]interface{}) - c.ShouldBind(&js) - path := js["path"].(string) - name := js["name"].(string) - format := js["format"].(bool) - - if len(path) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - - //diskInfo := service.MyService.Disk().GetDiskInfo(path) - - // if !file.CheckNotExist("/DATA/" + name) { - // // /mnt/name exist - // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)}) - // return - // } - diskMap[path] = "busying" - currentDisk := service.MyService.Disk().GetDiskInfo(path) - if format { - // format := service.MyService.Disk().FormatDisk(path+"1", "ext4") - // if len(format) == 0 { - // delete(diskMap, path) - // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)}) - // return - // } - service.MyService.Disk().AddPartition(path) - } - - // formatBool := true - // for formatBool { - // currentDisk = service.MyService.Disk().GetDiskInfo(path) - // if len(currentDisk.Children) > 0 { - // formatBool = false - // break - // } - // time.Sleep(time.Second) - // } - currentDisk = service.MyService.Disk().GetDiskInfo(path) - // if len(currentDisk.Children) != 1 { - // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)}) - // return - // } - fmt.Println(name) - if len(name) == 0 { - name = "Storage" - } - fmt.Println(name) - for i := 0; i < len(currentDisk.Children); i++ { - childrenName := currentDisk.Children[i].Label - if len(childrenName) == 0 { - //childrenName = name + "_" + currentDisk.Children[i].Name - childrenName = name + "_" + strconv.Itoa(i+1) - } - mountPath := "/DATA/" + childrenName - if !file.CheckNotExist(mountPath) { - ls := service.MyService.System().GetDirPath(mountPath) - if len(ls) > 0 { - // exist - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)}) - return - } - } - m := model2.SerialDisk{} - m.MountPoint = mountPath - m.Path = currentDisk.Children[i].Path - m.UUID = currentDisk.Children[i].UUID - m.State = 0 - m.CreatedAt = time.Now().Unix() - service.MyService.Disk().SaveMountPoint(m) - //mount dir - service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath) - } - - service.MyService.Disk().RemoveLSBLKCache() - - delete(diskMap, path) - - //send notify to client - msg := notify.StorageMessage{} - msg.Action = "ADDED" - msg.Path = currentDisk.Children[0].Path - msg.Volume = "/DATA/" - msg.Size = currentDisk.Children[0].Size - msg.Type = currentDisk.Children[0].Tran - service.MyService.Notify().SendStorageBySocket(msg) - - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Param pwd formData string true "user password" -// @Param volume formData string true "mount point" -// @Success 200 {string} string "ok" -// @Router /disk/format [post] -func PostDiskFormat(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - path := js["path"] - t := "ext4" - pwd := js["password"] - volume := js["volume"] - token := c.GetHeader("Authorization") - if len(token) == 0 { - token = c.Query("token") - } - claims, err := jwt.ParseToken(token, true) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if encryption.GetMD5ByStr(pwd) != claims.Password { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if len(path) == 0 || len(t) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - diskMap[path] = "busying" - service.MyService.Disk().UmountPointAndRemoveDir(path) - format := service.MyService.Disk().FormatDisk(path, t) - if len(format) == 0 { - delete(diskMap, path) - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)}) - return - } - service.MyService.Disk().MountDisk(path, volume) - service.MyService.Disk().RemoveLSBLKCache() - delete(diskMap, path) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary remove mount point -// @Produce application/json -// @Accept multipart/form-data -// @Tags disk -// @Security ApiKeyAuth -// @Param path formData string true "e.g. /dev/sda1" -// @Param mount_point formData string true "e.g. /mnt/volume1" -// @Param pwd formData string true "user password" -// @Success 200 {string} string "ok" -// @Router /disk/umount [post] -func PostDiskUmount(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - - path := js["path"] - mountPoint := js["volume"] - pwd := js["password"] - - if len(path) == 0 || len(mountPoint) == 0 { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) - return - } - token := c.GetHeader("Authorization") - if len(token) == 0 { - token = c.Query("token") - } - claims, err := jwt.ParseToken(token, true) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if encryption.GetMD5ByStr(pwd) != claims.Password { - c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) - return - } - - if _, ok := diskMap[path]; ok { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)}) - return - } - - service.MyService.Disk().UmountPointAndRemoveDir(path) - //delete data - service.MyService.Disk().DeleteMountPoint(path, mountPoint) - service.MyService.Disk().RemoveLSBLKCache() - - //send notify to client - msg := notify.StorageMessage{} - msg.Action = "REMOVED" - msg.Path = path - msg.Volume = mountPoint - msg.Size = 0 - msg.Type = "" - service.MyService.Notify().SendStorageBySocket(msg) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary confirm delete disk -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Param id path string true "id" -// @Success 200 {string} string "ok" -// @Router /disk/remove/{id} [delete] -func DeleteDisk(c *gin.Context) { - id := c.Param("id") - service.MyService.Disk().DeleteMount(id) - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} - -// @Summary check mount point -// @Produce application/json -// @Accept application/json -// @Tags disk -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /disk/init [get] -func GetDiskCheck(c *gin.Context) { - - dbList := service.MyService.Disk().GetSerialAll() - list := service.MyService.Disk().LSBLK(true) - - mapList := make(map[string]string) - - for _, v := range list { - mapList[v.Serial] = "1" - } - - for _, v := range dbList { - if _, ok := mapList[v.UUID]; !ok { - //disk undefind - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"}) - return - } - } - - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) -} diff --git a/route/v1/file.go b/route/v1/file.go index 0b2dbc7..548ee4a 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -236,33 +236,8 @@ func DirPath(c *gin.Context) { info[i].Type = "application" } } - } else if path == "/DATA" { - disk := make(map[string]string) - lsblk := service.MyService.Disk().LSBLK(true) - for _, v := range lsblk { - if len(v.Children) > 0 { - t := v.Tran - for _, c := range v.Children { - if len(c.Children) > 0 { - for _, gc := range c.Children { - if len(gc.MountPoint) > 0 { - disk[gc.MountPoint] = t - } - } - } - if len(c.MountPoint) > 0 { - disk[c.MountPoint] = t - } - } - - } - } - for i := 0; i < len(info); i++ { - if v, ok := disk[info[i].Path]; ok { - info[i].Type = v - } - } } + for i := 0; i < len(info); i++ { if v, ok := sharesMap[info[i].Path]; ok { ex := make(map[string]interface{}) diff --git a/route/v1/notiry.go b/route/v1/notiry.go index 54e86fd..eef2a1b 100644 --- a/route/v1/notiry.go +++ b/route/v1/notiry.go @@ -7,14 +7,15 @@ import ( "github.com/gin-gonic/gin" ) -func PostNotifyMssage(c *gin.Context) { +func PostNotifyMessage(c *gin.Context) { path := c.Param("path") message := make(map[string]interface{}) c.ShouldBind(&message) service.MyService.Notify().SendNotify(path, message) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) } -func PostSystemNotyfiy(c *gin.Context) { + +func PostSystemStatusNotify(c *gin.Context) { message := make(map[string]interface{}) c.ShouldBind(&message) service.MyService.Notify().SettingSystemTempData(message) diff --git a/route/v1/storage.go b/route/v1/storage.go deleted file mode 100644 index b6bb3e3..0000000 --- a/route/v1/storage.go +++ /dev/null @@ -1,109 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2022-07-11 16:02:29 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-17 19:14:50 - * @FilePath: /CasaOS/route/v1/storage.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package v1 - -import ( - "path/filepath" - "reflect" - - "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" - "github.com/IceWhaleTech/CasaOS/service" - "github.com/gin-gonic/gin" -) - -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 { - 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{}) { - temp.SmartStatus.Passed = true - } - 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 - stor.Avail = v.FSAvail - stor.Path = v.Path - stor.Type = v.FsType - stor.DriveName = v.Name - if len(v.Label) == 0 { - if stor.MountPoint == "/" { - stor.Label = "System" - } else { - stor.Label = filepath.Base(stor.MountPoint) - } - - children += 1 - } else { - stor.Label = v.Label - } - storageArr = append(storageArr, stor) - } - } - - if len(storageArr) > 0 { - 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 9f908d2..29fbcf2 100644 --- a/route/v1/system.go +++ b/route/v1/system.go @@ -7,7 +7,6 @@ import ( "io/ioutil" "net/http" "os" - "reflect" "strconv" "strings" "time" @@ -16,14 +15,12 @@ import ( "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" 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" "github.com/IceWhaleTech/CasaOS/types" "github.com/gin-gonic/gin" - "go.uber.org/zap" ) // @Summary check version @@ -79,7 +76,7 @@ func GetCasaOSErrorLogs(c *gin.Context) { c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)}) } -//系统配置 +// 系统配置 func GetSystemConfigDebug(c *gin.Context) { array := service.MyService.System().GetSystemConfigDebug() disk := service.MyService.System().GetDiskInfo() @@ -185,31 +182,6 @@ func PutSystemUSBAutoMount(c *gin.Context) { service.MyService.System().UpdateUSBAutoMount("False") service.MyService.System().ExecUSBAutoMountShell("False") } - go func() { - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - - } - } - if isMount { - usb = append(usb, temp) - } - } - } - service.MyService.Notify().SendUSBInfoBySocket(usb) - }() c.JSON(common_err.SUCCESS, model.Result{ Success: common_err.SUCCESS, @@ -229,31 +201,6 @@ func GetSystemUSBAutoMount(c *gin.Context) { if config.ServerInfo.USBAutoMount == "False" { state = "False" } - go func() { - usbList := service.MyService.Disk().LSBLK(false) - usb := []model.DriveUSB{} - for _, v := range usbList { - if v.Tran == "usb" { - isMount := false - temp := model.DriveUSB{} - temp.Model = v.Model - temp.Name = v.Name - temp.Size = v.Size - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - isMount = true - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - - } - } - if isMount { - usb = append(usb, temp) - } - } - } - service.MyService.Notify().SendUSBInfoBySocket(usb) - }() c.JSON(common_err.SUCCESS, model.Result{ Success: common_err.SUCCESS, @@ -324,98 +271,6 @@ func GetSystemHardwareInfo(c *gin.Context) { // @Router /sys/utilization [get] func GetSystemUtilization(c *gin.Context) { var data = make(map[string]interface{}, 6) - - list := service.MyService.Disk().LSBLK(true) - - 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) - loger.Info("disk info", zap.Any("/ total:", s)) - loger.Info("disk path", zap.Any("path", v.Path)) - 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) - loger.Info("disk info", zap.Any("/ total:", s)) - loger.Info("disk path", zap.Any("path", list[i].Path)) - 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" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") { - temp := service.MyService.Disk().SmartCTL(list[i].Path) - if reflect.DeepEqual(temp, model.SmartctlA{}) { - healthy = true - } else { - healthy = temp.SmartStatus.Passed - } - 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) - loger.Info("disk info", zap.Any("/ total:", s)) - loger.Info("disk path", zap.Any("path", list[i].Path)) - 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 - - for _, child := range v.Children { - if len(child.MountPoint) > 0 { - avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) - temp.Avail += avail - } - } - usb = append(usb, temp) - } - } - data["usb"] = usb cpu := service.MyService.System().GetCpuPercent() num := service.MyService.System().GetCpuCoreNum() cpuData := make(map[string]interface{}) diff --git a/service/disk.go b/service/disk.go deleted file mode 100644 index dfe8219..0000000 --- a/service/disk.go +++ /dev/null @@ -1,285 +0,0 @@ -package service - -import ( - json2 "encoding/json" - "fmt" - "reflect" - "strconv" - "strings" - "time" - - "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/config" - command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" - model2 "github.com/IceWhaleTech/CasaOS/service/model" - "github.com/shirou/gopsutil/v3/disk" - "github.com/tidwall/gjson" - "go.uber.org/zap" - "gorm.io/gorm" -) - -type DiskService interface { - GetPlugInDisk() []string - LSBLK(isUseCache bool) []model.LSBLKModel - SmartCTL(path string) model.SmartctlA - FormatDisk(path, format string) []string - UmountPointAndRemoveDir(path string) []string - GetDiskInfo(path string) model.LSBLKModel - DelPartition(path, num string) string - AddPartition(path string) string - GetDiskInfoByPath(path string) *disk.UsageStat - MountDisk(path, volume string) - GetSerialAll() []model2.SerialDisk - SaveMountPoint(m model2.SerialDisk) - DeleteMountPoint(path, mountPoint string) - DeleteMount(id string) - UpdateMountPoint(m model2.SerialDisk) - RemoveLSBLKCache() - UmountUSB(path string) -} -type diskService struct { - db *gorm.DB -} - -func (d *diskService) RemoveLSBLKCache() { - key := "system_lsblk" - Cache.Delete(key) -} -func (d *diskService) UmountUSB(path string) { - r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path) - fmt.Println(r) -} -func (d *diskService) SmartCTL(path string) model.SmartctlA { - - key := "system_smart_" + path - if result, ok := Cache.Get(key); ok { - - res, ok := result.(model.SmartctlA) - if ok { - return res - } - } - var m model.SmartctlA - str := command2.ExecSmartCTLByPath(path) - if str == nil { - loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error")) - Cache.Add(key, m, time.Minute*10) - return m - } - - err := json2.Unmarshal([]byte(str), &m) - if err != nil { - loger.Error("Failed to unmarshal json", zap.Any("err", err)) - } - if !reflect.DeepEqual(m, model.SmartctlA{}) { - Cache.Add(key, m, time.Hour*24) - } - return m -} - -//通过脚本获取外挂磁盘 -func (d *diskService) GetPlugInDisk() []string { - return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPlugInDisk") -} - -//格式化硬盘 -func (d *diskService) FormatDisk(path, format string) []string { - r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;FormatDisk " + path + " " + format) - return r -} - -//移除挂载点,删除目录 -func (d *diskService) UmountPointAndRemoveDir(path string) []string { - r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + path) - return r -} - -//删除分区 -func (d *diskService) DelPartition(path, num string) string { - r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;DelPartition " + path + " " + num) - fmt.Println(r) - return "" -} - -//part -func (d *diskService) AddPartition(path string) string { - command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;AddPartition " + path) - return "" -} - -func (d *diskService) AddAllPartition(path string) { - -} - -//获取硬盘详情 -func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat { - diskInfo, err := disk.Usage(path + "1") - - if err != nil { - fmt.Println(err) - } - diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64) - diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64) - return diskInfo -} - -//get disk details -func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel { - key := "system_lsblk" - var n []model.LSBLKModel - - if result, ok := Cache.Get(key); ok && isUseCache { - - res, ok := result.([]model.LSBLKModel) - if ok { - return res - } - } - - str := command2.ExecLSBLK() - if str == nil { - loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error")) - return nil - } - var m []model.LSBLKModel - err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m) - if err != nil { - loger.Error("Failed to unmarshal json", zap.Any("err", err)) - } - - var c []model.LSBLKModel - - var fsused uint64 - - var health = true - for _, i := range m { - if i.Type != "loop" && !i.RO { - fsused = 0 - for _, child := range i.Children { - if child.RM { - child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskHealthState " + child.Path)) - if strings.ToLower(strings.TrimSpace(child.State)) != "ok" { - health = false - } - f, _ := strconv.ParseUint(child.FSUsed, 10, 64) - fsused += f - } else { - health = false - } - c = append(c, child) - } - //i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskType " + i.Path)) - if health { - i.Health = "OK" - } - i.FSUsed = strconv.FormatUint(fsused, 10) - i.Children = c - if fsused > 0 { - i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64) - if err != nil { - loger.Error("Failed to parse float", zap.Any("err", err)) - } - } - n = append(n, i) - health = true - c = []model.LSBLKModel{} - fsused = 0 - } - } - if len(n) > 0 { - Cache.Add(key, n, time.Second*100) - } - return n -} - -func (d *diskService) GetDiskInfo(path string) model.LSBLKModel { - str := command2.ExecLSBLKByPath(path) - if str == nil { - loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error")) - return model.LSBLKModel{} - } - - var ml []model.LSBLKModel - err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml) - if err != nil { - loger.Error("Failed to unmarshal json", zap.Any("err", err)) - return model.LSBLKModel{} - } - - m := model.LSBLKModel{} - if len(ml) > 0 { - m = ml[0] - } - return m - // 下面为计算是否可以继续分区的部分,暂时不需要 - chiArr := make(map[string]string) - chiList := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPartitionSectors " + m.Path) - if len(chiList) == 0 { - loger.Error("chiList length error", zap.Any("err", "chiList length error")) - } - for i := 0; i < len(chiList); i++ { - tempArr := strings.Split(chiList[i], ",") - chiArr[tempArr[0]] = chiList[i] - } - var maxSector uint64 = 0 - for i := 0; i < len(m.Children); i++ { - tempArr := strings.Split(chiArr[m.Children[i].Path], ",") - m.Children[i].StartSector, _ = strconv.ParseUint(tempArr[1], 10, 64) - m.Children[i].EndSector, _ = strconv.ParseUint(tempArr[2], 10, 64) - if m.Children[i].EndSector > maxSector { - maxSector = m.Children[i].EndSector - } - - } - diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskSizeAndSectors " + m.Path) - - if len(diskEndSector) < 2 { - loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error")) - } - diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64) - if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 { - //添加可以分区情况 - p := model.LSBLKModel{} - p.Path = "可以添加" - m.Children = append(m.Children, p) - } - return m -} - -func (d *diskService) MountDisk(path, volume string) { - //fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume) - r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume) - fmt.Println(r) -} - -func (d *diskService) SaveMountPoint(m model2.SerialDisk) { - d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{}) - d.db.Create(&m) -} - -func (d *diskService) UpdateMountPoint(m model2.SerialDisk) { - d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint) -} - -func (d *diskService) DeleteMount(id string) { - - d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id) -} - -func (d *diskService) DeleteMountPoint(path, mountPoint string) { - - d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{}) - - command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;do_umount " + path) -} - -func (d *diskService) GetSerialAll() []model2.SerialDisk { - var m []model2.SerialDisk - d.db.Find(&m) - return m -} - -func NewDiskService(db *gorm.DB) DiskService { - return &diskService{db: db} -} diff --git a/service/docker.go b/service/docker.go index 9fe885f..812fb8a 100644 --- a/service/docker.go +++ b/service/docker.go @@ -59,6 +59,7 @@ type DockerService interface { DockerImageInfo(image string) (types.ImageInspect, error) GetNetWorkNameByNetWorkID(id string) (string, error) ContainerExecShell(container_id string) string + GetDockerInfo() (types.Info, error) } type dockerService struct { @@ -94,7 +95,7 @@ func (ds *dockerService) ContainerExecShell(container_id string) string { return exec.ID } -//创建默认网络 +// 创建默认网络 func DockerNetwork() { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -109,7 +110,7 @@ func DockerNetwork() { cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{}) } -//根据网络id获取网络名 +// 根据网络id获取网络名 func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) { cli, _ := client2.NewClientWithOpts(client2.FromEnv) defer cli.Close() @@ -122,7 +123,7 @@ func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) { return "", err } -//拉取镜像 +// 拉取镜像 func DockerPull() { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -141,7 +142,7 @@ func DockerPull() { } -//拉取镜像 +// 拉取镜像 func DockerEx() { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -292,7 +293,7 @@ func DockerLogs() { //正式内容 -//检查镜像是否存在 +// 检查镜像是否存在 func (ds *dockerService) IsExistImage(imageName string) bool { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -311,7 +312,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool { return false } -//安装镜像 +// 安装镜像 func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -365,12 +366,12 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c return container.ID, err } -//param imageName 镜像名称 -//param containerDbId 数据库的id -//param port 容器内部主端口 -//param mapPort 容器主端口映射到外部的端口 -//param tcp 容器其他tcp端口 -//param udp 容器其他udp端口 +// param imageName 镜像名称 +// param containerDbId 数据库的id +// param port 容器内部主端口 +// param mapPort 容器主端口映射到外部的端口 +// param tcp 容器其他tcp端口 +// param udp 容器其他udp端口 func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) { if len(m.NetworkModel) == 0 { m.NetworkModel = "bridge" @@ -581,7 +582,7 @@ func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id return containerDb.ID, err } -//删除容器 +// 删除容器 func (ds *dockerService) DockerContainerRemove(name string, update bool) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -605,7 +606,7 @@ func (ds *dockerService) DockerContainerRemove(name string, update bool) error { return err } -//删除镜像 +// 删除镜像 func (ds *dockerService) DockerImageRemove(name string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -653,7 +654,7 @@ Loop: return err } -//停止镜像 +// 停止镜像 func (ds *dockerService) DockerContainerStop(id string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -664,7 +665,7 @@ func (ds *dockerService) DockerContainerStop(id string) error { return err } -//启动容器 +// 启动容器 func (ds *dockerService) DockerContainerStart(name string) error { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -675,7 +676,7 @@ func (ds *dockerService) DockerContainerStart(name string) error { return err } -//查看日志 +// 查看日志 func (ds *dockerService) DockerContainerLog(name string) (string, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -714,7 +715,7 @@ func DockerContainerStats1() error { return nil } -//获取容器状态 +// 获取容器状态 func (ds *dockerService) DockerContainerStats(name string) (string, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -733,7 +734,7 @@ func (ds *dockerService) DockerContainerStats(name string) (string, error) { return string(sts), nil } -//备份容器 +// 备份容器 func (ds *dockerService) DockerContainerCommit(name string) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -778,7 +779,7 @@ func (ds *dockerService) DockerListByImage(image, version string) (*types.Contai return &containers[0], nil } -//获取容器详情 +// 获取容器详情 func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) @@ -793,13 +794,13 @@ func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, return &d, nil } -//更新容器 -//param shares cpu优先级 -//param containerDbId 数据库的id -//param port 容器内部主端口 -//param mapPort 容器主端口映射到外部的端口 -//param tcp 容器其他tcp端口 -//param udp 容器其他udp端口 +// 更新容器 +// param shares cpu优先级 +// param containerDbId 数据库的id +// param port 容器内部主端口 +// param mapPort 容器主端口映射到外部的端口 +// param tcp 容器其他tcp端口 +// param udp 容器其他udp端口 func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -834,9 +835,9 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id return } -//更新容器名称 -//param name 容器名称 -//param id 老的容器名称 +// 更新容器名称 +// param name 容器名称 +// param id 老的容器名称 func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { @@ -851,7 +852,7 @@ func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) return } -//获取网络列表 +// 获取网络列表 func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource { cli, _ := client2.NewClientWithOpts(client2.FromEnv) @@ -863,6 +864,17 @@ func NewDockerService() DockerService { return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)} } +func (ds *dockerService) GetDockerInfo() (types.Info, error) { + cli, err := client2.NewClientWithOpts(client2.FromEnv) + if err != nil { + return types.Info{}, err + } + defer cli.Close() + + return cli.Info(context.Background()) + +} + // ---------------------------------------test------------------------------------ //func ServiceCreate() { // cli, err := client2.NewClientWithOpts(client2.FromEnv) diff --git a/service/model/o_disk.go b/service/model/o_disk.go deleted file mode 100644 index 1121e87..0000000 --- a/service/model/o_disk.go +++ /dev/null @@ -1,25 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2021-12-07 17:14:41 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-08-17 18:46:43 - * @FilePath: /CasaOS/service/model/o_disk.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package model - -//SerialAdvanced Technology Attachment (STAT) -type SerialDisk struct { - Id uint `gorm:"column:id;primary_key" json:"id"` - UUID string `json:"uuid"` - Path string `json:"path"` - State int `json:"state"` - MountPoint string `json:"mount_point"` - CreatedAt int64 `json:"created_at"` -} - -func (p *SerialDisk) TableName() string { - return "o_disk" -} diff --git a/service/notify.go b/service/notify.go index fe93d83..05d3162 100644 --- a/service/notify.go +++ b/service/notify.go @@ -31,11 +31,9 @@ type NotifyServer interface { SendNetInfoBySocket(netList []model2.IOCountersStat) SendCPUInfoBySocket(cpu map[string]interface{}) SendMemInfoBySocket(mem map[string]interface{}) - SendUSBInfoBySocket(list []model2.DriveUSB) - SendDiskInfoBySocket(disk model2.Summary) SendFileOperateNotify(nowSend bool) SendInstallAppBySocket(app notify.Application) - SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) + SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) SendStorageBySocket(message notify.StorageMessage) SendNotify(path string, message map[string]interface{}) SettingSystemTempData(message map[string]interface{}) @@ -81,7 +79,7 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) { NotifyMsg <- notify } -func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) { +func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) { body := make(map[string]interface{}) @@ -263,38 +261,6 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) { } -func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) { - body := make(map[string]interface{}) - body["data"] = disk - - msg := gosf.Message{} - msg.Body = body - msg.Success = true - msg.Text = "sys_disk" - - notify := notify.Message{} - notify.Path = "sys_disk" - notify.Msg = msg - - NotifyMsg <- notify -} - -func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) { - body := make(map[string]interface{}) - body["data"] = list - - msg := gosf.Message{} - msg.Body = body - msg.Success = true - msg.Text = "sys_usb" - - notify := notify.Message{} - notify.Path = "sys_usb" - notify.Msg = msg - - NotifyMsg <- notify -} - func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) { body := make(map[string]interface{}) body["data"] = mem diff --git a/service/service.go b/service/service.go index 16594b9..e2164c0 100644 --- a/service/service.go +++ b/service/service.go @@ -30,7 +30,6 @@ type Repository interface { //User() UserService Docker() DockerService Casa() CasaService - Disk() DiskService Notify() NotifyServer Rely() RelyService System() SystemService @@ -51,7 +50,6 @@ func NewService(db *gorm.DB, RuntimePath string) Repository { app: NewAppService(db), docker: NewDockerService(), casa: NewCasaService(), - disk: NewDiskService(db), notify: NewNotifyService(db), rely: NewRelyService(db), system: NewSystemService(), @@ -65,7 +63,6 @@ type store struct { app AppService docker DockerService casa CasaService - disk DiskService notify NotifyServer rely RelyService system SystemService @@ -107,7 +104,3 @@ func (c *store) Docker() DockerService { func (c *store) Casa() CasaService { return c.casa } - -func (c *store) Disk() DiskService { - return c.disk -} From 80c347ac018610d207659f46ccb15f587c104c6e Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Fri, 16 Sep 2022 04:47:42 +0100 Subject: [PATCH 18/42] update http status --- common/notify.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/notify.go b/common/notify.go index 82d3394..a5cee48 100644 --- a/common/notify.go +++ b/common/notify.go @@ -36,7 +36,7 @@ func (n *notifyService) SendNotify(path string, message map[string]interface{}) return err } - if response.StatusCode != http.StatusCreated { + if response.StatusCode != http.StatusOK { return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") } return nil @@ -58,7 +58,7 @@ func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) e return err } - if response.StatusCode != http.StatusCreated { + if response.StatusCode != http.StatusOK { return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")") } return nil From aff18fa091f5368c35db9e2880433696324d8ecf Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Mon, 19 Sep 2022 10:09:04 +0100 Subject: [PATCH 19/42] add share function to common --- common/share.go | 78 ++++++++++++++++++++++++++++++++++++++++++++ common/share_test.go | 14 ++++++++ 2 files changed, 92 insertions(+) create mode 100644 common/share.go create mode 100644 common/share_test.go diff --git a/common/share.go b/common/share.go new file mode 100644 index 0000000..a0da4b2 --- /dev/null +++ b/common/share.go @@ -0,0 +1,78 @@ +package common + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "path/filepath" + "strings" +) + +const ( + APICasaOSShare = "/v1/samba/shares" +) + +type ShareService interface { + DeleteShare(id string) error +} +type shareService struct { + address string +} + +func (n *shareService) DeleteShare(id string) error { + url := strings.TrimSuffix(n.address, "/") + APICasaOSShare + "/" + id + fmt.Println(url) + message := "{}" + body, err := json.Marshal(message) + if err != nil { + return err + } + + client := &http.Client{} + + // Create request + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(body)) + if err != nil { + return err + } + + // Fetch Request + response, err := client.Do(req) + if err != nil { + return err + } + defer response.Body.Close() + + if response.StatusCode != http.StatusOK { + return errors.New("failed to send share (status code: " + fmt.Sprint(response.StatusCode) + ")") + } + return nil + +} + +func NewShareService(runtimePath string) (ShareService, error) { + casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename) + + buf, err := os.ReadFile(casaosAddressFile) + if err != nil { + return nil, err + } + + address := string(buf) + + response, err := http.Get(address + "/ping") + if err != nil { + return nil, err + } + + if response.StatusCode != 200 { + return nil, errors.New("failed to ping casaos service") + } + + return &shareService{ + address: address, + }, nil +} diff --git a/common/share_test.go b/common/share_test.go new file mode 100644 index 0000000..ce79e03 --- /dev/null +++ b/common/share_test.go @@ -0,0 +1,14 @@ +package common + +import "testing" + +func TestDeleteShare(t *testing.T) { + share, err := NewShareService("/var/run/casaos") + if err != nil { + t.Fatal(err) + } + err = share.DeleteShare("1") + if err != nil { + t.Fatal(err) + } +} From f0448cd1b939e488b092fe73d784bb823b3382fb Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Wed, 28 Sep 2022 16:13:42 +0100 Subject: [PATCH 20/42] remove temp path --- .gitignore | 3 ++- .../migration/script.d/03-migrate-casaos.sh | 7 ++++--- build/sysroot/etc/casaos/casaos.conf.sample | 1 - conf/conf.conf.sample | 1 - model/sys_common.go | 11 +++++------ pkg/config/init.go | 13 +++++-------- route/v1/docker.go | 2 +- route/v1/file.go | 8 +++++--- service/casa.go | 8 -------- service/docker.go | 17 ++++++++++------- 10 files changed, 32 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 51d11d0..411aba3 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ __debug_bin main github.com .all-contributorsrc -dist \ No newline at end of file +dist +CasaOS \ No newline at end of file diff --git a/build/scripts/migration/script.d/03-migrate-casaos.sh b/build/scripts/migration/script.d/03-migrate-casaos.sh index ba64e4d..a48c437 100644 --- a/build/scripts/migration/script.d/03-migrate-casaos.sh +++ b/build/scripts/migration/script.d/03-migrate-casaos.sh @@ -60,8 +60,8 @@ BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../.. SOURCE_ROOT=${BUILD_PATH}/sysroot APP_NAME="casaos" -# APP_NAME_FORMAL="CasaOS" -APP_NAME_FORMAL="casaos-alpha" +APP_NAME_FORMAL="CasaOS" +#APP_NAME_FORMAL="casaos-alpha" # check if migration is needed SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin @@ -153,7 +153,8 @@ pushd "${MIGRATION_SERVICE_DIR}" continue fi - MIGRATION_TOOL_URL=https://github.com/LinkLeong/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz + # MIGRATION_TOOL_URL=http://192.168.2.197:8000/v1/package/migration?type=release&name="${APP_NAME_FORMAL}"&version=${VER2}&arch=${ARCH} + MIGRATION_TOOL_URL=https://github.com/IceWhaleTech/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz echo "Dowloading ${MIGRATION_TOOL_URL}..." curl -sL -O "${MIGRATION_TOOL_URL}" done diff --git a/build/sysroot/etc/casaos/casaos.conf.sample b/build/sysroot/etc/casaos/casaos.conf.sample index 3e64508..e51f0fa 100644 --- a/build/sysroot/etc/casaos/casaos.conf.sample +++ b/build/sysroot/etc/casaos/casaos.conf.sample @@ -11,7 +11,6 @@ DateFormat = 2006-01-02 DBPath = /var/lib/casaos ShellPath = /usr/share/casaos/shell UserDataPath = /var/lib/casaos/conf -TempPath = /var/lib/casaos/temp [server] RunMode = release diff --git a/conf/conf.conf.sample b/conf/conf.conf.sample index 5ce1d0e..1364418 100644 --- a/conf/conf.conf.sample +++ b/conf/conf.conf.sample @@ -11,7 +11,6 @@ DateFormat = 2006-01-02 DBPath = /var/lib/casaos ShellPath = /usr/share/casaos/shell UserDataPath = /var/lib/casaos/conf -TempPath = /var/lib/casaos/temp [server] RunMode = release diff --git a/model/sys_common.go b/model/sys_common.go index 1a78867..73316b0 100644 --- a/model/sys_common.go +++ b/model/sys_common.go @@ -12,12 +12,12 @@ package model import "time" -//系统配置 +// 系统配置 type SysInfoModel struct { Name string //系统名称 } -//服务配置 +// 服务配置 type ServerModel struct { HttpPort string RunMode string @@ -28,7 +28,7 @@ type ServerModel struct { SocketPort string } -//服务配置 +// 服务配置 type APPModel struct { LogPath string LogSaveName string @@ -40,20 +40,19 @@ type APPModel struct { DateFormat string DBPath string ShellPath string - TempPath string } type CommonModel struct { RuntimePath string } -//公共返回模型 +// 公共返回模型 type Result struct { Success int `json:"success" example:"200"` Message string `json:"message" example:"ok"` Data interface{} `json:"data" example:"返回结果"` } -//redis配置文件 +// redis配置文件 type RedisModel struct { Host string Password string diff --git a/pkg/config/init.go b/pkg/config/init.go index c79d71f..b2de00f 100644 --- a/pkg/config/init.go +++ b/pkg/config/init.go @@ -23,17 +23,17 @@ import ( "github.com/go-ini/ini" ) -//系统配置 +// 系统配置 var SysInfo = &model.SysInfoModel{} -//用户相关 +// 用户相关 var AppInfo = &model.APPModel{} var CommonInfo = &model.CommonModel{} //var RedisInfo = &model.RedisModel{} -//server相关 +// server相关 var ServerInfo = &model.ServerModel{} var SystemConfigInfo = &model.SystemConfig{} @@ -44,7 +44,7 @@ var FileSettingInfo = &model.FileSetting{} var Cfg *ini.File -//初始化设置,获取系统的部分信息。 +// 初始化设置,获取系统的部分信息。 func InitSetup(config string) { var configDir = USERCONFIGURL @@ -86,9 +86,6 @@ func InitSetup(config string) { if len(AppInfo.UserDataPath) == 0 { AppInfo.UserDataPath = "/var/lib/casaos/conf" } - if len(AppInfo.TempPath) == 0 { - AppInfo.TempPath = "/var/lib/casaos/temp" - } if len(CommonInfo.RuntimePath) == 0 { CommonInfo.RuntimePath = "/var/run/casaos" } @@ -97,7 +94,7 @@ func InitSetup(config string) { } -//映射 +// 映射 func mapTo(section string, v interface{}) { err := Cfg.Section(section).MapTo(v) if err != nil { diff --git a/route/v1/docker.go b/route/v1/docker.go index 8c1254f..4b7d4a4 100644 --- a/route/v1/docker.go +++ b/route/v1/docker.go @@ -761,7 +761,7 @@ func ChangAppState(c *gin.Context) { func ContainerLog(c *gin.Context) { appId := c.Param("id") log, _ := service.MyService.Docker().DockerContainerLog(appId) - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: log}) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(log)}) } // @Summary 获取容器状态 diff --git a/route/v1/file.go b/route/v1/file.go index 548ee4a..396074d 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -16,7 +16,6 @@ import ( "sync" "github.com/IceWhaleTech/CasaOS/model" - "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/service" @@ -267,6 +266,9 @@ func DirPath(c *gin.Context) { pathList := []model.Path{} for i := 0; i < len(info); i++ { + if info[i].Name == ".temp" && info[i].IsDir { + continue + } if _, ok := fileQueue[info[i].Path]; !ok { pathList = append(pathList, info[i]) } @@ -367,7 +369,7 @@ func GetFileUpload(c *gin.Context) { path := c.Query("path") dirPath := "" hash := file.GetHashByContent([]byte(fileName)) - tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/" + tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" if fileName != relative { dirPath = strings.TrimSuffix(relative, fileName) tempDir += dirPath @@ -406,7 +408,7 @@ func PostFileUpload(c *gin.Context) { c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return } - tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/" + tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" if fileName != relative { dirPath = strings.TrimSuffix(relative, fileName) diff --git a/service/casa.go b/service/casa.go index f5a71d3..4d80bf4 100644 --- a/service/casa.go +++ b/service/casa.go @@ -130,10 +130,6 @@ func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollec errr := json2.Unmarshal(results, &collection) if errr != nil { loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results))) - } else { - if collection.Version == o.GetCasaosVersion().Version { - return collection, err - } } head := make(map[string]string) @@ -204,10 +200,6 @@ func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error) err := json2.Unmarshal(results, &list) if err != nil { loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results))) - } else { - if list.Version == o.GetCasaosVersion().Version { - return list.Item, nil - } } item := []model.CategoryList{} head := make(map[string]string) diff --git a/service/docker.go b/service/docker.go index 812fb8a..f453c0b 100644 --- a/service/docker.go +++ b/service/docker.go @@ -52,7 +52,7 @@ type DockerService interface { DockerContainerStop(id string) error DockerContainerUpdateName(name, id string) (err error) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) - DockerContainerLog(name string) (string, error) + DockerContainerLog(name string) ([]byte, error) DockerContainerCommit(name string) DockerContainerList() []types.Container DockerNetworkModelList() []types.NetworkResource @@ -677,23 +677,26 @@ func (ds *dockerService) DockerContainerStart(name string) error { } // 查看日志 -func (ds *dockerService) DockerContainerLog(name string) (string, error) { +func (ds *dockerService) DockerContainerLog(name string) ([]byte, error) { cli, err := client2.NewClientWithOpts(client2.FromEnv) if err != nil { - return "", err + return []byte(""), err } defer cli.Close() - body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStderr: true, ShowStdout: true}) + //body, err := cli.ContainerAttach(context.Background(), name, types.ContainerAttachOptions{Logs: true, Stream: false, Stdin: false, Stdout: false, Stderr: false}) + body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true}) + if err != nil { - return "", err + return []byte(""), err } defer body.Close() content, err := ioutil.ReadAll(body) + //content, err := ioutil.ReadAll(body) if err != nil { - return "", err + return []byte(""), err } - return string(content), nil + return content, nil } func DockerContainerStats1() error { From 455d226dcdb3f59595e5a705fa24ecfb75d60bf6 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 11:14:19 -0400 Subject: [PATCH 21/42] remove /DATA directory initialization - moved to local-storage (#578) --- cmd/migration-tool/main.go | 18 +++++++++++------- main.go | 30 +++++++++++++++--------------- pkg/config/update.go | 32 -------------------------------- 3 files changed, 26 insertions(+), 54 deletions(-) delete mode 100644 pkg/config/update.go diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go index 5f7c60b..93b065d 100644 --- a/cmd/migration-tool/main.go +++ b/cmd/migration-tool/main.go @@ -28,25 +28,29 @@ const ( casaosServiceName = "casaos.service" ) -var _logger *Logger -var sqliteDB *gorm.DB +var ( + _logger *Logger + sqliteDB *gorm.DB +) -var configFlag = "" -var dbFlag = "" +var ( + configFlag = "" + dbFlag = "" +) func init() { config.InitSetup(configFlag) - config.UpdateSetup() if len(dbFlag) == 0 { dbFlag = config.AppInfo.DBPath + "/db" } sqliteDB = sqlite.GetDb(dbFlag) - //gredis.GetRedisConn(config.RedisInfo), + // gredis.GetRedisConn(config.RedisInfo), service.MyService = service.NewService(sqliteDB, "") } + func main() { versionFlag := flag.Bool("v", false, "version") debugFlag := flag.Bool("d", true, "debug") @@ -113,6 +117,6 @@ func main() { selectedMigrationTool.PostMigrate() _logger.Info("casaos migration ok") - //panic(err) + // panic(err) } diff --git a/main.go b/main.go index f02afca..32b1c01 100644 --- a/main.go +++ b/main.go @@ -28,9 +28,11 @@ const LOCALHOST = "127.0.0.1" var sqliteDB *gorm.DB -var configFlag = flag.String("c", "", "config address") -var dbFlag = flag.String("db", "", "db path") -var versionFlag = flag.Bool("v", false, "version") +var ( + configFlag = flag.String("c", "", "config address") + dbFlag = flag.String("db", "", "db path") + versionFlag = flag.Bool("v", false, "version") +) func init() { flag.Parse() @@ -39,7 +41,6 @@ func init() { return } config.InitSetup(*configFlag) - config.UpdateSetup() loger.LogInit() if len(*dbFlag) == 0 { @@ -47,7 +48,7 @@ func init() { } sqliteDB = sqlite.GetDb(*dbFlag) - //gredis.GetRedisConn(config.RedisInfo), + // gredis.GetRedisConn(config.RedisInfo), service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath) @@ -60,7 +61,6 @@ func init() { // go service.LoopFriend() // go service.MyService.App().CheckNewImage() - } // @title casaOS API @@ -80,21 +80,21 @@ func main() { return } go route.SocketInit(service.NotifyMsg) - //model.Setup() - //gredis.Setup() + // model.Setup() + // gredis.Setup() r := route.InitRouter() - //service.SyncTask(sqliteDB) + // service.SyncTask(sqliteDB) cron2 := cron.New() - //every day execution + // every day execution err := cron2.AddFunc("0/5 * * * * *", func() { if service.ClientCount > 0 { - //route.SendNetINfoBySocket() - //route.SendCPUBySocket() - //route.SendMemBySocket() + // route.SendNetINfoBySocket() + // route.SendCPUBySocket() + // route.SendMemBySocket() // route.SendDiskBySocket() - //route.SendUSBBySocket() + // route.SendUSBBySocket() route.SendAllHardwareStatusBySocket() } }) @@ -123,7 +123,7 @@ func main() { } go func() { time.Sleep(time.Second * 2) - //v0.3.6 + // v0.3.6 if config.ServerInfo.HttpPort != "" { changePort := common.ChangePortRequest{} changePort.Port = config.ServerInfo.HttpPort diff --git a/pkg/config/update.go b/pkg/config/update.go deleted file mode 100644 index 7dbae82..0000000 --- a/pkg/config/update.go +++ /dev/null @@ -1,32 +0,0 @@ -package config - -import ( - "runtime" - - "github.com/IceWhaleTech/CasaOS/pkg/utils/file" -) - -//检查目录是否存在 -func mkdirDATAAll() { - sysType := runtime.GOOS - var dirArray []string - if sysType == "linux" { - dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"} - } - - if sysType == "windows" { - dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"} - } - if sysType == "darwin" { - dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"} - } - - for _, v := range dirArray { - file.IsNotExistMkDir(v) - } - -} - -func UpdateSetup() { - mkdirDATAAll() -} From 12d5e5db03687c343cd41cc74193db5d2338ef1f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 12:21:44 -0400 Subject: [PATCH 22/42] update goreleaser configuration --- .goreleaser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 949e04f..690519d 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -117,7 +117,7 @@ builds: goarch: - arm goarm: - - "7" + - "7" archives: - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}" id: casaos @@ -159,9 +159,9 @@ changelog: # name_template: "v{{ .Version }}" release: github: - owner: LinkLeong - name: casaos-alpha + owner: IceWhaleTech + name: CasaOS draft: true prerelease: auto mode: replace - name_template: "v{{ .Version }}" \ No newline at end of file + name_template: "v{{ .Version }}" From 182bc25343c99acb89f7729acdcfdb8cbf532f78 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 17:56:28 -0400 Subject: [PATCH 23/42] wip --- .../usr/lib/systemd/system/casaos.service | 3 ++- go.mod | 1 + main.go | 24 ++++++++++++------- types/system.go | 19 +++++++-------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/build/sysroot/usr/lib/systemd/system/casaos.service b/build/sysroot/usr/lib/systemd/system/casaos.service index 249d72c..aa7ad32 100644 --- a/build/sysroot/usr/lib/systemd/system/casaos.service +++ b/build/sysroot/usr/lib/systemd/system/casaos.service @@ -1,12 +1,13 @@ [Unit] After=casaos-gateway.service ConditionFileNotEmpty=/etc/casaos/casaos.conf -Description=CasaOS Service +Description=CasaOS Main Service [Service] ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf PIDFile=/var/run/casaos/casaos.pid Restart=always +Type=notify [Install] WantedBy=multi-user.target diff --git a/go.mod b/go.mod index cfcc59b..db9ca62 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109 github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect github.com/containerd/containerd v1.5.7 // indirect + github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e github.com/disintegration/imaging v1.6.2 github.com/docker/distribution v2.8.0+incompatible // indirect github.com/docker/docker v20.10.7+incompatible diff --git a/main.go b/main.go index 32b1c01..ede006d 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ import ( "github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/types" + "github.com/coreos/go-systemd/daemon" "go.uber.org/zap" "github.com/robfig/cron" @@ -135,14 +136,6 @@ func main() { } }() - // s := &http.Server{ - // Addr: listener.Addr().String(), //fmt.Sprintf(":%v", config.ServerInfo.HttpPort), - // Handler: r, - // ReadTimeout: 60 * time.Second, - // WriteTimeout: 60 * time.Second, - // MaxHeaderBytes: 1 << 20, - // } - // s.ListenAndServe() urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url") err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()) if err != nil { @@ -152,7 +145,20 @@ func main() { ) } - err = http.Serve(listener, r) + if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { + loger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err)) + } else if supported { + loger.Info("Notified systemd that casaos main service is ready") + } else { + loger.Info("This process is not running as a systemd service.") + } + + s := &http.Server{ + Handler: r, + ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec) + } + + err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec) if err != nil { panic(err) } diff --git a/types/system.go b/types/system.go index 24ef182..e77a7d6 100644 --- a/types/system.go +++ b/types/system.go @@ -1,15 +1,14 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2022-02-17 18:53:22 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-09-06 14:27:42 - * @FilePath: /CasaOS/types/system.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. +/*@Author: LinkLeong link@icewhale.com + *@Date: 2022-02-17 18:53:22 + *@LastEditors: LinkLeong + *@LastEditTime: 2022-09-06 14:27:42 + *@FilePath: /CasaOS/types/system.go + *@Description: + *@Website: https://www.casaos.io + *Copyright (c) 2022 by icewhale, All Rights Reserved. */ package types -const CURRENTVERSION = "0.3.6" +const CURRENTVERSION = "0.3.7" const BODY = " " From b41d855f73a8444bbf44b8e9c81ab2319d44872d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 28 Sep 2022 18:19:31 -0400 Subject: [PATCH 24/42] change service type to notify for systemd so its status is OK only when service is initialized successfully --- build/scripts/setup/service.d/casaos/debian/setup-casaos.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh index a13b6e1..e083373 100644 --- a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh +++ b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh @@ -40,6 +40,6 @@ else echo "Enabling service..." systemctl enable --force --no-ask-password "${APP_NAME}.service" - echo "Starting service..." - systemctl start --force --no-ask-password "${APP_NAME}.service" + #echo "Starting service..." + #systemctl start --force --no-ask-password "${APP_NAME}.service" fi \ No newline at end of file From 2eac0408754ab340edc67272c3e67a5ff332dadc Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 29 Sep 2022 00:05:12 -0400 Subject: [PATCH 25/42] update CasaOS-Common to fix runtime error --- .goreleaser.debug.yaml | 167 +++++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +- middleware/gin.go | 12 +-- 4 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 .goreleaser.debug.yaml diff --git a/.goreleaser.debug.yaml b/.goreleaser.debug.yaml new file mode 100644 index 0000000..885e3a0 --- /dev/null +++ b/.goreleaser.debug.yaml @@ -0,0 +1,167 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +project_name: casaos +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy +builds: + - id: casaos-amd64 + binary: build/sysroot/usr/bin/casaos + env: + - CGO_ENABLED=1 + - CC=x86_64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - amd64 + hooks: + post: + - find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest + - id: casaos-arm64 + binary: build/sysroot/usr/bin/casaos + env: + - CGO_ENABLED=1 + - CC=aarch64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm64 + hooks: + post: + - find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest + - id: casaos-arm-7 + binary: build/sysroot/usr/bin/casaos + env: + - CGO_ENABLED=1 + - CC=arm-linux-gnueabihf-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm + goarm: + - "7" + hooks: + post: + - find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest + - id: casaos-migration-tool-amd64 + binary: build/sysroot/usr/bin/casaos-migration-tool + main: ./cmd/migration-tool + env: + - CGO_ENABLED=1 + - CC=x86_64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - amd64 + - id: casaos-migration-tool-arm64 + binary: build/sysroot/usr/bin/casaos-migration-tool + main: ./cmd/migration-tool + env: + - CGO_ENABLED=1 + - CC=aarch64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm64 + - id: casaos-migration-tool-arm-7 + binary: build/sysroot/usr/bin/casaos-migration-tool + main: ./cmd/migration-tool + env: + - CGO_ENABLED=1 + - CC=arm-linux-gnueabihf-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + goos: + - linux + goarch: + - arm + goarm: + - "7" +archives: + - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}" + id: casaos + builds: + - casaos-amd64 + - casaos-arm64 + - casaos-arm-7 + replacements: + arm: arm-7 + files: + - build/**/* + - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}" + id: casaos-migration-tool + builds: + - casaos-migration-tool-amd64 + - casaos-migration-tool-arm64 + - casaos-migration-tool-arm-7 + replacements: + arm: arm-7 + files: + - build/sysroot/etc/**/* +checksum: + name_template: "checksums.txt" +snapshot: + name_template: "{{ incpatch .Version }}" +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" +# release: +# github: +# owner: IceWhaleTech +# name: CasaOS +# draft: true +# prerelease: auto +# mode: replace +# name_template: "v{{ .Version }}" +release: + github: + owner: IceWhaleTech + name: CasaOS + draft: true + prerelease: auto + mode: replace + name_template: "v{{ .Version }}" diff --git a/go.mod b/go.mod index db9ca62..6c454be 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d - github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220909125858-92fc5b2e0ae5 + github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8 github.com/IceWhaleTech/CasaOS-Gateway v0.3.6 github.com/Microsoft/go-winio v0.5.0 // indirect github.com/ambelovsky/go-structs v1.1.0 // indirect diff --git a/go.sum b/go.sum index 49a1770..0bf42e2 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220901034123-ca130f6b5ce9/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk= -github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220909125858-92fc5b2e0ae5 h1:vgAf0jVKCBo3wyjOZ4z9tB77lVrgIfz2CcQX2+4JTSI= -github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220909125858-92fc5b2e0ae5/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk= +github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8 h1:r8nhgQ6tnrn6ikXN9aLH/K4H4H64Nc0hZ6jyW2B22x0= +github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk= github.com/IceWhaleTech/CasaOS-Gateway v0.3.6 h1:2tQQo85+jzbbjqIsKKn77QlAA73bc7vZsVCFvWnK4mg= github.com/IceWhaleTech/CasaOS-Gateway v0.3.6/go.mod h1:hnZwGUzcOyiufMpVO7l3gu2gAm6Ws4TY4Nlj3kMshXA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= diff --git a/middleware/gin.go b/middleware/gin.go index d8fd836..a9b07b6 100644 --- a/middleware/gin.go +++ b/middleware/gin.go @@ -13,6 +13,7 @@ package middleware import ( "fmt" "net/http" + "runtime/debug" "strings" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" @@ -26,18 +27,18 @@ func Cors() gin.HandlerFunc { c.Header("Access-Control-Allow-Origin", "*") 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,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With") // 允许浏览器(客户端)可以解析的头部 (重要) c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") - //c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With") - //设置缓存时间 + // c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With") + // 设置缓存时间 c.Header("Access-Control-Max-Age", "172800") c.Header("Access-Control-Allow-Credentials", "true") c.Set("Content-Type", "application/json") //} - //允许类型校验 + // 允许类型校验 if method == "OPTIONS" { c.JSON(http.StatusOK, "ok!") } @@ -45,18 +46,19 @@ func Cors() gin.HandlerFunc { defer func() { if err := recover(); err != nil { fmt.Println(err) + debug.PrintStack() } }() c.Next() } } + func WriteLog() gin.HandlerFunc { return func(c *gin.Context) { if !strings.Contains(c.Request.URL.String(), "password") { loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method)) c.Next() } - } } From ff6cdb6fda57f0d4ebbacd7b625459f0950b5117 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Oct 2022 00:19:02 -0400 Subject: [PATCH 26/42] wip --- model/docker.go | 6 +- pkg/docker/helper.go | 72 ++++++++++----------- pkg/utils/command/command_helper.go | 13 ++-- pkg/utils/file/file.go | 39 +++++++----- route/route.go | 63 +++++++++--------- route/v1/app.go | 99 ++++++++++++++++++++--------- 6 files changed, 170 insertions(+), 122 deletions(-) diff --git a/model/docker.go b/model/docker.go index 20b68cc..34412cd 100644 --- a/model/docker.go +++ b/model/docker.go @@ -17,6 +17,8 @@ type DockerStatsModel struct { Previous interface{} `json:"previous"` } -type DeckerDaemonModel struct { - Graph string `json:"graph"` +// reference - https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file +type DockerDaemonConfigurationModel struct { + // e.g. `/var/lib/docker` + Root string `json:"data-root,omitempty"` } diff --git a/pkg/docker/helper.go b/pkg/docker/helper.go index be76b7d..0aef117 100644 --- a/pkg/docker/helper.go +++ b/pkg/docker/helper.go @@ -15,7 +15,6 @@ import ( ) func NewSshClient(user, password string, port string) (*ssh.Client, error) { - // connet to ssh // addr = fmt.Sprintf("%s:%d", host, port) @@ -23,10 +22,10 @@ func NewSshClient(user, password string, port string) (*ssh.Client, error) { Timeout: time.Second * 5, User: user, HostKeyCallback: ssh.InsecureIgnoreHostKey(), - //HostKeyCallback: , - //HostKeyCallback: hostKeyCallBackFunc(h.Host), + // HostKeyCallback: , + // HostKeyCallback: hostKeyCallBackFunc(h.Host), } - //if h.Type == "password" { + // if h.Type == "password" { config.Auth = []ssh.AuthMethod{ssh.Password(password)} //} else { // config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)} @@ -90,11 +89,11 @@ func (w *wsBufferWriter) Write(p []byte) (int, error) { defer w.mu.Unlock() return w.buffer.Write(p) } + func (s *SshConn) Close() { if s.Session != nil { s.Session.Close() } - } const ( @@ -102,16 +101,15 @@ const ( wsMsgResize = "resize" ) -//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin +// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { - //tells other go routine quit + // tells other go routine quit username := "" for { - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { - return "" } @@ -125,8 +123,8 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { //} switch msgObj.Type { case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) decodeBytes := []byte(msgObj.Cmd) if msgObj.Cmd == "\u007f" { if len(username) == 0 { @@ -144,7 +142,7 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil { logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed") } - //write input cmd to log buffer + // write input cmd to log buffer if _, err := logBuff.Write(decodeBytes); err != nil { logrus.WithError(err).Error("write received cmd into log buffer failed") } @@ -154,11 +152,11 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { } func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string { - //tells other go routine quit + // tells other go routine quit password := "" for { - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { logrus.WithError(err).Error("reading webSocket message failed") @@ -175,8 +173,8 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string //} switch msgObj.Type { case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) if msgObj.Cmd == "\r" { return password } @@ -194,16 +192,16 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string } } -//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin +// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) { - //tells other go routine quit + // tells other go routine quit defer setQuit(exitCh) for { select { case <-exitCh: return default: - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { logrus.WithError(err).Error("reading webSocket message failed") @@ -227,15 +225,15 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe switch msgObj.Type { case wsMsgResize: - //handle xterm.js size change + // handle xterm.js size change if msgObj.Cols > 0 && msgObj.Rows > 0 { if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil { logrus.WithError(err).Error("ssh pty change windows size failed") } } case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) decodeBytes := []byte(msgObj.Cmd) if err != nil { logrus.WithError(err).Error("websock cmd string base64 decoding failed") @@ -243,7 +241,7 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil { logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed") } - //write input cmd to log buffer + // write input cmd to log buffer if _, err := logBuff.Write(decodeBytes); err != nil { logrus.WithError(err).Error("write received cmd into log buffer failed") } @@ -253,17 +251,17 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe } func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) { - //tells other go routine quit - //defer setQuit(exitCh) + // tells other go routine quit + // defer setQuit(exitCh) - //every 120ms write combine output bytes into websocket response + // every 120ms write combine output bytes into websocket response tick := time.NewTicker(time.Millisecond * time.Duration(120)) - //for range time.Tick(120 * time.Millisecond){} + // for range time.Tick(120 * time.Millisecond){} defer tick.Stop() for { select { case <-tick.C: - //write combine output bytes into websocket response + // write combine output bytes into websocket response if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil { logrus.WithError(err).Error("ssh sending combo output to webSocket failed") return @@ -273,6 +271,7 @@ func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) } } } + func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error { if w.buffer.Len() != 0 { err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes()) @@ -284,16 +283,16 @@ func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error { return nil } -//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin +// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) { - //tells other go routine quit + // tells other go routine quit defer setQuit(exitCh) for { select { case <-exitCh: return default: - //read websocket msg + // read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { logrus.WithError(err).Error("reading webSocket message failed") @@ -317,15 +316,15 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit switch msgObj.Type { case wsMsgResize: - //handle xterm.js size change + // handle xterm.js size change if msgObj.Cols > 0 && msgObj.Rows > 0 { if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil { logrus.WithError(err).Error("ssh pty change windows size failed") } } case wsMsgCmd: - //handle xterm.js stdin - //decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + // handle xterm.js stdin + // decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) decodeBytes := []byte(msgObj.Cmd) if err != nil { logrus.WithError(err).Error("websock cmd string base64 decoding failed") @@ -333,7 +332,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil { logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed") } - //write input cmd to log buffer + // write input cmd to log buffer if _, err := logBuff.Write(decodeBytes); err != nil { logrus.WithError(err).Error("write received cmd into log buffer failed") } @@ -341,6 +340,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit } } } + func (ssConn *SshConn) SessionWait(quitChan chan bool) { if err := ssConn.Session.Wait(); err != nil { logrus.WithError(err).Error("ssh session wait failed") @@ -395,7 +395,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) { if err = json2.Unmarshal(p, &msgObj); err != nil { writer.Write(p) } else if msgObj.Type == wsMsgResize { - //writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r")) + // writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r")) } } } diff --git a/pkg/utils/command/command_helper.go b/pkg/utils/command/command_helper.go index 9a2fded..a47b288 100644 --- a/pkg/utils/command/command_helper.go +++ b/pkg/utils/command/command_helper.go @@ -35,8 +35,8 @@ func ExecResultStrArray(cmdStr string) []string { fmt.Println(err) return nil } - //str, err := ioutil.ReadAll(stdout) - var networklist = []string{} + // str, err := ioutil.ReadAll(stdout) + networklist := []string{} outputBuf := bufio.NewReader(stdout) for { output, _, err := outputBuf.ReadLine() @@ -54,6 +54,8 @@ func ExecResultStrArray(cmdStr string) []string { func ExecResultStr(cmdStr string) string { cmd := exec.Command("/bin/bash", "-c", cmdStr) + println(cmd.String()) + stdout, err := cmd.StdoutPipe() if err != nil { fmt.Println(err) @@ -73,7 +75,7 @@ func ExecResultStr(cmdStr string) string { return string(str) } -//执行 lsblk 命令 +// 执行 lsblk 命令 func ExecLSBLK() []byte { output, err := exec.Command("lsblk", "-O", "-J", "-b").Output() if err != nil { @@ -83,7 +85,7 @@ func ExecLSBLK() []byte { return output } -//执行 lsblk 命令 +// 执行 lsblk 命令 func ExecLSBLKByPath(path string) []byte { output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output() if err != nil { @@ -93,7 +95,7 @@ func ExecLSBLKByPath(path string) []byte { return output } -//exec smart +// exec smart func ExecSmartCTLByPath(path string) []byte { timeout := 3 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) @@ -107,6 +109,5 @@ func ExecSmartCTLByPath(path string) []byte { } func ExecEnabledSMART(path string) { - exec.Command("smartctl", "-s on", path).Output() } diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go index b08dcda..e7fed65 100644 --- a/pkg/utils/file/file.go +++ b/pkg/utils/file/file.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "log" "mime/multipart" @@ -60,7 +61,7 @@ func MkDir(src string) error { if err != nil { return err } - os.Chmod(src, 0777) + os.Chmod(src, 0o777) return nil } @@ -103,7 +104,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) { return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err) } - f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) + f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644) if err != nil { return nil, fmt.Errorf("Fail to OpenFile :%v", err) } @@ -113,7 +114,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) { // 判断所给路径文件/文件夹是否存在 func Exists(path string) bool { - _, err := os.Stat(path) //os.Stat获取文件信息 + _, err := os.Stat(path) // os.Stat获取文件信息 if err != nil { if os.IsExist(err) { return true @@ -147,7 +148,7 @@ func CreateFile(path string) error { } func CreateFileAndWriteContent(path string, content string) error { - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666) if err != nil { return err } @@ -163,7 +164,7 @@ func CreateFileAndWriteContent(path string, content string) error { // IsNotExistMkDir create a directory if it does not exist func IsNotExistCreateFile(src string) error { - if notExist := CheckNotExist(src); notExist == true { + if notExist := CheckNotExist(src); notExist { if err := CreateFile(src); err != nil { return err } @@ -267,7 +268,7 @@ func CopySingleFile(src, dst, style string) error { return os.Chmod(dst, srcinfo.Mode()) } -//Check for duplicate file names +// Check for duplicate file names func GetNoDuplicateFileName(fullPath string) string { path, fileName := filepath.Split(fullPath) fileSuffix := path2.Ext(fileName) @@ -293,7 +294,7 @@ func CopyDir(src string, dst string, style string) error { } return nil } - //dstPath := dst + // dstPath := dst lastPath := src[strings.LastIndex(src, "/")+1:] dst += "/" + lastPath // for i := 0; Exists(dst); i++ { @@ -314,7 +315,7 @@ func CopyDir(src string, dst string, style string) error { } for _, fd := range fds { srcfp := path.Join(src, fd.Name()) - dstfp := dst //path.Join(dst, fd.Name()) + dstfp := dst // path.Join(dst, fd.Name()) if fd.IsDir() { if err = CopyDir(srcfp, dstfp, style); err != nil { @@ -336,10 +337,17 @@ func WriteToPath(data []byte, path, name string) error { } else { fullPath += "/" + name } - IsNotExistCreateFile(fullPath) + return WriteToFullPath(data, fullPath, 0o666) +} + +func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error { + if err := IsNotExistCreateFile(fullPath); err != nil { + return err + } + file, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, - 0666, + perm, ) if err != nil { return err @@ -350,16 +358,15 @@ func WriteToPath(data []byte, path, name string) error { return err } -//最终拼接 +// 最终拼接 func SpliceFiles(dir, path string, length int, startPoint int) error { - fullPath := path IsNotExistCreateFile(fullPath) file, _ := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, - 0666, + 0o666, ) defer file.Close() bufferedWriter := bufio.NewWriter(file) @@ -380,7 +387,6 @@ func SpliceFiles(dir, path string, length int, startPoint int) error { } func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) { - switch t { case "zip", "": return ".zip", archiver.NewZip(), nil @@ -400,8 +406,8 @@ func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) { return "", nil, errors.New("format not implemented") } } -func AddFile(ar archiver.Writer, path, commonPath string) error { +func AddFile(ar archiver.Writer, path, commonPath string) error { info, err := os.Stat(path) if err != nil { return err @@ -447,6 +453,7 @@ func AddFile(ar archiver.Writer, path, commonPath string) error { return nil } + func CommonPrefix(sep byte, paths ...string) string { // Handle special cases. switch len(paths) { @@ -513,7 +520,7 @@ func GetFileOrDirSize(path string) (int64, error) { return fileInfo.Size(), nil } -//getFileSize get file size by path(B) +// getFileSize get file size by path(B) func DirSizeB(path string) (int64, error) { var size int64 err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { diff --git a/route/route.go b/route/route.go index 110fd69..8b254f8 100644 --- a/route/route.go +++ b/route/route.go @@ -11,7 +11,6 @@ import ( ) func InitRouter() *gin.Engine { - r := gin.Default() r.Use(middleware.Cors()) @@ -35,7 +34,7 @@ func InitRouter() *gin.Engine { // r.GET("/v1/users/image", v1.GetUserImage) // r.GET("/v1/users/status", v1.GetUserStatus) //init/check - //r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check + // r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port @@ -73,7 +72,7 @@ func InitRouter() *gin.Engine { v1AppsGroup := v1Group.Group("/apps") v1AppsGroup.Use() { - v1AppsGroup.GET("", v1.AppList) //list + v1AppsGroup.GET("", v1.AppList) // list v1AppsGroup.GET("/:id", v1.AppInfo) } v1ContainerGroup := v1Group.Group("/container") @@ -84,24 +83,24 @@ func InitRouter() *gin.Engine { v1ContainerGroup.GET("/usage", v1.AppUsageList) v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id - v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config + v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) // app/install/config - v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress + v1ContainerGroup.GET("/:id/state", v1.GetContainerState) // app/state/:id ?state=install_progress // there are problems, temporarily do not deal with - v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id - v1ContainerGroup.POST("", v1.InstallApp) //app/install - //v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id + v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) // app/terminal/:id + v1ContainerGroup.POST("", v1.InstallApp) // app/install + // v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id - v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) //app/uninstall/:id - //Not used + v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) // app/uninstall/:id + // Not used v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate) - //Not used + // Not used v1ContainerGroup.POST("/share", v1.ShareAppFile) - v1ContainerGroup.GET("/info", v1.GetcontainerInfo) - v1ContainerGroup.PUT("/info", v1.PutcontainerInfo) + v1ContainerGroup.GET("/info", v1.GetDockerDaemonConfiguration) + v1ContainerGroup.PUT("/info", v1.PutDockerDaemonConfiguration) } v1AppCategoriesGroup := v1Group.Group("/app-categories") @@ -113,19 +112,19 @@ func InitRouter() *gin.Engine { v1SysGroup := v1Group.Group("/sys") v1SysGroup.Use() { - v1SysGroup.GET("/version", v1.GetSystemCheckVersion) //version/check + v1SysGroup.GET("/version", v1.GetSystemCheckVersion) // version/check v1SysGroup.POST("/update", v1.SystemUpdate) - v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info + v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) // hardware/info v1SysGroup.GET("/wsssh", v1.WsSsh) v1SysGroup.POST("/ssh-login", v1.PostSshLogin) - //v1SysGroup.GET("/config", v1.GetSystemConfig) //delete - //v1SysGroup.POST("/config", v1.PostSetSystemConfig) - v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs - //v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete - //v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete + // v1SysGroup.GET("/config", v1.GetSystemConfig) //delete + // v1SysGroup.POST("/config", v1.PostSetSystemConfig) + v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) // error/logs + // v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete + // v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete v1SysGroup.POST("/stop", v1.PostKillCasaOS) @@ -141,31 +140,31 @@ func InitRouter() *gin.Engine { v1SysGroup.GET("/server-info", nil) v1SysGroup.PUT("/server-info", nil) v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus) - //v1SysGroup.GET("/port", v1.GetCasaOSPort) - //v1SysGroup.PUT("/port", v1.PutCasaOSPort) + // v1SysGroup.GET("/port", v1.GetCasaOSPort) + // v1SysGroup.PUT("/port", v1.PutCasaOSPort) v1SysGroup.GET("/proxy", v1.GetSystemProxy) } v1PortGroup := v1Group.Group("/port") v1PortGroup.Use() { - v1PortGroup.GET("/", v1.GetPort) //app/port - v1PortGroup.GET("/state/:port", v1.PortCheck) //app/check/:port + v1PortGroup.GET("/", v1.GetPort) // app/port + v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port } v1FileGroup := v1Group.Group("/file") v1FileGroup.Use() { - v1FileGroup.GET("", v1.GetDownloadSingleFile) //download/:path + v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path v1FileGroup.POST("", v1.PostCreateFile) v1FileGroup.PUT("", v1.PutFileContent) v1FileGroup.PUT("/name", v1.RenamePath) - //file/rename - v1FileGroup.GET("/content", v1.GetFilerContent) //file/read + // file/rename + v1FileGroup.GET("/content", v1.GetFilerContent) // file/read - //File uploads need to be handled separately, and will not be modified here + // File uploads need to be handled separately, and will not be modified here v1FileGroup.POST("/upload", v1.PostFileUpload) v1FileGroup.GET("/upload", v1.GetFileUpload) - //v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) + // v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) } v1FolderGroup := v1Group.Group("/folder") v1FolderGroup.Use() @@ -178,9 +177,9 @@ func InitRouter() *gin.Engine { v1BatchGroup.Use() { - v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete + v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir) - v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate + v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate v1BatchGroup.GET("", v1.GetDownloadFile) } v1ImageGroup := v1Group.Group("/image") @@ -211,7 +210,7 @@ func InitRouter() *gin.Engine { v1NotifyGroup.Use() { v1NotifyGroup.POST("/:path", v1.PostNotifyMessage) - //merge to system + // merge to system v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify) } } diff --git a/route/v1/app.go b/route/v1/app.go index cc2ee00..dec60ef 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -2,8 +2,9 @@ package v1 import ( "encoding/json" - "fmt" "io/ioutil" + "net/http" + "path/filepath" "strconv" "github.com/IceWhaleTech/CasaOS/model" @@ -16,6 +17,10 @@ import ( "github.com/gin-gonic/gin" ) +const ( + dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json" +) + // @Summary 获取远程列表 // @Produce application/json // @Accept application/json @@ -29,8 +34,7 @@ import ( // @Success 200 {string} string "ok" // @Router /app/list [get] func AppList(c *gin.Context) { - - //service.MyService.Docker().DockerContainerCommit("test2") + // service.MyService.Docker().DockerContainerCommit("test2") index := c.DefaultQuery("index", "1") size := c.DefaultQuery("size", "10000") @@ -139,7 +143,7 @@ func MyAppList(c *gin.Context) { func AppUsageList(c *gin.Context) { list := service.MyService.App().GetHardwareUsage() c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list}) - //c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil}) + // c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil}) } // @Summary 应用详情 @@ -151,7 +155,6 @@ func AppUsageList(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /app/appinfo/{id} [get] func AppInfo(c *gin.Context) { - id := c.Param("id") language := c.GetHeader("Language") info, err := service.MyService.Casa().GetServerAppInfo(id, "", language) @@ -213,7 +216,7 @@ func AppInfo(c *gin.Context) { // return c1.Type < c2.Type // } - //sort + // sort // if info.NetworkModel != "host" { // sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts) // sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts) @@ -265,53 +268,89 @@ func ShareAppFile(c *gin.Context) { c.JSON(common_err.SUCCESS, json.RawMessage(content)) } -func GetcontainerInfo(c *gin.Context) { +func GetDockerDaemonConfiguration(c *gin.Context) { // info, err := service.MyService.Docker().GetDockerInfo() // 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 // } - daemon := model.DeckerDaemonModel{} + dockerConfig := model.DockerDaemonConfigurationModel{} data := make(map[string]interface{}, 1) data["docker_root_dir"] = "" - if file.Exists("/etc/docker/daemon.json") { - byteResult := file.ReadFullFile("/etc/docker/daemon.json") - err := json.Unmarshal(byteResult, &daemon) + + // TODO read dockerRootDir from /etc/casaos/casaos.conf + if file.Exists(dockerDaemonConfigurationFilePath) { + byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) + err := json.Unmarshal(byteResult, &dockerConfig) if err != nil { c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) return } - data["docker_root_dir"] = daemon.Graph + + if dockerConfig.Root != "" { + data["docker_root_dir"] = dockerConfig.Root + } else { + data["docker_root_dir"] = "/var/lib/docker" + } } c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) } -func PutcontainerInfo(c *gin.Context) { + +func PutDockerDaemonConfiguration(c *gin.Context) { js := make(map[string]interface{}) - err := c.BindJSON(&js) - if err != nil { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + if err := c.BindJSON(&js); err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) return } - dockerRootDir := js["docker_root_dir"].(string) - daemon := model.DeckerDaemonModel{} - if file.Exists("/etc/docker/daemon.json") { - byteResult := file.ReadFullFile("/etc/docker/daemon.json") - err := json.Unmarshal(byteResult, &daemon) + + value, ok := js["docker_root_dir"] + if !ok { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "`docker_root_dir` should not empty"}) + return + } + + dockerConfig := model.DockerDaemonConfigurationModel{} + if file.Exists(dockerDaemonConfigurationFilePath) { + byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) + err := json.Unmarshal(byteResult, &dockerConfig) if err != nil { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err.Error()}) return } } - if !file.Exists(dockerRootDir) { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) + + dockerRootDir := value.(string) + if dockerRootDir == "/" { + dockerConfig.Root = "" // omitempty - empty string will not be serialized + } else { + if !file.Exists(dockerRootDir) { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) + return + } + + dockerConfig.Root = filepath.Join(dockerRootDir, "docker") + + if err := file.IsNotExistMkDir(dockerConfig.Root); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err.Error()}) + return + } + } + + byteMode, err := json.Marshal(dockerConfig) + if err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker config", Data: dockerConfig}) return } - daemon.Graph = dockerRootDir - byteMode, _ := json.Marshal(daemon) - file.WriteToPath(byteMode, "/etc/docker", "daemon.json") - fmt.Println(command.ExecResultStr("systemctl daemon-reload")) - fmt.Println(command.ExecResultStr("systemctl restart docker")) + if err := file.WriteToFullPath(byteMode, dockerDaemonConfigurationFilePath, 0o644); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err.Error()}) + return + } - c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) + // TODO also write dockerRootDir to /etc/casaos/casaos.conf + + println(command.ExecResultStr("systemctl daemon-reload")) + println(command.ExecResultStr("systemctl restart docker")) + + c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) } From cbbb907d6aa1bce9741c2b03791dab6a4672f3f4 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Oct 2022 16:55:20 -0400 Subject: [PATCH 27/42] wip --- route/v1/app.go | 59 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/route/v1/app.go b/route/v1/app.go index dec60ef..8e39347 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -18,6 +18,7 @@ import ( ) const ( + dockerRootDirFilePath = "/var/lib/casaos/docker_root" dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json" ) @@ -274,36 +275,27 @@ func GetDockerDaemonConfiguration(c *gin.Context) { // 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 // } - dockerConfig := model.DockerDaemonConfigurationModel{} - data := make(map[string]interface{}, 1) - data["docker_root_dir"] = "" + data := make(map[string]interface{}) - // TODO read dockerRootDir from /etc/casaos/casaos.conf - if file.Exists(dockerDaemonConfigurationFilePath) { - byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) - err := json.Unmarshal(byteResult, &dockerConfig) + if file.Exists(dockerRootDirFilePath) { + buf := file.ReadFullFile(dockerRootDirFilePath) + err := json.Unmarshal(buf, &data) if err != nil { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err}) return } - - if dockerConfig.Root != "" { - data["docker_root_dir"] = dockerConfig.Root - } else { - data["docker_root_dir"] = "/var/lib/docker" - } } c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) } func PutDockerDaemonConfiguration(c *gin.Context) { - js := make(map[string]interface{}) - if err := c.BindJSON(&js); err != nil { - c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + request := make(map[string]interface{}) + if err := c.BindJSON(&request); err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err}) return } - value, ok := js["docker_root_dir"] + value, ok := request["docker_root_dir"] if !ok { c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "`docker_root_dir` should not empty"}) return @@ -314,7 +306,7 @@ func PutDockerDaemonConfiguration(c *gin.Context) { byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) err := json.Unmarshal(byteResult, &dockerConfig) if err != nil { - c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err.Error()}) + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err}) return } } @@ -331,26 +323,33 @@ func PutDockerDaemonConfiguration(c *gin.Context) { dockerConfig.Root = filepath.Join(dockerRootDir, "docker") if err := file.IsNotExistMkDir(dockerConfig.Root); err != nil { - c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err.Error()}) + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err}) return } } - byteMode, err := json.Marshal(dockerConfig) - if err != nil { + if buf, err := json.Marshal(request); err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker root json", Data: err}) + return + } else { + if err := file.WriteToFullPath(buf, dockerRootDirFilePath, 0o644); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write " + dockerRootDirFilePath, Data: err}) + return + } + } + + if buf, err := json.Marshal(dockerConfig); err != nil { c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker config", Data: dockerConfig}) return + } else { + if err := file.WriteToFullPath(buf, dockerDaemonConfigurationFilePath, 0o644); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err}) + return + } } - if err := file.WriteToFullPath(byteMode, dockerDaemonConfigurationFilePath, 0o644); err != nil { - c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err.Error()}) - return - } - - // TODO also write dockerRootDir to /etc/casaos/casaos.conf - println(command.ExecResultStr("systemctl daemon-reload")) println(command.ExecResultStr("systemctl restart docker")) - c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) + c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: request}) } From dd66f731572d7bec72d33706e6ece7deb479a07a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Oct 2022 19:12:12 -0400 Subject: [PATCH 28/42] wip --- middleware/gin.go | 64 ----------------------- pkg/utils/file/file.go | 12 +++-- route/route.go | 20 ++++++-- route/v1/file.go | 112 ++++++++++++++++++++++++++--------------- 4 files changed, 97 insertions(+), 111 deletions(-) delete mode 100644 middleware/gin.go diff --git a/middleware/gin.go b/middleware/gin.go deleted file mode 100644 index a9b07b6..0000000 --- a/middleware/gin.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2021-10-08 10:29:08 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-07-22 11:06:07 - * @FilePath: /CasaOS/middleware/gin.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package middleware - -import ( - "fmt" - "net/http" - "runtime/debug" - "strings" - - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" - "github.com/gin-gonic/gin" - "go.uber.org/zap" -) - -func Cors() gin.HandlerFunc { - return func(c *gin.Context) { - method := c.Request.Method - - c.Header("Access-Control-Allow-Origin", "*") - 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,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With") - // 允许浏览器(客户端)可以解析的头部 (重要) - c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") - // c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With") - // 设置缓存时间 - c.Header("Access-Control-Max-Age", "172800") - c.Header("Access-Control-Allow-Credentials", "true") - c.Set("Content-Type", "application/json") - //} - - // 允许类型校验 - if method == "OPTIONS" { - c.JSON(http.StatusOK, "ok!") - } - - defer func() { - if err := recover(); err != nil { - fmt.Println(err) - debug.PrintStack() - } - }() - - c.Next() - } -} - -func WriteLog() gin.HandlerFunc { - return func(c *gin.Context) { - if !strings.Contains(c.Request.URL.String(), "password") { - loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method)) - c.Next() - } - } -} diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go index e7fed65..1fd9de2 100644 --- a/pkg/utils/file/file.go +++ b/pkg/utils/file/file.go @@ -362,21 +362,27 @@ func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error { func SpliceFiles(dir, path string, length int, startPoint int) error { fullPath := path - IsNotExistCreateFile(fullPath) + if err := IsNotExistCreateFile(fullPath); err != nil { + return err + } file, _ := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o666, ) + defer file.Close() + bufferedWriter := bufio.NewWriter(file) + + // todo: here should have a goroutine to remove each partial file after it is read, to save disk space + for i := 0; i < length+startPoint; i++ { data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint)) if err != nil { return err } - _, err = bufferedWriter.Write(data) - if err != nil { + if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write return err } } diff --git a/route/route.go b/route/route.go index 8b254f8..a876849 100644 --- a/route/route.go +++ b/route/route.go @@ -1,8 +1,10 @@ package route import ( + "os" + + "github.com/IceWhaleTech/CasaOS-Common/middleware" "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" - "github.com/IceWhaleTech/CasaOS/middleware" "github.com/IceWhaleTech/CasaOS/pkg/config" v1 "github.com/IceWhaleTech/CasaOS/route/v1" @@ -11,12 +13,22 @@ import ( ) func InitRouter() *gin.Engine { - r := gin.Default() + ginMode := gin.ReleaseMode + if config.ServerInfo.RunMode != "" { + ginMode = config.ServerInfo.RunMode + } + if os.Getenv(gin.EnvGinMode) != "" { + ginMode = os.Getenv(gin.EnvGinMode) + } + gin.SetMode(ginMode) + r := gin.New() + r.Use(gin.Recovery()) r.Use(middleware.Cors()) - r.Use(middleware.WriteLog()) r.Use(gzip.Gzip(gzip.DefaultCompression)) - gin.SetMode(config.ServerInfo.RunMode) + if ginMode != gin.ReleaseMode { + r.Use(middleware.WriteLog()) + } // r.StaticFS("/ui", http.FS(web.Static)) // r.GET("/", WebUIHome) diff --git a/route/v1/file.go b/route/v1/file.go index 396074d..64a5f69 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -18,9 +18,11 @@ import ( "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" + "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" "github.com/gin-gonic/gin" uuid "github.com/satori/go.uuid" + "go.uber.org/zap" ) // @Summary 读取文件 @@ -47,7 +49,7 @@ func GetFilerContent(c *gin.Context) { }) return } - //文件读取任务是将文件内容读取到内存中。 + // 文件读取任务是将文件内容读取到内存中。 info, err := ioutil.ReadFile(filePath) if err != nil { c.JSON(common_err.SERVICE_ERROR, model.Result{ @@ -83,7 +85,6 @@ func GetLocalFile(c *gin.Context) { return } c.File(path) - return } // @Summary download @@ -96,7 +97,6 @@ func GetLocalFile(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/download [get] func GetDownloadFile(c *gin.Context) { - t := c.Query("format") files := c.Query("files") @@ -135,11 +135,11 @@ func GetDownloadFile(c *gin.Context) { } if !info.IsDir() { - //打开文件 + // 打开文件 fileTmp, _ := os.Open(filePath) defer fileTmp.Close() - //获取文件的名称 + // 获取文件的名称 fileName := path.Base(filePath) c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) c.File(filePath) @@ -179,7 +179,6 @@ func GetDownloadFile(c *gin.Context) { log.Printf("Failed to archive %s: %v", fname, err) } } - } func GetDownloadSingleFile(c *gin.Context) { @@ -202,7 +201,7 @@ func GetDownloadSingleFile(c *gin.Context) { defer fileTmp.Close() fileName := path.Base(filePath) - //c.Header("Content-Disposition", "inline") + // c.Header("Content-Disposition", "inline") c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) c.File(filePath) } @@ -248,7 +247,7 @@ func DirPath(c *gin.Context) { info[i].Extensions = ex } } - //Hide the files or folders in operation + // Hide the files or folders in operation fileQueue := make(map[string]string) if len(service.OpStrArr) > 0 { for _, v := range service.OpStrArr { @@ -361,7 +360,6 @@ func PostCreateFile(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/upload [get] func GetFileUpload(c *gin.Context) { - relative := c.Query("relativePath") fileName := c.Query("filename") chunkNumber := c.Query("chunkNumber") @@ -405,55 +403,92 @@ func PostFileUpload(c *gin.Context) { hash := file.GetHashByContent([]byte(fileName)) if len(path) == 0 { - c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + loger.Error("path should not be empty") + c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return } + tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" if fileName != relative { dirPath = strings.TrimSuffix(relative, fileName) tempDir += dirPath - file.MkDir(path + "/" + dirPath) + if err := file.MkDir(path + "/" + dirPath); err != nil { + loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } } path += "/" + relative if !file.CheckNotExist(tempDir + chunkNumber) { - file.RMDir(tempDir + chunkNumber) + if err := file.RMDir(tempDir + chunkNumber); err != nil { + loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } } if totalChunks > 1 { - file.IsNotExistMkDir(tempDir) - - out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644) - defer out.Close() - _, err := io.Copy(out, f) - 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()}) + if err := file.IsNotExistMkDir(tempDir); err != nil { + loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return } + + out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644) + if err != nil { + loger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + defer out.Close() + + if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy + loger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + fileNum, err := ioutil.ReadDir(tempDir) + if err != nil { + loger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + if totalChunks == len(fileNum) { + if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil { + loger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + if err := file.RMDir(tempDir); err != nil { + loger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + } } else { - out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644) - defer out.Close() - _, err := io.Copy(out, f) + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644) 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()}) + loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return } - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) - return - } - fileNum, err := ioutil.ReadDir(tempDir) - 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 - } - if totalChunks == len(fileNum) { - file.SpliceFiles(tempDir, path, totalChunks, 1) - file.RMDir(tempDir) - } - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) + defer out.Close() + + if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy + loger.Error("error when trying to write to `"+path+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) + return + } + } + c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) } // @Summary copy or move file @@ -465,7 +500,6 @@ func PostFileUpload(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/operate [post] func PostOperateFileOrDir(c *gin.Context) { - list := model.FileOperate{} c.ShouldBind(&list) @@ -515,7 +549,6 @@ func PostOperateFileOrDir(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/delete [delete] func DeleteFile(c *gin.Context) { - paths := []string{} c.ShouldBind(&paths) if len(paths) == 0 { @@ -547,7 +580,6 @@ func DeleteFile(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/update [put] func PutFileContent(c *gin.Context) { - fi := model.FileUpdate{} c.ShouldBind(&fi) @@ -557,7 +589,7 @@ func PutFileContent(c *gin.Context) { c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)}) return } - //err := os.Remove(path) + // err := os.Remove(path) err := os.RemoveAll(fi.FilePath) if err != nil { c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err}) From 0f3d3e82f56d09e162b61c29e021121e8f608e6b Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 11 Oct 2022 23:23:21 -0400 Subject: [PATCH 29/42] wip --- .../migration/script.d/03-migrate-casaos.sh | 98 +++++----- .../migration/service.d/casaos/migration.list | 7 +- cmd/migration-tool/main.go | 10 +- cmd/migration-tool/migration-034-035.go | 182 ------------------ cmd/migration-tool/migration-036.go | 74 ------- 5 files changed, 54 insertions(+), 317 deletions(-) delete mode 100644 cmd/migration-tool/migration-034-035.go delete mode 100644 cmd/migration-tool/migration-036.go diff --git a/build/scripts/migration/script.d/03-migrate-casaos.sh b/build/scripts/migration/script.d/03-migrate-casaos.sh index a48c437..719ff60 100644 --- a/build/scripts/migration/script.d/03-migrate-casaos.sh +++ b/build/scripts/migration/script.d/03-migrate-casaos.sh @@ -60,8 +60,6 @@ BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../.. SOURCE_ROOT=${BUILD_PATH}/sysroot APP_NAME="casaos" -APP_NAME_FORMAL="CasaOS" -#APP_NAME_FORMAL="casaos-alpha" # check if migration is needed SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin @@ -85,45 +83,6 @@ if [ "${NEED_MIGRATION}" = "false" ]; then exit 0 fi -MIGRATION_SERVICE_DIR=${1} - -if [ -z "${MIGRATION_SERVICE_DIR}" ]; then - MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME} -fi -MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list -MIGRATION_PATH=() - -CURRENT_VERSION_FOUND="false" - -# a VERSION_PAIR looks like "v0.3.5 v0.3.6-alpha2" -# -# - "v0.3.5" is the current version installed on this host -# - "v0.3.6-alpha2" is the version of the migration tool from GitHub -while read -r VERSION_PAIR; do - if [ -z "${VERSION_PAIR}" ]; then - continue - fi - - # obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2" - VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1) - - # obtain "v0.3.6-alpha2" from "v0.3.5 v0.3.6-alpha2" - VER2=$(echo "${VERSION_PAIR}" | cut -d' ' -f2) - - if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then - CURRENT_VERSION_FOUND="true" - fi - - if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then - MIGRATION_PATH+=("${VER2// /}") - fi -done < "${MIGRATION_LIST_FILE}" - -if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then - __warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}" - exit 0 -fi - ARCH="unknown" case $(uname -m) in @@ -141,22 +100,59 @@ case $(uname -m) in ;; esac +__info "ARCH: ${ARCH}" + +MIGRATION_SERVICE_DIR=${1} + +if [ -z "${MIGRATION_SERVICE_DIR}" ]; then + MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME} +fi +MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list +MIGRATION_PATH=() + +CURRENT_VERSION_FOUND="false" + +# a VERSION_PAIR looks like "v0.3.5 " +# +# - "v0.3.5" is the current version installed on this host +# - "" is the url of the migration tool +while read -r VERSION_PAIR; do + if [ -z "${VERSION_PAIR}" ]; then + continue + fi + + # obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2" + VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1) + + # obtain "" from "v0.3.5 " + URL=$(eval echo "${VERSION_PAIR}" | cut -d' ' -f2) + + if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then + CURRENT_VERSION_FOUND="true" + fi + + if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then + MIGRATION_PATH+=("${URL// /}") + fi +done < "${MIGRATION_LIST_FILE}" + +if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then + __warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}" + exit 0 +fi + pushd "${MIGRATION_SERVICE_DIR}" -{ for VER2 in "${MIGRATION_PATH[@]}"; do - - - MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz +{ for URL in "${MIGRATION_PATH[@]}"; do + MIGRATION_TOOL_FILE=$(basename "${URL}") if [ -f "${MIGRATION_TOOL_FILE}" ]; then __info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading." continue fi - # MIGRATION_TOOL_URL=http://192.168.2.197:8000/v1/package/migration?type=release&name="${APP_NAME_FORMAL}"&version=${VER2}&arch=${ARCH} - MIGRATION_TOOL_URL=https://github.com/IceWhaleTech/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz - echo "Dowloading ${MIGRATION_TOOL_URL}..." - curl -sL -O "${MIGRATION_TOOL_URL}" + __info "Dowloading ${URL}..." + curl -fsSL -o "${MIGRATION_TOOL_FILE}" -O "${URL}" done } || { popd @@ -164,8 +160,8 @@ pushd "${MIGRATION_SERVICE_DIR}" } { - for VER2 in "${MIGRATION_PATH[@]}"; do - MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz + for URL in "${MIGRATION_PATH[@]}"; do + MIGRATION_TOOL_FILE=$(basename "${URL}") __info "Extracting ${MIGRATION_TOOL_FILE}..." tar zxvf "${MIGRATION_TOOL_FILE}" || __error "Failed to extract ${MIGRATION_TOOL_FILE}" diff --git a/build/scripts/migration/service.d/casaos/migration.list b/build/scripts/migration/service.d/casaos/migration.list index d3ce03f..c780280 100644 --- a/build/scripts/migration/service.d/casaos/migration.list +++ b/build/scripts/migration/service.d/casaos/migration.list @@ -1,4 +1,3 @@ -LEGACY_WITHOUT_VERSION v0.3.6 -v0.3.5 v0.3.6 -v0.3.5.1 v0.3.6 -v0.3.6 v0.3.7 +LEGACY_WITHOUT_VERSION https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz +v0.3.5 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz +v0.3.5.1 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go index 93b065d..d28663c0 100644 --- a/cmd/migration-tool/main.go +++ b/cmd/migration-tool/main.go @@ -83,8 +83,7 @@ func main() { } migrationTools := []interfaces.MigrationTool{ - NewMigrationToolFor_035(), - NewMigrationToolFor_036(), + // nothing to migrate from last version } var selectedMigrationTool interfaces.MigrationTool @@ -115,8 +114,7 @@ func main() { panic(err) } - selectedMigrationTool.PostMigrate() - _logger.Info("casaos migration ok") - // panic(err) - + if err := selectedMigrationTool.PostMigrate(); err != nil { + _logger.Error("Migration succeeded, but post-migration failed: %s", err) + } } diff --git a/cmd/migration-tool/migration-034-035.go b/cmd/migration-tool/migration-034-035.go deleted file mode 100644 index 3dfed60..0000000 --- a/cmd/migration-tool/migration-034-035.go +++ /dev/null @@ -1,182 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2022-08-24 17:36:00 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-09-05 11:24:27 - * @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package main - -import ( - "io" - "io/ioutil" - "os" - "path" - "strings" - - interfaces "github.com/IceWhaleTech/CasaOS-Common" - "github.com/IceWhaleTech/CasaOS-Common/utils/version" - "github.com/IceWhaleTech/CasaOS/pkg/config" - "github.com/IceWhaleTech/CasaOS/pkg/utils/command" - "github.com/IceWhaleTech/CasaOS/pkg/utils/file" - "github.com/IceWhaleTech/CasaOS/service" -) - -type migrationTool036 struct{} - -func (u *migrationTool036) IsMigrationNeeded() (bool, error) { - - majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() - if err != nil { - if err == version.ErrLegacyVersionNotFound { - return false, nil - } - - return false, err - } - - if majorVersion > 0 { - return false, nil - } - - if minorVersion > 3 { - return false, nil - } - - if minorVersion == 3 && patchVersion > 5 { - return false, nil - } - - _logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...") - return true, nil - -} - -func (u *migrationTool036) PreMigrate() error { - - return nil -} - -func (u *migrationTool036) Migrate() error { - - if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { - service.MyService.System().UpdateUSBAutoMount("False") - service.MyService.System().ExecUSBAutoMountShell("False") - } - newAPIUrl := "https://api.casaos.io/casaos-api" - if config.ServerInfo.ServerApi == "https://api.casaos.zimaboard.com" { - config.ServerInfo.ServerApi = newAPIUrl - config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl) - config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) - } - command.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/assist.sh | bash") - if !file.CheckNotExist("/casaOS") { - command.OnlyExec("source /casaOS/server/shell/update.sh ;") - command.OnlyExec("source " + config.AppInfo.ShellPath + "/delete-old-service.sh ;") - } - - service.MyService.App().ImportApplications(true) - - src := "/casaOS/server/conf/conf.ini" - if file.Exists(src) { - dst := "/etc/casaos/casaos.conf" - source, err := os.Open(src) - if err != nil { - return err - } - defer source.Close() - - destination, err := os.Create(dst) - if err != nil { - return err - } - defer destination.Close() - _, err = io.Copy(destination, source) - if err != nil { - return err - } - - } - - if file.Exists("/casaOS/server/db") { - var fds []os.FileInfo - var err error - to := "/var/lib/casaos/db" - file.IsNotExistMkDir(to) - from := "/casaOS/server/db" - if fds, err = ioutil.ReadDir(from); err != nil { - return err - } - - for _, fd := range fds { - srcfp := path.Join(from, fd.Name()) - dstfp := path.Join(to, fd.Name()) - source, err := os.Open(srcfp) - if err != nil { - return err - } - defer source.Close() - - destination, err := os.Create(dstfp) - if err != nil { - return err - } - defer destination.Close() - _, err = io.Copy(destination, source) - if err != nil { - return err - } - } - - } - - if file.Exists("/casaOS/server/conf") { - var fds []os.FileInfo - var err error - to := "/var/lib/casaos/conf" - file.IsNotExistMkDir(to) - from := "/casaOS/server/conf" - if fds, err = ioutil.ReadDir(from); err != nil { - return err - } - - for _, fd := range fds { - fExt := path.Ext(fd.Name()) - if fExt != ".json" { - continue - } - srcfp := path.Join(from, fd.Name()) - dstfp := path.Join(to, fd.Name()) - source, err := os.Open(srcfp) - if err != nil { - return err - } - defer source.Close() - - destination, err := os.Create(dstfp) - if err != nil { - return err - } - defer destination.Close() - _, err = io.Copy(destination, source) - if err != nil { - return err - } - } - - } - - _logger.Info("update done") - return nil -} - -func (u *migrationTool036) PostMigrate() error { - return nil -} - -func NewMigrationToolFor_035() interfaces.MigrationTool { - return &migrationTool{} -} diff --git a/cmd/migration-tool/migration-036.go b/cmd/migration-tool/migration-036.go deleted file mode 100644 index b6d5410..0000000 --- a/cmd/migration-tool/migration-036.go +++ /dev/null @@ -1,74 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2022-08-24 17:36:00 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-09-05 11:24:27 - * @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package main - -import ( - "strings" - - interfaces "github.com/IceWhaleTech/CasaOS-Common" - "github.com/IceWhaleTech/CasaOS-Common/utils/version" - "github.com/IceWhaleTech/CasaOS/pkg/config" - "github.com/IceWhaleTech/CasaOS/service" -) - -type migrationTool struct{} - -func (u *migrationTool) IsMigrationNeeded() (bool, error) { - - majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() - if err != nil { - if err == version.ErrLegacyVersionNotFound { - return false, nil - } - - return false, err - } - - if majorVersion > 0 { - return false, nil - } - - if minorVersion > 3 { - return false, nil - } - - if minorVersion == 3 && patchVersion > 5 { - return false, nil - } - - _logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...") - return true, nil - -} - -func (u *migrationTool) PreMigrate() error { - - return nil -} - -func (u *migrationTool) Migrate() error { - - if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { - service.MyService.System().UpdateUSBAutoMount("False") - service.MyService.System().ExecUSBAutoMountShell("False") - } - - _logger.Info("update done") - return nil -} - -func (u *migrationTool) PostMigrate() error { - return nil -} - -func NewMigrationToolFor_036() interfaces.MigrationTool { - return &migrationTool{} -} From b61a3db611efee5a729ea2b8715eee0108984462 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 12 Oct 2022 16:12:14 -0400 Subject: [PATCH 30/42] wip --- .../setup/service.d/casaos/debian/setup-casaos.sh | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh index e083373..50c8d91 100644 --- a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh +++ b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh @@ -31,15 +31,10 @@ if [ ! -f "${CONF_FILE}" ]; then cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}" fi -if systemctl is-active "${APP_NAME}.service" &>/dev/null ;then - echo "server started" -else - # enable and start service - systemctl daemon-reload +rm -rf /etc/systemd/system/casaos.service # remove old service file - echo "Enabling service..." - systemctl enable --force --no-ask-password "${APP_NAME}.service" +systemctl daemon-reload - #echo "Starting service..." - #systemctl start --force --no-ask-password "${APP_NAME}.service" -fi \ No newline at end of file +# enable service (without starting) +echo "Enabling service..." +systemctl enable --force --no-ask-password "${APP_NAME}.service" From 6ea3cdb3641552aa4baf10749f5d6acbcaf44280 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Thu, 13 Oct 2022 04:45:17 +0100 Subject: [PATCH 31/42] Utilization interface to supplement disk information --- route/v1/system.go | 6 ++++-- service/notify.go | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/route/v1/system.go b/route/v1/system.go index 29fbcf2..95674e7 100644 --- a/route/v1/system.go +++ b/route/v1/system.go @@ -270,7 +270,7 @@ func GetSystemHardwareInfo(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /sys/utilization [get] func GetSystemUtilization(c *gin.Context) { - var data = make(map[string]interface{}, 6) + var data = make(map[string]interface{}) cpu := service.MyService.System().GetCpuPercent() num := service.MyService.System().GetCpuCoreNum() cpuData := make(map[string]interface{}) @@ -299,7 +299,9 @@ func GetSystemUtilization(c *gin.Context) { } data["net"] = newNet - + for k, v := range service.MyService.Notify().GetSystemTempMap() { + data[k] = v + } c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) } diff --git a/service/notify.go b/service/notify.go index 05d3162..5e31ebe 100644 --- a/service/notify.go +++ b/service/notify.go @@ -37,6 +37,7 @@ type NotifyServer interface { SendStorageBySocket(message notify.StorageMessage) SendNotify(path string, message map[string]interface{}) SettingSystemTempData(message map[string]interface{}) + GetSystemTempMap() map[string]interface{} } type notifyServer struct { @@ -442,7 +443,11 @@ func SendMeg() { // } // } +func (i *notifyServer) GetSystemTempMap() map[string]interface{} { + return i.SystemTempMap + +} func NewNotifyService(db *gorm.DB) NotifyServer { return ¬ifyServer{db: db, SystemTempMap: make(map[string]interface{})} } From 46a37f05100f0312695f4747f6df0f19db9a4291 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Thu, 13 Oct 2022 11:32:30 +0100 Subject: [PATCH 32/42] fix upload file --- pkg/utils/file/file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go index 1fd9de2..10e91f7 100644 --- a/pkg/utils/file/file.go +++ b/pkg/utils/file/file.go @@ -377,7 +377,7 @@ func SpliceFiles(dir, path string, length int, startPoint int) error { // todo: here should have a goroutine to remove each partial file after it is read, to save disk space - for i := 0; i < length+startPoint; i++ { + for i := 0; i < length+startPoint-1; i++ { data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint)) if err != nil { return err From df0f0159443be324dfc616acb322b29f25e0a1c4 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 13 Oct 2022 16:09:19 -0400 Subject: [PATCH 33/42] wip --- route/route.go | 3 --- route/v1/system.go | 61 +++++----------------------------------------- service/system.go | 42 +++++++++++++------------------ 3 files changed, 23 insertions(+), 83 deletions(-) diff --git a/route/route.go b/route/route.go index a876849..19f2b3b 100644 --- a/route/route.go +++ b/route/route.go @@ -146,9 +146,6 @@ func InitRouter() *gin.Engine { // v1SysGroup.GET("/disk", v1.GetSystemDiskInfo) // v1SysGroup.GET("/network", v1.GetSystemNetInfo) - v1SysGroup.PUT("/usb-auto-mount", v1.PutSystemUSBAutoMount) ///sys/usb/:status - v1SysGroup.GET("/usb-auto-mount", v1.GetSystemUSBAutoMount) ///sys/usb/status - v1SysGroup.GET("/server-info", nil) v1SysGroup.PUT("/server-info", nil) v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus) diff --git a/route/v1/system.go b/route/v1/system.go index 95674e7..9872ee3 100644 --- a/route/v1/system.go +++ b/route/v1/system.go @@ -164,51 +164,6 @@ func PostKillCasaOS(c *gin.Context) { os.Exit(0) } -// @Summary Turn off usb auto-mount -// @Produce application/json -// @Accept application/json -// @Tags sys -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /sys/usb/off [put] -func PutSystemUSBAutoMount(c *gin.Context) { - js := make(map[string]string) - c.ShouldBind(&js) - status := js["state"] - if status == "on" { - service.MyService.System().UpdateUSBAutoMount("True") - service.MyService.System().ExecUSBAutoMountShell("True") - } else { - service.MyService.System().UpdateUSBAutoMount("False") - service.MyService.System().ExecUSBAutoMountShell("False") - } - c.JSON(common_err.SUCCESS, - model.Result{ - Success: common_err.SUCCESS, - Message: common_err.GetMsg(common_err.SUCCESS), - }) -} - -// @Summary Turn off usb auto-mount -// @Produce application/json -// @Accept application/json -// @Tags sys -// @Security ApiKeyAuth -// @Success 200 {string} string "ok" -// @Router /sys/usb [get] -func GetSystemUSBAutoMount(c *gin.Context) { - state := "True" - if config.ServerInfo.USBAutoMount == "False" { - state = "False" - } - c.JSON(common_err.SUCCESS, - model.Result{ - Success: common_err.SUCCESS, - Message: common_err.GetMsg(common_err.SUCCESS), - Data: state, - }) -} - func GetSystemAppsStatus(c *gin.Context) { systemAppList := service.MyService.App().GetSystemAppList() appList := []model2.MyAppList{} @@ -225,12 +180,12 @@ func GetSystemAppsStatus(c *gin.Context) { Id: v.ID, Port: v.Labels["web"], Index: v.Labels["index"], - //Order: m.Labels["order"], + // Order: m.Labels["order"], Image: v.Image, Latest: false, - //Type: m.Labels["origin"], - //Slogan: m.Slogan, - //Rely: m.Rely, + // Type: m.Labels["origin"], + // Slogan: m.Slogan, + // Rely: m.Rely, Host: v.Labels["host"], Protocol: v.Labels["protocol"], }) @@ -251,7 +206,6 @@ func GetSystemAppsStatus(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /sys/hardware/info [get] func GetSystemHardwareInfo(c *gin.Context) { - data := make(map[string]string, 1) data["drive_model"] = service.MyService.System().GetDeviceTree() c.JSON(common_err.SUCCESS, @@ -270,7 +224,7 @@ func GetSystemHardwareInfo(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /sys/utilization [get] func GetSystemUtilization(c *gin.Context) { - var data = make(map[string]interface{}) + data := make(map[string]interface{}) cpu := service.MyService.System().GetCpuPercent() num := service.MyService.System().GetCpuCoreNum() cpuData := make(map[string]interface{}) @@ -282,7 +236,7 @@ func GetSystemUtilization(c *gin.Context) { data["cpu"] = cpuData data["mem"] = service.MyService.System().GetMemInfo() - //拼装网络信息 + // 拼装网络信息 netList := service.MyService.System().GetNetInfo() newNet := []model.IOCountersStat{} nets := service.MyService.System().GetNet(true) @@ -313,7 +267,6 @@ func GetSystemUtilization(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /sys/socket/port [get] func GetSystemSocketPort(c *gin.Context) { - c.JSON(common_err.SUCCESS, model.Result{ Success: common_err.SUCCESS, @@ -336,7 +289,6 @@ func GetSystemCupInfo(c *gin.Context) { data["percent"] = cpu data["num"] = num c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) - } // @Summary get mem info @@ -349,7 +301,6 @@ func GetSystemCupInfo(c *gin.Context) { func GetSystemMemInfo(c *gin.Context) { mem := service.MyService.System().GetMemInfo() c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem}) - } // @Summary get disk info diff --git a/service/system.go b/service/system.go index 8717e4c..b7feef8 100644 --- a/service/system.go +++ b/service/system.go @@ -30,8 +30,6 @@ type SystemService interface { UpdateAssist() UpSystemPort(port string) GetTimeZone() string - UpdateUSBAutoMount(state string) - ExecUSBAutoMountShell(state string) UpAppOrderFile(str, id string) GetAppOrderFile(id string) []byte GetNet(physics bool) []string @@ -53,14 +51,7 @@ type SystemService interface { GetCPUTemperature() int GetCPUPower() map[string]string } -type systemService struct { -} - -func (s *systemService) UpdateUSBAutoMount(state string) { - config.ServerInfo.USBAutoMount = state - config.Cfg.Section("server").Key("USBAutoMount").SetValue(state) - config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) -} +type systemService struct{} func (c *systemService) MkdirAll(path string) (int, error) { _, err := os.Stat(path) @@ -76,8 +67,8 @@ func (c *systemService) MkdirAll(path string) (int, error) { } return common_err.SERVICE_ERROR, err } -func (c *systemService) RenameFile(oldF, newF string) (int, error) { +func (c *systemService) RenameFile(oldF, newF string) (int, error) { _, err := os.Stat(newF) if err == nil { return common_err.DIR_ALREADY_EXISTS, nil @@ -92,6 +83,7 @@ func (c *systemService) RenameFile(oldF, newF string) (int, error) { } return common_err.SERVICE_ERROR, err } + func (c *systemService) CreateFile(path string) (int, error) { _, err := os.Stat(path) if err == nil { @@ -104,9 +96,11 @@ func (c *systemService) CreateFile(path string) (int, error) { } return common_err.SERVICE_ERROR, err } + func (c *systemService) GetDeviceTree() string { return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDeviceTree") } + func (c *systemService) GetSysInfo() host.InfoStat { info, _ := host.Info() return *info @@ -128,9 +122,7 @@ func (c *systemService) GetNetState(name string) string { } func (c *systemService) GetDirPathOne(path string) (m model.Path) { - f, err := os.Stat(path) - if err != nil { return } @@ -175,6 +167,7 @@ func (c *systemService) GetDirPath(path string) []model.Path { } return dirs } + func (c *systemService) GetCpuInfo() []cpu.InfoStat { info, _ := cpu.Info() return info @@ -207,6 +200,7 @@ func (c *systemService) GetNetInfo() []net.IOCountersStat { parts, _ := net.IOCounters(true) return parts } + func (c *systemService) GetNet(physics bool) []string { t := "1" if physics { @@ -220,11 +214,12 @@ func (s *systemService) UpdateSystemVersion(version string) { os.Remove(config.AppInfo.LogPath + "/upgrade.log") } file.CreateFile(config.AppInfo.LogPath + "/upgrade.log") - //go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash") + // go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash") go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash") - //s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version) - //s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)) + // s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version) + // s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)) } + func (s *systemService) UpdateAssist() { command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/assist.sh") } @@ -233,14 +228,6 @@ func (s *systemService) GetTimeZone() string { return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetTimeZone") } -func (s *systemService) ExecUSBAutoMountShell(state string) { - if state == "False" { - command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Stop_Auto") - } else { - command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Start_Auto") - } -} - func (s *systemService) GetSystemConfigDebug() []string { return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetSysInfo") } @@ -248,9 +235,11 @@ func (s *systemService) GetSystemConfigDebug() []string { func (s *systemService) UpAppOrderFile(str, id string) { file.WriteToPath([]byte(str), config.AppInfo.DBPath+"/"+id, "app_order.json") } + func (s *systemService) GetAppOrderFile(id string) []byte { return file.ReadFullFile(config.AppInfo.UserDataPath + "/" + id + "/app_order.json") } + func (s *systemService) UpSystemPort(port string) { if len(port) > 0 && port != config.ServerInfo.HttpPort { config.Cfg.Section("server").Key("HttpPort").SetValue(port) @@ -258,6 +247,7 @@ func (s *systemService) UpSystemPort(port string) { } config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) } + func (s *systemService) GetCasaOSLogs(lineNumber int) string { file, err := os.Open(filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s", config.AppInfo.LogSaveName, @@ -294,8 +284,8 @@ func GetDeviceAllIP() []string { func (s *systemService) IsServiceRunning(name string) bool { status := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;CheckServiceStatus smbd") return strings.TrimSpace(status) == "running" - } + func (s *systemService) GetCPUTemperature() int { outPut := "" if file.Exists("/sys/class/thermal/thermal_zone0/temp") { @@ -313,6 +303,7 @@ func (s *systemService) GetCPUTemperature() int { } return celsius } + func (s *systemService) GetCPUPower() map[string]string { data := make(map[string]string, 2) data["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10) @@ -323,6 +314,7 @@ func (s *systemService) GetCPUPower() map[string]string { } return data } + func NewSystemService() SystemService { return &systemService{} } From 8908c399698e7d95f78bf648c91289715590f9e7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 13 Oct 2022 19:33:18 -0400 Subject: [PATCH 34/42] wip --- .../{migration-036.go => migration-sample.go} | 14 -------------- 1 file changed, 14 deletions(-) rename cmd/migration-tool/{migration-036.go => migration-sample.go} (73%) diff --git a/cmd/migration-tool/migration-036.go b/cmd/migration-tool/migration-sample.go similarity index 73% rename from cmd/migration-tool/migration-036.go rename to cmd/migration-tool/migration-sample.go index b6d5410..c45858d 100644 --- a/cmd/migration-tool/migration-036.go +++ b/cmd/migration-tool/migration-sample.go @@ -11,18 +11,13 @@ package main import ( - "strings" - interfaces "github.com/IceWhaleTech/CasaOS-Common" "github.com/IceWhaleTech/CasaOS-Common/utils/version" - "github.com/IceWhaleTech/CasaOS/pkg/config" - "github.com/IceWhaleTech/CasaOS/service" ) type migrationTool struct{} func (u *migrationTool) IsMigrationNeeded() (bool, error) { - majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() if err != nil { if err == version.ErrLegacyVersionNotFound { @@ -46,22 +41,13 @@ func (u *migrationTool) IsMigrationNeeded() (bool, error) { _logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...") return true, nil - } func (u *migrationTool) PreMigrate() error { - return nil } func (u *migrationTool) Migrate() error { - - if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { - service.MyService.System().UpdateUSBAutoMount("False") - service.MyService.System().ExecUSBAutoMountShell("False") - } - - _logger.Info("update done") return nil } From c05d8373500edae0be1ffbbfb70786a0a44ec397 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Mon, 17 Oct 2022 06:53:23 +0100 Subject: [PATCH 35/42] add update url --- model/sys_common.go | 1 + service/system.go | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/model/sys_common.go b/model/sys_common.go index 73316b0..f9476a4 100644 --- a/model/sys_common.go +++ b/model/sys_common.go @@ -26,6 +26,7 @@ type ServerModel struct { Token string USBAutoMount string SocketPort string + UpdateUrl string } // 服务配置 diff --git a/service/system.go b/service/system.go index 8717e4c..845927b 100644 --- a/service/system.go +++ b/service/system.go @@ -221,7 +221,12 @@ func (s *systemService) UpdateSystemVersion(version string) { } file.CreateFile(config.AppInfo.LogPath + "/upgrade.log") //go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash") - go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash") + if len(config.ServerInfo.UpdateUrl) > 0 { + go command2.OnlyExec("curl -fsSL " + config.ServerInfo.UpdateUrl + " | bash") + } else { + go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash") + } + //s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version) //s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)) } From 6d47d4ff1829e2d1624eceeb0854b2bb087b1121 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Oct 2022 17:30:00 -0400 Subject: [PATCH 36/42] wip --- .../cleanup/script.d/01-cleanup-casaos.sh | 0 .../cleanup/script.d/03-cleanup-casaos.sh | 199 ++++++++++++++++++ 2 files changed, 199 insertions(+) delete mode 100644 build/sysroot/usr/share/casaos/cleanup/script.d/01-cleanup-casaos.sh create mode 100644 build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh diff --git a/build/sysroot/usr/share/casaos/cleanup/script.d/01-cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/script.d/01-cleanup-casaos.sh deleted file mode 100644 index e69de29..0000000 diff --git a/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh new file mode 100644 index 0000000..b6a7ce2 --- /dev/null +++ b/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh @@ -0,0 +1,199 @@ +#!/bin/bash + +set -e + +readonly CASA_SERVICES=( + "casaos.service" + "devmon@devmon.service" +) + +readonly CASA_EXEC=casaos +readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service +readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service +readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service + +# Old Casa Files +readonly CASA_PATH=/casaOS +readonly CASA_BIN=/usr/local/bin/casaos +readonly CASA_CONF_PATH_OLD=/etc/casaos.conf + +readonly aCOLOUR=( + '\e[38;5;154m' # green | Lines, bullets and separators + '\e[1m' # Bold white | Main descriptions + '\e[90m' # Grey | Credits + '\e[91m' # Red | Update notifications Alert + '\e[33m' # Yellow | Emphasis +) + +Show() { + # OK + if (($1 == 0)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + # FAILED + elif (($1 == 1)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + # INFO + elif (($1 == 2)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + # NOTICE + elif (($1 == 3)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + fi +} + +Warn() { + echo -e "${aCOLOUR[3]}$1$COLOUR_RESET" +} + +trap 'onCtrlC' INT +onCtrlC() { + echo -e "${COLOUR_RESET}" + exit 1 +} + +Detecting_CasaOS() { + if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then + Show 2 "CasaOS is not detected, exit the script." + exit 1 + else + Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files." + fi +} + +Uninstall_Container() { + if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then + Show 2 "Start deleting containers." + docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers." + docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers." + fi +} + +Remove_Images() { + if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then + Show 2 "Start deleting all images." + docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images." + elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then + Show 2 "Start deleting unuse images." + docker image prune -af || Show 1 "Failed to delete unuse images." + fi +} + + +Uninstall_Casaos() { + + for SERVICE in "${CASA_SERVICES[@]}"; do + Show 2 "Stopping ${SERVICE}..." + systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}" + done + + # Remove Service file + if [[ -f ${CASA_SERVICE_USR} ]]; then + rm -rf ${CASA_SERVICE_USR} + fi + + if [[ -f ${CASA_SERVICE_LIB} ]]; then + rm -rf ${CASA_SERVICE_LIB} + fi + + if [[ -f ${CASA_SERVICE_ETC} ]]; then + rm -rf ${CASA_SERVICE_ETC} + fi + + # Old Casa Files + if [[ -d ${CASA_PATH} ]]; then + rm -rf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files." + fi + + if [[ -f ${CASA_BIN} ]]; then + rm -rf ${CASA_BIN} || Show 1 "Failed to delete legacy CasaOS exec file." + fi + + if [[ -f ${CASA_CONF_PATH_OLD} ]]; then + rm -rf ${CASA_CONF_PATH_OLD} + fi + + # New Casa Files + if [[ ${REMOVE_APP_DATA} = true ]]; then + rm -rf /DATA/AppData || Show 1 "Failed to delete AppData." + fi +} + +Detecting_CasaOS + +while true; do + echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + UNINSTALL_ALL_CONTAINER=true + break + ;; + [nN][oO] | [nN]) + UNINSTALL_ALL_CONTAINER=false + break + ;; + *) + Warn " Invalid input..." + ;; + esac +done + +if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then + while true; do + echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + REMOVE_IMAGES="all" + break + ;; + [nN][oO] | [nN]) + REMOVE_IMAGES="none" + break + ;; + *) + Warn " Invalid input..." + ;; + esac + done + + while true; do + echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + REMOVE_APP_DATA=true + break + ;; + [nN][oO] | [nN]) + REMOVE_APP_DATA=false + break + ;; + *) + Warn " Invalid input..." + ;; + esac + done +else + while true; do + echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + REMOVE_IMAGES="unuse" + break + ;; + [nN][oO] | [nN]) + REMOVE_IMAGES="none" + break + ;; + *) + Warn " Invalid input..." + ;; + esac + done +fi + +Uninstall_Container +Remove_Images +Uninstall_Casaos From 87de9cec0a5fd547119551ddbd772714d770aa79 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 18 Oct 2022 18:58:26 -0400 Subject: [PATCH 37/42] wip --- .../cleanup/script.d/03-cleanup-casaos.sh | 221 +++--------------- .../casaos/debian/bullseye/cleanup-casaos.sh | 1 + .../service.d/casaos/debian/cleanup-casaos.sh | 204 ++++++++++++++++ .../service.d/casaos/ubuntu/cleanup-casaos.sh | 1 + .../casaos/ubuntu/jammy/cleanup-casaos.sh | 1 + 5 files changed, 241 insertions(+), 187 deletions(-) mode change 100644 => 100755 build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh create mode 120000 build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/bullseye/cleanup-casaos.sh create mode 100644 build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/cleanup-casaos.sh create mode 120000 build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/cleanup-casaos.sh create mode 120000 build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/jammy/cleanup-casaos.sh diff --git a/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh old mode 100644 new mode 100755 index b6a7ce2..ce29b6d --- a/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh +++ b/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh @@ -2,198 +2,45 @@ set -e -readonly CASA_SERVICES=( - "casaos.service" - "devmon@devmon.service" -) +readonly APP_NAME_SHORT=casaos -readonly CASA_EXEC=casaos -readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service -readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service -readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service +__get_setup_script_directory_by_os_release() { + pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" &>/dev/null -# Old Casa Files -readonly CASA_PATH=/casaOS -readonly CASA_BIN=/usr/local/bin/casaos -readonly CASA_CONF_PATH_OLD=/etc/casaos.conf + { + # shellcheck source=/dev/null + { + source /etc/os-release + { + pushd "${ID}"/"${VERSION_CODENAME}" &>/dev/null + } || { + pushd "${ID}" &>/dev/null + } || { + pushd "${ID_LIKE}" &>/dev/null + } || { + echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})" + exit 1 + } -readonly aCOLOUR=( - '\e[38;5;154m' # green | Lines, bullets and separators - '\e[1m' # Bold white | Main descriptions - '\e[90m' # Grey | Credits - '\e[91m' # Red | Update notifications Alert - '\e[33m' # Yellow | Emphasis -) + pwd -Show() { - # OK - if (($1 == 0)); then - echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" - # FAILED - elif (($1 == 1)); then - echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" - # INFO - elif (($1 == 2)); then - echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" - # NOTICE - elif (($1 == 3)); then - echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" - fi + popd &>/dev/null + + } || { + echo "Unsupported OS: unknown" + exit 1 + } + + } + + popd &>/dev/null } -Warn() { - echo -e "${aCOLOUR[3]}$1$COLOUR_RESET" -} +SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release) -trap 'onCtrlC' INT -onCtrlC() { - echo -e "${COLOUR_RESET}" - exit 1 -} +readonly SETUP_SCRIPT_DIRECTORY +readonly SETUP_SCRIPT_FILENAME="cleanup-${APP_NAME_SHORT}.sh" +readonly SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}" -Detecting_CasaOS() { - if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then - Show 2 "CasaOS is not detected, exit the script." - exit 1 - else - Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files." - fi -} - -Uninstall_Container() { - if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then - Show 2 "Start deleting containers." - docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers." - docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers." - fi -} - -Remove_Images() { - if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then - Show 2 "Start deleting all images." - docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images." - elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then - Show 2 "Start deleting unuse images." - docker image prune -af || Show 1 "Failed to delete unuse images." - fi -} - - -Uninstall_Casaos() { - - for SERVICE in "${CASA_SERVICES[@]}"; do - Show 2 "Stopping ${SERVICE}..." - systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}" - done - - # Remove Service file - if [[ -f ${CASA_SERVICE_USR} ]]; then - rm -rf ${CASA_SERVICE_USR} - fi - - if [[ -f ${CASA_SERVICE_LIB} ]]; then - rm -rf ${CASA_SERVICE_LIB} - fi - - if [[ -f ${CASA_SERVICE_ETC} ]]; then - rm -rf ${CASA_SERVICE_ETC} - fi - - # Old Casa Files - if [[ -d ${CASA_PATH} ]]; then - rm -rf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files." - fi - - if [[ -f ${CASA_BIN} ]]; then - rm -rf ${CASA_BIN} || Show 1 "Failed to delete legacy CasaOS exec file." - fi - - if [[ -f ${CASA_CONF_PATH_OLD} ]]; then - rm -rf ${CASA_CONF_PATH_OLD} - fi - - # New Casa Files - if [[ ${REMOVE_APP_DATA} = true ]]; then - rm -rf /DATA/AppData || Show 1 "Failed to delete AppData." - fi -} - -Detecting_CasaOS - -while true; do - echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}" - read -r input - case $input in - [yY][eE][sS] | [yY]) - UNINSTALL_ALL_CONTAINER=true - break - ;; - [nN][oO] | [nN]) - UNINSTALL_ALL_CONTAINER=false - break - ;; - *) - Warn " Invalid input..." - ;; - esac -done - -if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then - while true; do - echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}" - read -r input - case $input in - [yY][eE][sS] | [yY]) - REMOVE_IMAGES="all" - break - ;; - [nN][oO] | [nN]) - REMOVE_IMAGES="none" - break - ;; - *) - Warn " Invalid input..." - ;; - esac - done - - while true; do - echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}" - read -r input - case $input in - [yY][eE][sS] | [yY]) - REMOVE_APP_DATA=true - break - ;; - [nN][oO] | [nN]) - REMOVE_APP_DATA=false - break - ;; - *) - Warn " Invalid input..." - ;; - esac - done -else - while true; do - echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}" - read -r input - case $input in - [yY][eE][sS] | [yY]) - REMOVE_IMAGES="unuse" - break - ;; - [nN][oO] | [nN]) - REMOVE_IMAGES="none" - break - ;; - *) - Warn " Invalid input..." - ;; - esac - done -fi - -Uninstall_Container -Remove_Images -Uninstall_Casaos +echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..." +$SHELL "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}" diff --git a/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/bullseye/cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/bullseye/cleanup-casaos.sh new file mode 120000 index 0000000..6afabc7 --- /dev/null +++ b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/bullseye/cleanup-casaos.sh @@ -0,0 +1 @@ +../cleanup-casaos.sh \ No newline at end of file diff --git a/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/cleanup-casaos.sh new file mode 100644 index 0000000..989ea55 --- /dev/null +++ b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/debian/cleanup-casaos.sh @@ -0,0 +1,204 @@ +#!/bin/bash + +set -e + +readonly CASA_SERVICES=( + "casaos.service" + "devmon@devmon.service" +) + +readonly CASA_EXEC=casaos +readonly CASA_CONF=/etc/casaos/casaos.conf +readonly CASA_URL=/var/run/casaos/casaos.url +readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service +readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service +readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service + +# Old Casa Files +readonly CASA_PATH=/casaOS +readonly CASA_CONF_PATH_OLD=/etc/casaos.conf + +readonly aCOLOUR=( + '\e[38;5;154m' # green | Lines, bullets and separators + '\e[1m' # Bold white | Main descriptions + '\e[90m' # Grey | Credits + '\e[91m' # Red | Update notifications Alert + '\e[33m' # Yellow | Emphasis +) + +Show() { + # OK + if (($1 == 0)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + # FAILED + elif (($1 == 1)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + # INFO + elif (($1 == 2)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + # NOTICE + elif (($1 == 3)); then + echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2" + fi +} + +Warn() { + echo -e "${aCOLOUR[3]}$1$COLOUR_RESET" +} + +trap 'onCtrlC' INT +onCtrlC() { + echo -e "${COLOUR_RESET}" + exit 1 +} + +Detecting_CasaOS() { + if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then + Show 2 "CasaOS is not detected, exit the script." + exit 1 + else + Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files." + fi +} + +Uninstall_Container() { + if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then + Show 2 "Start deleting containers." + docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers." + docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers." + fi +} + +Remove_Images() { + if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then + Show 2 "Start deleting all images." + docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images." + elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then + Show 2 "Start deleting unuse images." + docker image prune -af || Show 1 "Failed to delete unuse images." + fi +} + + +Uninstall_Casaos() { + + for SERVICE in "${CASA_SERVICES[@]}"; do + Show 2 "Stopping ${SERVICE}..." + systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}" + done + + # Remove Service file + if [[ -f ${CASA_SERVICE_USR} ]]; then + rm -rvf ${CASA_SERVICE_USR} + fi + + if [[ -f ${CASA_SERVICE_LIB} ]]; then + rm -rvf ${CASA_SERVICE_LIB} + fi + + if [[ -f ${CASA_SERVICE_ETC} ]]; then + rm -rvf ${CASA_SERVICE_ETC} + fi + + # Old Casa Files + if [[ -d ${CASA_PATH} ]]; then + rm -rvf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files." + fi + + if [[ -f ${CASA_CONF_PATH_OLD} ]]; then + rm -rvf ${CASA_CONF_PATH_OLD} + fi + + # New Casa Files + if [[ ${REMOVE_APP_DATA} = true ]]; then + rm -rvf /DATA/AppData || Show 1 "Failed to delete AppData." + fi + + rm -rvf "$(which ${CASA_EXEC})" || Show 3 "Failed to remove ${CASA_EXEC}" + rm -rvf ${CASA_CONF} || Show 3 "Failed to remove ${CASA_CONF}" + rm -rvf ${CASA_URL} || Show 3 "Failed to remove ${CASA_URL}" + + rm -rvf /var/lib/casaos/app_category.json + rm -rvf /var/lib/casaos/app_list.json + rm -rvf /var/lib/casaos/docker_root +} + +Detecting_CasaOS + +while true; do + echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + UNINSTALL_ALL_CONTAINER=true + break + ;; + [nN][oO] | [nN]) + UNINSTALL_ALL_CONTAINER=false + break + ;; + *) + Warn " Invalid input..." + ;; + esac +done + +if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then + while true; do + echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + REMOVE_IMAGES="all" + break + ;; + [nN][oO] | [nN]) + REMOVE_IMAGES="none" + break + ;; + *) + Warn " Invalid input..." + ;; + esac + done + + while true; do + echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + REMOVE_APP_DATA=true + break + ;; + [nN][oO] | [nN]) + REMOVE_APP_DATA=false + break + ;; + *) + Warn " Invalid input..." + ;; + esac + done +else + while true; do + echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}" + read -r input + case $input in + [yY][eE][sS] | [yY]) + REMOVE_IMAGES="unuse" + break + ;; + [nN][oO] | [nN]) + REMOVE_IMAGES="none" + break + ;; + *) + Warn " Invalid input..." + ;; + esac + done +fi + +Uninstall_Container +Remove_Images +Uninstall_Casaos diff --git a/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/cleanup-casaos.sh new file mode 120000 index 0000000..8862621 --- /dev/null +++ b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/cleanup-casaos.sh @@ -0,0 +1 @@ +../debian/cleanup-casaos.sh \ No newline at end of file diff --git a/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/jammy/cleanup-casaos.sh b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/jammy/cleanup-casaos.sh new file mode 120000 index 0000000..bf358e5 --- /dev/null +++ b/build/sysroot/usr/share/casaos/cleanup/service.d/casaos/ubuntu/jammy/cleanup-casaos.sh @@ -0,0 +1 @@ +../../debian/bullseye/cleanup-casaos.sh \ No newline at end of file From bcda9923225c99d45d5edea93259dd7e37eb8a4c Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Wed, 19 Oct 2022 09:00:45 +0100 Subject: [PATCH 38/42] add change log --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9058ae4..668dd1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +## [0.3.7] + +### Added +- [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line) + +### Changed +- [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity. +- [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions. +- [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization. +### Removed + +### Security + +### Fixed +- [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately. +- [Storage] Fixed a lot of known issues + ## [0.3.6-alpha.1] - 2022-09-06 From 2beb1c0d821924e3b57a0b5d9fcb365dca886ff3 Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Wed, 19 Oct 2022 09:08:11 +0100 Subject: [PATCH 39/42] update changelog --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 668dd1c..9f92680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,9 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity. - [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions. - [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization. -### Removed - -### Security ### Fixed - [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately. From ca967ec59ca3ce568462b9a24a509caa090646fa Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Wed, 26 Oct 2022 08:45:32 +0100 Subject: [PATCH 40/42] update release --- .github/workflows/release.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f92f949..9cc9b7d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,10 @@ jobs: - name: Fetch all tags run: git fetch --force --tags + + - name: Get version + id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - name: Set up Go uses: actions/setup-go@v2 @@ -45,3 +49,18 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} + + - name: Upload to oss + id: upload_to_oss + uses: tvrcgo/upload-to-oss@master + with: + key-id: ${{ secrets.OSS_KEY_ID }} + key-secret: ${{ secrets.OSS_KEY_SECRET }} + region: oss-cn-shanghai + bucket: casaos + assets: | + dist/checksums.txt:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/checksums.txt + dist/linux-arm-7-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz + dist/linux-arm64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz + dist/linux-amd64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz + From 438b8a1dd292b88c3044814581bb2de545600b4d Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Fri, 4 Nov 2022 07:41:09 +0000 Subject: [PATCH 41/42] Solve the problem of local application import failure --- CHANGELOG.md | 9 ++++++++- model/sys_common.go | 5 +++++ route/init.go | 34 ++++++++++++++++++++++++++++++++++ service/docker.go | 1 + service/system.go | 9 +++++++++ types/system.go | 2 +- 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f92680..eb34787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -## [0.3.7] +## [0.3.7.1] 2022-11-04 + +### Fixed + +- Fix memory leak issue ([#658](https://github.com/IceWhaleTech/CasaOS/issues/658)[#646](https://github.com/IceWhaleTech/CasaOS/issues/646)) +- Solve the problem of local application import failure ([#490](https://github.com/IceWhaleTech/CasaOS/issues/490)) + +## [0.3.7] 2022-10-28 ### Added - [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line) diff --git a/model/sys_common.go b/model/sys_common.go index f9476a4..098ba97 100644 --- a/model/sys_common.go +++ b/model/sys_common.go @@ -74,3 +74,8 @@ type FileSetting struct { ShareDir []string `json:"share_dir" delim:"|"` DownloadDir string `json:"download_dir"` } +type BaseInfo struct { + Hash string `json:"i"` + Version string `json:"v"` + Channel string `json:"c,omitempty"` +} diff --git a/route/init.go b/route/init.go index a35de29..986e73f 100644 --- a/route/init.go +++ b/route/init.go @@ -1,21 +1,55 @@ package route import ( + "encoding/json" "fmt" "os" "strings" "time" + "github.com/IceWhaleTech/CasaOS/model" + "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/samba" + "github.com/IceWhaleTech/CasaOS/pkg/utils/encryption" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" + "github.com/IceWhaleTech/CasaOS/types" "go.uber.org/zap" ) func InitFunction() { go InitNetworkMount() + go InitInfo() } + +func InitInfo() { + mb := model.BaseInfo{} + if file.Exists(config.AppInfo.DBPath + "/baseinfo.conf") { + err := json.Unmarshal(file.ReadFullFile(config.AppInfo.DBPath+"/baseinfo.conf"), &mb) + if err != nil { + loger.Error("baseinfo.conf", zap.String("error", err.Error())) + } + } + if file.Exists("/etc/CHANNEL") { + channel := file.ReadFullFile("/etc/CHANNEL") + mb.Channel = string(channel) + } + mac, err := service.MyService.System().GetMacAddress() + if err != nil { + loger.Error("GetMacAddress", zap.String("error", err.Error())) + } + mb.Hash = encryption.GetMD5ByStr(mac) + mb.Version = types.CURRENTVERSION + os.Remove(config.AppInfo.DBPath + "/baseinfo.conf") + by, err := json.Marshal(mb) + if err != nil { + loger.Error("init info err", zap.Any("err", err)) + return + } + file.WriteToFullPath(by, config.AppInfo.DBPath+"/baseinfo.conf", 0o666) +} + func InitNetworkMount() { time.Sleep(time.Second * 10) connections := service.MyService.Connections().GetConnectionsList() diff --git a/service/docker.go b/service/docker.go index f453c0b..8963dc5 100644 --- a/service/docker.go +++ b/service/docker.go @@ -560,6 +560,7 @@ func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id //container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name) hostConfig.Mounts = volumes + hostConfig.Binds = []string{} hostConfig.Privileged = m.Privileged hostConfig.CapAdd = m.CapAdd hostConfig.NetworkMode = container.NetworkMode(m.NetworkModel) diff --git a/service/system.go b/service/system.go index 497a469..c6d0837 100644 --- a/service/system.go +++ b/service/system.go @@ -50,9 +50,18 @@ type SystemService interface { IsServiceRunning(name string) bool GetCPUTemperature() int GetCPUPower() map[string]string + GetMacAddress() (string, error) } type systemService struct{} +func (c *systemService) GetMacAddress() (string, error) { + interfaces, err := net.Interfaces() + if err != nil { + return "", err + } + inter := interfaces[0] + return inter.HardwareAddr, nil +} func (c *systemService) MkdirAll(path string) (int, error) { _, err := os.Stat(path) if err == nil { diff --git a/types/system.go b/types/system.go index e77a7d6..a164363 100644 --- a/types/system.go +++ b/types/system.go @@ -9,6 +9,6 @@ */ package types -const CURRENTVERSION = "0.3.7" +const CURRENTVERSION = "0.3.7.1" const BODY = " " From 13c296788988470e5361d4ead94e6f14eaa1d9af Mon Sep 17 00:00:00 2001 From: LinkLeong Date: Wed, 16 Nov 2022 05:57:39 +0000 Subject: [PATCH 42/42] update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d65c868..21c8d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +## [0.3.8-alpha.1] 2022-11-16 + +### Added +- [System] Add system announcement +- [App] Allow to turn off the display of "Existing Docker Apps" in the settings. + +### Changed +- [System] Improve the feedback function, you can submit feedback in the bottom right corner of WebUI. + ## [0.3.7.1] 2022-11-04 ### Fixed