diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b1c23c50..cf858c310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -## [0.3.2-pre] - 2022-06-08 +## [0.3.2] - 2022-06-10 ### Added diff --git a/main.go b/main.go index cef616cbb..3f9e3665d 100644 --- a/main.go +++ b/main.go @@ -100,13 +100,14 @@ func main() { if err != nil { fmt.Println(err) } - err = cron2.AddFunc("0/3 * * * * *", func() { + err = cron2.AddFunc("0/5 * * * * *", func() { if service.ClientCount > 0 { - route.SendNetINfoBySocket() - route.SendCPUBySocket() - route.SendMemBySocket() - route.SendDiskBySocket() - route.SendUSBBySocket() + // route.SendNetINfoBySocket() + // route.SendCPUBySocket() + // route.SendMemBySocket() + // route.SendDiskBySocket() + // route.SendUSBBySocket() + route.SendAllHardwareStatusBySocket() } }) if err != nil { diff --git a/model/file.go b/model/file.go index 361d9685a..d918317b2 100644 --- a/model/file.go +++ b/model/file.go @@ -2,7 +2,7 @@ * @Author: LinkLeong link@icewhale.com * @Date: 2022-05-20 16:27:12 * @LastEditors: LinkLeong - * @LastEditTime: 2022-06-08 15:40:33 + * @LastEditTime: 2022-06-09 18:18:46 * @FilePath: /CasaOS/model/file.go * @Description: * @Website: https://www.casaos.io @@ -16,6 +16,8 @@ type FileOperate struct { TotalSize int64 `json:"total_size"` ProcessedSize int64 `json:"processed_size"` To string `json:"to" binding:"required"` + Style string `json:"style"` + Finished bool `json:"finished"` } type FileItem struct { diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go index ea8eeb847..48e1aa01f 100644 --- a/pkg/utils/file/file.go +++ b/pkg/utils/file/file.go @@ -186,7 +186,7 @@ func ReadFullFile(path string) []byte { } // File copies a single file from src to dst -func CopyFile(src, dst string) error { +func CopyFile(src, dst, style string) error { var err error var srcfd *os.File var dstfd *os.File @@ -197,20 +197,13 @@ func CopyFile(src, dst string) error { if !strings.HasSuffix(dst, "/") { dst += "/" } - dstPath := dst dst += lastPath - for i := 0; Exists(dst); i++ { - name := strings.Split(lastPath, ".") - nameIndex := 0 - if len(name) > 2 { - nameIndex = len(name) - 2 - } - name[nameIndex] = name[nameIndex] + "(Copy)" - dst = dstPath - for _, v := range name { - dst += v + "." + if Exists(dst) { + if style == "skip" { + return nil + } else { + os.Remove(dst) } - dst = strings.TrimSuffix(dst, ".") } if srcfd, err = os.Open(src); err != nil { @@ -244,7 +237,7 @@ func GetNoDuplicateFileName(fullPath string) string { } // Dir copies a whole directory recursively -func CopyDir(src string, dst string) error { +func CopyDir(src string, dst string, style string) error { var err error var fds []os.FileInfo var srcinfo os.FileInfo @@ -253,16 +246,23 @@ func CopyDir(src string, dst string) error { return err } if !srcinfo.IsDir() { - if err = CopyFile(src, dst); err != nil { + if err = CopyFile(src, dst, style); err != nil { fmt.Println(err) } return nil } - dstPath := dst + //dstPath := dst lastPath := src[strings.LastIndex(src, "/")+1:] dst += "/" + lastPath - for i := 0; Exists(dst); i++ { - dst = dstPath + "/" + lastPath + strconv.Itoa(i+1) + // for i := 0; Exists(dst); i++ { + // dst = dstPath + "/" + lastPath + strconv.Itoa(i+1) + // } + if Exists(dst) { + if style == "skip" { + return nil + } else { + os.Remove(dst) + } } if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil { return err @@ -275,11 +275,11 @@ func CopyDir(src string, dst string) error { dstfp := dst //path.Join(dst, fd.Name()) if fd.IsDir() { - if err = CopyDir(srcfp, dstfp); err != nil { + if err = CopyDir(srcfp, dstfp, style); err != nil { fmt.Println(err) } } else { - if err = CopyFile(srcfp, dstfp); err != nil { + if err = CopyFile(srcfp, dstfp, style); err != nil { fmt.Println(err) } } diff --git a/pkg/utils/oasis_err/e.go b/pkg/utils/oasis_err/e.go index a6526ce90..9d5608890 100644 --- a/pkg/utils/oasis_err/e.go +++ b/pkg/utils/oasis_err/e.go @@ -40,6 +40,7 @@ const ( FILE_READ_ERROR = 60002 FILE_DELETE_ERROR = 60003 DIR_NOT_EXISTS = 60004 + SOURCE_DES_SAME = 60005 //shortcuts SHORTCUTS_URL_ERROR = 70001 @@ -88,6 +89,7 @@ var MsgFlags = map[int]string{ FORMAT_ERROR: "Formatting failed, please check if the directory is occupied", // + SOURCE_DES_SAME: "Source and destination cannot be the same.", FILE_DOES_NOT_EXIST: "File does not exist", DIR_NOT_EXISTS: "Directory does not exist", diff --git a/route/periodical.go b/route/periodical.go index a6554d041..093401407 100644 --- a/route/periodical.go +++ b/route/periodical.go @@ -2,7 +2,7 @@ * @Author: LinkLeong link@icewhale.com * @Date: 2022-05-27 15:55:36 * @LastEditors: LinkLeong - * @LastEditTime: 2022-05-27 18:57:40 + * @LastEditTime: 2022-06-10 12:17:59 * @FilePath: /CasaOS/route/periodical.go * @Description: * @Website: https://www.casaos.io @@ -153,3 +153,133 @@ func SendUSBBySocket() { } service.MyService.Notify().SendUSBInfoBySocket(usb) } + +func SendAllHardwareStatusBySocket() { + + netList := service.MyService.System().GetNetInfo() + newNet := []model.IOCountersStat{} + nets := service.MyService.System().GetNet(true) + for _, n := range netList { + for _, netCardName := range nets { + if n.Name == netCardName { + item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) + item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) + item.Time = time.Now().Unix() + newNet = append(newNet, item) + break + } + } + } + + cpu := service.MyService.System().GetCpuPercent() + num := service.MyService.System().GetCpuCoreNum() + cpuData := make(map[string]interface{}) + cpuData["percent"] = cpu + cpuData["num"] = num + + 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" { + temp := service.MyService.Disk().SmartCTL(list[i].Path) + if reflect.DeepEqual(temp, model.SmartctlA{}) { + continue + } + + //list[i].Temperature = temp.Temperature.Current + if !temp.SmartStatus.Passed { + healthy = false + } + if len(list[i].Children) > 0 { + for _, v := range list[i].Children { + s, _ := strconv.ParseUint(v.FSSize, 10, 64) + a, _ := strconv.ParseUint(v.FSAvail, 10, 64) + u, _ := strconv.ParseUint(v.FSUsed, 10, 64) + summary.Size += s + summary.Avail += a + summary.Used += u + } + } + + } + } + + summary.Health = healthy + + usbList := service.MyService.Disk().LSBLK(false) + usb := []model.DriveUSB{} + for _, v := range usbList { + if v.Tran == "usb" { + temp := model.DriveUSB{} + temp.Model = v.Model + temp.Name = v.Name + temp.Size = v.Size + mountTemp := true + if len(v.Children) == 0 { + mountTemp = false + } + for _, child := range v.Children { + if len(child.MountPoint) > 0 { + avail, _ := strconv.ParseUint(child.FSAvail, 10, 64) + temp.Avail += avail + used, _ := strconv.ParseUint(child.FSUsed, 10, 64) + temp.Used += used + } else { + mountTemp = false + } + } + temp.Mount = mountTemp + usb = append(usb, temp) + } + } + memInfo := service.MyService.System().GetMemInfo() + memData := make(map[string]interface{}) + memData["total"] = memInfo.Total + memData["available"] = memInfo.Available + memData["used"] = memInfo.Used + memData["free"] = memInfo.Free + memData["usedPercent"] = memInfo.UsedPercent + + service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memData, cpuData, newNet) + +} diff --git a/route/socket.go b/route/socket.go index a8e5f71eb..8b73a0bda 100644 --- a/route/socket.go +++ b/route/socket.go @@ -2,7 +2,7 @@ * @Author: LinkLeong link@icewhale.com * @Date: 2022-05-23 17:18:56 * @LastEditors: LinkLeong - * @LastEditTime: 2022-06-08 16:31:24 + * @LastEditTime: 2022-06-09 21:48:10 * @FilePath: /CasaOS/route/socket.go * @Description: * @Website: https://www.casaos.io @@ -49,7 +49,7 @@ func SocketInit(msg chan notify.Message) { go func(msg chan notify.Message) { for v := range msg { f.Broadcast("", v.Path, &v.Msg) - time.Sleep(time.Millisecond * 300) + time.Sleep(time.Millisecond * 100) } }(msg) diff --git a/route/v1/file.go b/route/v1/file.go index d82ea0e48..076e132b7 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -199,7 +199,6 @@ func GetDownloadFile(c *gin.Context) { defer ar.Close() commonDir := file.CommonPrefix(filepath.Separator, list...) - currentPath := filepath.Base(commonDir) name := "_" + currentPath @@ -278,17 +277,20 @@ func DirPath(c *gin.Context) { //Hide the files or folders in operation fileQueue := make(map[string]string) - for _, v := range service.OpStrArr { - v, ok := service.FileQueue.Load(v) - if !ok { - continue - } - vt := v.(model.FileOperate) - for _, i := range vt.Item { - lastPath := i.From[strings.LastIndex(i.From, "/")+1:] - fileQueue[vt.To+"/"+lastPath] = i.From + if len(service.OpStrArr) > 0 { + for _, v := range service.OpStrArr { + v, ok := service.FileQueue.Load(v) + if !ok { + continue + } + vt := v.(model.FileOperate) + for _, i := range vt.Item { + lastPath := i.From[strings.LastIndex(i.From, "/")+1:] + fileQueue[vt.To+"/"+lastPath] = i.From + } } } + pathList := []model.Path{} for i := 0; i < len(info); i++ { if _, ok := fileQueue[info[i].Path]; !ok { @@ -495,6 +497,11 @@ func PostOperateFileOrDir(c *gin.Context) { c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) return } + if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] { + c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SOURCE_DES_SAME, Message: oasis_err2.GetMsg(oasis_err2.SOURCE_DES_SAME)}) + return + } + var total int64 = 0 for i := 0; i < len(list.Item); i++ { diff --git a/service/disk.go b/service/disk.go index 55ca9af29..cca835ab2 100644 --- a/service/disk.go +++ b/service/disk.go @@ -67,7 +67,7 @@ func (d *diskService) SmartCTL(path string) model.SmartctlA { loger.Error("Failed to unmarshal json", zap.Any("err", err)) } if !reflect.DeepEqual(m, model.SmartctlA{}) { - Cache.Add(key, m, time.Second*10) + Cache.Add(key, m, time.Hour*24) } return m } diff --git a/service/file.go b/service/file.go index 4ea9306cf..697dd1420 100644 --- a/service/file.go +++ b/service/file.go @@ -2,7 +2,7 @@ * @Author: LinkLeong link@icewhale.com * @Date: 2021-12-20 14:15:46 * @LastEditors: LinkLeong - * @LastEditTime: 2022-06-08 15:46:36 + * @LastEditTime: 2022-06-09 18:15:54 * @FilePath: /CasaOS/service/file.go * @Description: * @Website: https://www.casaos.io @@ -21,6 +21,8 @@ import ( "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" + "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" + "go.uber.org/zap" ) var FileQueue sync.Map @@ -87,26 +89,37 @@ func FileOperate(k string) { if temp.ProcessedSize > 0 { return } - for _, v := range temp.Item { + for i := 0; i < len(temp.Item); i++ { + v := temp.Item[i] if temp.Type == "move" { lastPath := v.From[strings.LastIndex(v.From, "/")+1:] + if !file.CheckNotExist(temp.To + "/" + lastPath) { - continue + if temp.Style == "skip" { + temp.Item[i].Finished = true + continue + } else { + os.Remove(temp.To + "/" + lastPath) + } } + err := os.Rename(v.From, temp.To+"/"+lastPath) if err != nil { + loger.Debug("file move error", zap.Any("err", err)) continue } } else if temp.Type == "copy" { - err := file.CopyDir(v.From, temp.To) + err := file.CopyDir(v.From, temp.To, temp.Style) if err != nil { continue } } else { continue } - } + } + temp.Finished = true + FileQueue.Store(k, temp) } func ExecOpFile() { diff --git a/service/notify.go b/service/notify.go index 5eccf56b0..6159f14de 100644 --- a/service/notify.go +++ b/service/notify.go @@ -37,12 +37,39 @@ type NotifyServer interface { SendPersonStatusBySocket(status notify.Person) 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) } type notifyServer struct { db *gorm.DB } +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 + + body["sys_cpu"] = cpu + + body["sys_net"] = netList + + msg := gosf.Message{} + msg.Body = body + msg.Success = true + msg.Text = "sys_hardware_status" + + notify := notify.Message{} + notify.Path = "sys_hardware_status" + notify.Msg = msg + + NotifyMsg <- notify + +} + // Send periodic broadcast messages func (i *notifyServer) SendFileOperateNotify(nowSend bool) { @@ -94,7 +121,7 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) { task.Status = "PROCESSING" } - if temp.ProcessedSize >= temp.TotalSize { + if temp.Finished || temp.ProcessedSize >= temp.TotalSize { task.Finished = true task.Status = "FINISHED" @@ -160,7 +187,8 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) { } else { task.Status = "PROCESSING" } - if temp.ProcessedSize >= temp.TotalSize { + if temp.Finished || temp.ProcessedSize >= temp.TotalSize { + task.Finished = true task.Status = "FINISHED" FileQueue.Delete(v) diff --git a/web/index.html b/web/index.html index dabeb76f0..3158bf09c 100644 --- a/web/index.html +++ b/web/index.html @@ -20,7 +20,7 @@ CasaOS - +