CasaOS/route/v1/system.go

386 lines
12 KiB
Go
Raw Normal View History

2021-09-26 02:35:02 +00:00
package v1
import (
"bytes"
2023-06-07 07:21:22 +00:00
"encoding/json"
2021-09-26 02:35:02 +00:00
"fmt"
"io"
"io/ioutil"
"net/http"
2021-12-06 09:08:36 +00:00
"os"
2023-02-08 10:11:46 +00:00
"runtime"
"strconv"
2021-12-29 08:42:20 +00:00
"strings"
"time"
2021-12-29 08:42:20 +00:00
"unsafe"
http2 "github.com/IceWhaleTech/CasaOS-Common/utils/http"
"github.com/IceWhaleTech/CasaOS-Common/utils/port"
"github.com/IceWhaleTech/CasaOS/common"
2021-09-27 06:17:36 +00:00
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
2021-09-27 06:17:36 +00:00
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
2021-09-26 02:35:02 +00:00
"github.com/gin-gonic/gin"
2023-05-15 03:01:21 +00:00
"github.com/tidwall/gjson"
2021-09-26 02:35:02 +00:00
)
2022-05-05 05:46:55 +00:00
// @Summary check version
2021-09-26 02:35:02 +00:00
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
2022-06-13 12:43:19 +00:00
// @Router /sys/version/check [get]
func GetSystemCheckVersion(c *gin.Context) {
need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
2021-09-26 02:35:02 +00:00
if need {
installLog := model2.AppNotify{}
installLog.State = 0
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.Name = "CasaOS System"
2021-09-26 02:35:02 +00:00
service.MyService.Notify().AddLog(installLog)
}
data := make(map[string]interface{}, 3)
data["need_update"] = need
2021-09-26 02:35:02 +00:00
data["version"] = version
data["current_version"] = common.VERSION
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
2021-09-26 02:35:02 +00:00
}
// @Summary 系统信息
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/update [post]
func SystemUpdate(c *gin.Context) {
need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
2021-09-26 02:35:02 +00:00
if need {
service.MyService.System().UpdateSystemVersion(version.Version)
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
2021-09-26 02:35:02 +00:00
}
// @Summary get logs
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/error/logs [get]
func GetCasaOSErrorLogs(c *gin.Context) {
line, _ := strconv.Atoi(c.DefaultQuery("line", "100"))
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
2021-09-26 02:35:02 +00:00
}
// 系统配置
2021-09-26 02:35:02 +00:00
func GetSystemConfigDebug(c *gin.Context) {
array := service.MyService.System().GetSystemConfigDebug()
disk := service.MyService.System().GetDiskInfo()
sys := service.MyService.System().GetSysInfo()
version := service.MyService.Casa().GetCasaosVersion()
var bugContent string = fmt.Sprintf(`
- OS: %s
- CasaOS Version: %s
- Disk Total: %v
- Disk Used: %v
- System Info: %s
- Remote Version: %s
- Browser: $Browser$
- Version: $Version$
`, sys.OS, common.VERSION, disk.Total>>20, disk.Used>>20, array, version.Version)
// array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
}
// @Summary get casaos server port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/port [get]
func GetCasaOSPort(c *gin.Context) {
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: config.ServerInfo.HttpPort,
})
}
2021-12-06 09:08:36 +00:00
// @Summary edit casaos server port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
2022-06-13 12:43:19 +00:00
// @Param port json string true "port"
2021-12-06 09:08:36 +00:00
// @Success 200 {string} string "ok"
// @Router /sys/port [put]
2021-12-06 09:08:36 +00:00
func PutCasaOSPort(c *gin.Context) {
2022-06-13 12:43:19 +00:00
json := make(map[string]string)
c.ShouldBind(&json)
2022-06-13 12:43:19 +00:00
portStr := json["port"]
portNumber, err := strconv.Atoi(portStr)
2021-12-06 09:08:36 +00:00
if err != nil {
c.JSON(common_err.SERVICE_ERROR,
2021-12-06 09:08:36 +00:00
model.Result{
Success: common_err.SERVICE_ERROR,
2021-12-06 09:08:36 +00:00
Message: err.Error(),
})
return
}
isAvailable := port.IsPortAvailable(portNumber, "tcp")
2021-12-06 09:08:36 +00:00
if !isAvailable {
c.JSON(common_err.SERVICE_ERROR,
2021-12-06 09:08:36 +00:00
model.Result{
Success: common_err.PORT_IS_OCCUPIED,
Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED),
2021-12-06 09:08:36 +00:00
})
return
}
service.MyService.System().UpSystemPort(strconv.Itoa(portNumber))
c.JSON(common_err.SUCCESS,
2021-12-06 09:08:36 +00:00
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
2021-12-06 09:08:36 +00:00
})
}
// @Summary active killing casaos
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
2022-06-13 12:43:19 +00:00
// @Router /sys/restart [post]
2021-12-06 09:08:36 +00:00
func PostKillCasaOS(c *gin.Context) {
os.Exit(0)
}
2021-12-29 08:42:20 +00:00
✨ New Feature - [Apps] This is a feature that has been highly requested by the community. Import the original Docker application into CasaOS. Now it's easy to import with just a few clicks! - [Apps] App list supports a custom sorting function! You can arrange apps in different orders by dragging the icons. - [Apps] App custom installation supports Docker Compose configuration import in YAML format. - [Files] Added thumbnail preview function for image files. - [Connect] Multiple CasaConenct devices in the LAN will be transmitted through the LAN network. - [System] Added a switch for auto-mounting USB disk devices. 🎈 Enhancement - [System] Optimized the system update alert, you will see the new version update log from the next version. - [Apps] Added live preview for icons in custom installed apps. - [Apps] Optimized the input of WebUI. - [Files] Completely updated the image preview, now it supports switching all images in the same folder, as well as dragging, zooming, rotating and resetting. - [Widgets] Added color levels for CPU and RAM charts. - [Conenct] Optimized the display of the right-click menu of the Connect friends list. 🎈 Changed - [Files] Change the initial display directory to /DATA 🐞 Fixed - [System] Fixed an issue with Raspberry Pi devices failing to boot using USB disks. (Achieved by disabling USB disk auto-mount) - [Apps] Fixed the issue that some Docker CLI commands failed to import. - [Apps] Fixed the issue that the app is not easily recognized in /DATA/AppData directory and docker command line after installation, it will be shown as the app name. (Newly installed apps only) - [Apps] Fixed the issue that Pi-hole cannot be launched after installation in the app store. - [Apps] Fixed the issue that apps cannot be updated with WatchTower. - [Files] Fixed the issue that when there is an upload task, the task status is lost after closing Files.
2022-05-13 10:12:26 +00:00
// @Summary get system hardware info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @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()
2023-03-23 04:09:46 +00:00
data["arch"] = runtime.GOARCH
2023-03-15 06:20:58 +00:00
2023-03-15 02:46:12 +00:00
if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
2023-03-15 06:20:58 +00:00
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: data,
})
}
✨ New Feature - [Apps] This is a feature that has been highly requested by the community. Import the original Docker application into CasaOS. Now it's easy to import with just a few clicks! - [Apps] App list supports a custom sorting function! You can arrange apps in different orders by dragging the icons. - [Apps] App custom installation supports Docker Compose configuration import in YAML format. - [Files] Added thumbnail preview function for image files. - [Connect] Multiple CasaConenct devices in the LAN will be transmitted through the LAN network. - [System] Added a switch for auto-mounting USB disk devices. 🎈 Enhancement - [System] Optimized the system update alert, you will see the new version update log from the next version. - [Apps] Added live preview for icons in custom installed apps. - [Apps] Optimized the input of WebUI. - [Files] Completely updated the image preview, now it supports switching all images in the same folder, as well as dragging, zooming, rotating and resetting. - [Widgets] Added color levels for CPU and RAM charts. - [Conenct] Optimized the display of the right-click menu of the Connect friends list. 🎈 Changed - [Files] Change the initial display directory to /DATA 🐞 Fixed - [System] Fixed an issue with Raspberry Pi devices failing to boot using USB disks. (Achieved by disabling USB disk auto-mount) - [Apps] Fixed the issue that some Docker CLI commands failed to import. - [Apps] Fixed the issue that the app is not easily recognized in /DATA/AppData directory and docker command line after installation, it will be shown as the app name. (Newly installed apps only) - [Apps] Fixed the issue that Pi-hole cannot be launched after installation in the app store. - [Apps] Fixed the issue that apps cannot be updated with WatchTower. - [Files] Fixed the issue that when there is an upload task, the task status is lost after closing Files.
2022-05-13 10:12:26 +00:00
}
2022-06-13 12:43:19 +00:00
// @Summary system utilization
2021-12-29 08:42:20 +00:00
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
2022-06-13 12:43:19 +00:00
// @Router /sys/utilization [get]
func GetSystemUtilization(c *gin.Context) {
data := make(map[string]interface{})
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuModel := "arm"
2022-11-29 02:25:26 +00:00
if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
cpuModel = "intel"
} else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 {
cpuModel = "amd"
}
}
2021-12-29 08:42:20 +00:00
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
cpuData["temperature"] = service.MyService.System().GetCPUTemperature()
cpuData["power"] = service.MyService.System().GetCPUPower()
2022-11-29 02:25:26 +00:00
cpuData["model"] = cpuModel
2021-12-29 08:42:20 +00:00
data["cpu"] = cpuData
data["mem"] = service.MyService.System().GetMemInfo()
2021-12-29 08:42:20 +00:00
// 拼装网络信息
netList := service.MyService.System().GetNetInfo()
2021-12-29 08:42:20 +00:00
newNet := []model.IOCountersStat{}
nets := service.MyService.System().GetNet(true)
2021-12-29 08:42:20 +00:00
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
2022-04-06 04:10:51 +00:00
item.Time = time.Now().Unix()
2021-12-29 08:42:20 +00:00
newNet = append(newNet, item)
break
}
}
}
data["net"] = newNet
systemMap := service.MyService.Notify().GetSystemTempMap()
systemMap.Range(func(key, value interface{}) bool {
data[key.(string)] = value
return true
})
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
2021-12-29 08:42:20 +00:00
}
2022-06-13 12:43:19 +00:00
// @Summary get cpu info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/cpu [get]
func GetSystemCupInfo(c *gin.Context) {
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
data := make(map[string]interface{})
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})
2022-06-13 12:43:19 +00:00
}
// @Summary get mem info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/mem [get]
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})
2022-06-13 12:43:19 +00:00
}
// @Summary get disk info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/disk [get]
func GetSystemDiskInfo(c *gin.Context) {
disk := service.MyService.System().GetDiskInfo()
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: disk})
2022-06-13 12:43:19 +00:00
}
// @Summary get Net info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/net [get]
func GetSystemNetInfo(c *gin.Context) {
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
for _, n := range netList {
for _, netCardName := range service.MyService.System().GetNet(true) {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
2022-06-13 12:43:19 +00:00
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
}
func GetSystemProxy(c *gin.Context) {
url := c.Query("url")
resp, err := http2.Get(url, 30*time.Second)
if err != nil {
return
}
defer resp.Body.Close()
for k, v := range c.Request.Header {
c.Header(k, v[0])
}
rda, _ := ioutil.ReadAll(resp.Body)
// json.NewEncoder(c.Writer).Encode(json.RawMessage(string(rda)))
// 响应状态码
c.Writer.WriteHeader(resp.StatusCode)
// 复制转发的响应Body到响应Body
io.Copy(c.Writer, ioutil.NopCloser(bytes.NewBuffer(rda)))
}
2022-11-29 02:25:26 +00:00
func PutSystemState(c *gin.Context) {
state := c.Param("state")
2022-12-20 06:05:16 +00:00
if strings.ToLower(state) == "off" {
2022-12-07 02:57:27 +00:00
service.MyService.System().SystemShutdown()
2022-12-20 06:05:16 +00:00
} else if strings.ToLower(state) == "restart" {
2022-12-07 02:57:27 +00:00
service.MyService.System().SystemReboot()
2022-11-29 02:25:26 +00:00
}
2022-12-07 02:57:27 +00:00
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "The operation will be completed shortly."})
2022-11-29 02:25:26 +00:00
}
// @Summary 获取一个可用端口
// @Produce application/json
// @Accept application/json
// @Tags app
// @Param type query string true "端口类型 udp/tcp"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/getport [get]
func GetPort(c *gin.Context) {
t := c.DefaultQuery("type", "tcp")
var p int
ok := true
for ok {
p, _ = port.GetAvailablePort(t)
ok = !port.IsPortAvailable(p, t)
}
// @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
}
// @Summary 检查端口是否可用
// @Produce application/json
// @Accept application/json
// @Tags app
// @Param port path int true "端口号"
// @Param type query string true "端口类型 udp/tcp"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/check/{port} [get]
func PortCheck(c *gin.Context) {
p, _ := strconv.Atoi(c.Param("port"))
t := c.DefaultQuery("type", "tcp")
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
}
2023-05-15 03:01:21 +00:00
func GetSystemEntry(c *gin.Context) {
entry := service.MyService.System().GetSystemEntry()
2023-06-07 07:21:22 +00:00
str := json.RawMessage(entry)
if !gjson.ValidBytes(str) {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: entry, Data: json.RawMessage("[]")})
2023-05-15 03:01:21 +00:00
return
}
2023-06-07 07:21:22 +00:00
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: str})
2023-05-15 03:01:21 +00:00
}