system.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. package v1
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "net/http"
  8. "os"
  9. "runtime"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "unsafe"
  14. http2 "github.com/IceWhaleTech/CasaOS-Common/utils/http"
  15. "github.com/IceWhaleTech/CasaOS-Common/utils/port"
  16. "github.com/IceWhaleTech/CasaOS/common"
  17. "github.com/IceWhaleTech/CasaOS/model"
  18. "github.com/IceWhaleTech/CasaOS/pkg/config"
  19. "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
  20. "github.com/IceWhaleTech/CasaOS/pkg/utils/version"
  21. "github.com/IceWhaleTech/CasaOS/service"
  22. model2 "github.com/IceWhaleTech/CasaOS/service/model"
  23. "github.com/IceWhaleTech/CasaOS/types"
  24. "github.com/gin-gonic/gin"
  25. "github.com/tidwall/gjson"
  26. )
  27. // @Summary check version
  28. // @Produce application/json
  29. // @Accept application/json
  30. // @Tags sys
  31. // @Security ApiKeyAuth
  32. // @Success 200 {string} string "ok"
  33. // @Router /sys/version/check [get]
  34. func GetSystemCheckVersion(c *gin.Context) {
  35. need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
  36. if need {
  37. installLog := model2.AppNotify{}
  38. installLog.State = 0
  39. installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
  40. installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
  41. installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  42. installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  43. installLog.Name = "CasaOS System"
  44. service.MyService.Notify().AddLog(installLog)
  45. }
  46. data := make(map[string]interface{}, 3)
  47. data["need_update"] = need
  48. data["version"] = version
  49. data["current_version"] = common.VERSION
  50. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
  51. }
  52. // @Summary 系统信息
  53. // @Produce application/json
  54. // @Accept application/json
  55. // @Tags sys
  56. // @Security ApiKeyAuth
  57. // @Success 200 {string} string "ok"
  58. // @Router /sys/update [post]
  59. func SystemUpdate(c *gin.Context) {
  60. need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
  61. if need {
  62. service.MyService.System().UpdateSystemVersion(version.Version)
  63. }
  64. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  65. }
  66. // @Summary get logs
  67. // @Produce application/json
  68. // @Accept application/json
  69. // @Tags sys
  70. // @Security ApiKeyAuth
  71. // @Success 200 {string} string "ok"
  72. // @Router /sys/error/logs [get]
  73. func GetCasaOSErrorLogs(c *gin.Context) {
  74. line, _ := strconv.Atoi(c.DefaultQuery("line", "100"))
  75. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
  76. }
  77. // 系统配置
  78. func GetSystemConfigDebug(c *gin.Context) {
  79. array := service.MyService.System().GetSystemConfigDebug()
  80. disk := service.MyService.System().GetDiskInfo()
  81. sys := service.MyService.System().GetSysInfo()
  82. version := service.MyService.Casa().GetCasaosVersion()
  83. var bugContent string = fmt.Sprintf(`
  84. - OS: %s
  85. - CasaOS Version: %s
  86. - Disk Total: %v
  87. - Disk Used: %v
  88. - System Info: %s
  89. - Remote Version: %s
  90. - Browser: $Browser$
  91. - Version: $Version$
  92. `, sys.OS, common.VERSION, disk.Total>>20, disk.Used>>20, array, version.Version)
  93. // array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
  94. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
  95. }
  96. // @Summary get casaos server port
  97. // @Produce application/json
  98. // @Accept application/json
  99. // @Tags sys
  100. // @Security ApiKeyAuth
  101. // @Success 200 {string} string "ok"
  102. // @Router /sys/port [get]
  103. func GetCasaOSPort(c *gin.Context) {
  104. c.JSON(common_err.SUCCESS,
  105. model.Result{
  106. Success: common_err.SUCCESS,
  107. Message: common_err.GetMsg(common_err.SUCCESS),
  108. Data: config.ServerInfo.HttpPort,
  109. })
  110. }
  111. // @Summary edit casaos server port
  112. // @Produce application/json
  113. // @Accept application/json
  114. // @Tags sys
  115. // @Security ApiKeyAuth
  116. // @Param port json string true "port"
  117. // @Success 200 {string} string "ok"
  118. // @Router /sys/port [put]
  119. func PutCasaOSPort(c *gin.Context) {
  120. json := make(map[string]string)
  121. c.ShouldBind(&json)
  122. portStr := json["port"]
  123. portNumber, err := strconv.Atoi(portStr)
  124. if err != nil {
  125. c.JSON(common_err.SERVICE_ERROR,
  126. model.Result{
  127. Success: common_err.SERVICE_ERROR,
  128. Message: err.Error(),
  129. })
  130. return
  131. }
  132. isAvailable := port.IsPortAvailable(portNumber, "tcp")
  133. if !isAvailable {
  134. c.JSON(common_err.SERVICE_ERROR,
  135. model.Result{
  136. Success: common_err.PORT_IS_OCCUPIED,
  137. Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED),
  138. })
  139. return
  140. }
  141. service.MyService.System().UpSystemPort(strconv.Itoa(portNumber))
  142. c.JSON(common_err.SUCCESS,
  143. model.Result{
  144. Success: common_err.SUCCESS,
  145. Message: common_err.GetMsg(common_err.SUCCESS),
  146. })
  147. }
  148. // @Summary active killing casaos
  149. // @Produce application/json
  150. // @Accept application/json
  151. // @Tags sys
  152. // @Security ApiKeyAuth
  153. // @Success 200 {string} string "ok"
  154. // @Router /sys/restart [post]
  155. func PostKillCasaOS(c *gin.Context) {
  156. os.Exit(0)
  157. }
  158. // @Summary get system hardware info
  159. // @Produce application/json
  160. // @Accept application/json
  161. // @Tags sys
  162. // @Security ApiKeyAuth
  163. // @Success 200 {string} string "ok"
  164. // @Router /sys/hardware/info [get]
  165. func GetSystemHardwareInfo(c *gin.Context) {
  166. data := make(map[string]string, 1)
  167. data["drive_model"] = service.MyService.System().GetDeviceTree()
  168. data["arch"] = runtime.GOARCH
  169. if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
  170. c.JSON(common_err.SUCCESS,
  171. model.Result{
  172. Success: common_err.SUCCESS,
  173. Message: common_err.GetMsg(common_err.SUCCESS),
  174. Data: data,
  175. })
  176. }
  177. }
  178. // @Summary system utilization
  179. // @Produce application/json
  180. // @Accept application/json
  181. // @Tags sys
  182. // @Security ApiKeyAuth
  183. // @Success 200 {string} string "ok"
  184. // @Router /sys/utilization [get]
  185. func GetSystemUtilization(c *gin.Context) {
  186. data := make(map[string]interface{})
  187. cpu := service.MyService.System().GetCpuPercent()
  188. num := service.MyService.System().GetCpuCoreNum()
  189. cpuModel := "arm"
  190. if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
  191. if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
  192. cpuModel = "intel"
  193. } else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 {
  194. cpuModel = "amd"
  195. }
  196. }
  197. cpuData := make(map[string]interface{})
  198. cpuData["percent"] = cpu
  199. cpuData["num"] = num
  200. cpuData["temperature"] = service.MyService.System().GetCPUTemperature()
  201. cpuData["power"] = service.MyService.System().GetCPUPower()
  202. cpuData["model"] = cpuModel
  203. data["cpu"] = cpuData
  204. data["mem"] = service.MyService.System().GetMemInfo()
  205. // 拼装网络信息
  206. netList := service.MyService.System().GetNetInfo()
  207. newNet := []model.IOCountersStat{}
  208. nets := service.MyService.System().GetNet(true)
  209. for _, n := range netList {
  210. for _, netCardName := range nets {
  211. if n.Name == netCardName {
  212. item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
  213. item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
  214. item.Time = time.Now().Unix()
  215. newNet = append(newNet, item)
  216. break
  217. }
  218. }
  219. }
  220. data["net"] = newNet
  221. systemMap := service.MyService.Notify().GetSystemTempMap()
  222. systemMap.Range(func(key, value interface{}) bool {
  223. data[key.(string)] = value
  224. return true
  225. })
  226. c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
  227. }
  228. // @Summary get cpu info
  229. // @Produce application/json
  230. // @Accept application/json
  231. // @Tags sys
  232. // @Security ApiKeyAuth
  233. // @Success 200 {string} string "ok"
  234. // @Router /sys/cpu [get]
  235. func GetSystemCupInfo(c *gin.Context) {
  236. cpu := service.MyService.System().GetCpuPercent()
  237. num := service.MyService.System().GetCpuCoreNum()
  238. data := make(map[string]interface{})
  239. data["percent"] = cpu
  240. data["num"] = num
  241. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
  242. }
  243. // @Summary get mem info
  244. // @Produce application/json
  245. // @Accept application/json
  246. // @Tags sys
  247. // @Security ApiKeyAuth
  248. // @Success 200 {string} string "ok"
  249. // @Router /sys/mem [get]
  250. func GetSystemMemInfo(c *gin.Context) {
  251. mem := service.MyService.System().GetMemInfo()
  252. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem})
  253. }
  254. // @Summary get disk info
  255. // @Produce application/json
  256. // @Accept application/json
  257. // @Tags sys
  258. // @Security ApiKeyAuth
  259. // @Success 200 {string} string "ok"
  260. // @Router /sys/disk [get]
  261. func GetSystemDiskInfo(c *gin.Context) {
  262. disk := service.MyService.System().GetDiskInfo()
  263. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: disk})
  264. }
  265. // @Summary get Net info
  266. // @Produce application/json
  267. // @Accept application/json
  268. // @Tags sys
  269. // @Security ApiKeyAuth
  270. // @Success 200 {string} string "ok"
  271. // @Router /sys/net [get]
  272. func GetSystemNetInfo(c *gin.Context) {
  273. netList := service.MyService.System().GetNetInfo()
  274. newNet := []model.IOCountersStat{}
  275. for _, n := range netList {
  276. for _, netCardName := range service.MyService.System().GetNet(true) {
  277. if n.Name == netCardName {
  278. item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
  279. item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
  280. item.Time = time.Now().Unix()
  281. newNet = append(newNet, item)
  282. break
  283. }
  284. }
  285. }
  286. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
  287. }
  288. func GetSystemProxy(c *gin.Context) {
  289. url := c.Query("url")
  290. resp, err := http2.Get(url, 30*time.Second)
  291. if err != nil {
  292. return
  293. }
  294. defer resp.Body.Close()
  295. for k, v := range c.Request.Header {
  296. c.Header(k, v[0])
  297. }
  298. rda, _ := ioutil.ReadAll(resp.Body)
  299. // json.NewEncoder(c.Writer).Encode(json.RawMessage(string(rda)))
  300. // 响应状态码
  301. c.Writer.WriteHeader(resp.StatusCode)
  302. // 复制转发的响应Body到响应Body
  303. io.Copy(c.Writer, ioutil.NopCloser(bytes.NewBuffer(rda)))
  304. }
  305. func PutSystemState(c *gin.Context) {
  306. state := c.Param("state")
  307. if strings.ToLower(state) == "off" {
  308. service.MyService.System().SystemShutdown()
  309. } else if strings.ToLower(state) == "restart" {
  310. service.MyService.System().SystemReboot()
  311. }
  312. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "The operation will be completed shortly."})
  313. }
  314. // @Summary 获取一个可用端口
  315. // @Produce application/json
  316. // @Accept application/json
  317. // @Tags app
  318. // @Param type query string true "端口类型 udp/tcp"
  319. // @Security ApiKeyAuth
  320. // @Success 200 {string} string "ok"
  321. // @Router /app/getport [get]
  322. func GetPort(c *gin.Context) {
  323. t := c.DefaultQuery("type", "tcp")
  324. var p int
  325. ok := true
  326. for ok {
  327. p, _ = port.GetAvailablePort(t)
  328. ok = !port.IsPortAvailable(p, t)
  329. }
  330. // @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
  331. c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
  332. }
  333. // @Summary 检查端口是否可用
  334. // @Produce application/json
  335. // @Accept application/json
  336. // @Tags app
  337. // @Param port path int true "端口号"
  338. // @Param type query string true "端口类型 udp/tcp"
  339. // @Security ApiKeyAuth
  340. // @Success 200 {string} string "ok"
  341. // @Router /app/check/{port} [get]
  342. func PortCheck(c *gin.Context) {
  343. p, _ := strconv.Atoi(c.Param("port"))
  344. t := c.DefaultQuery("type", "tcp")
  345. c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
  346. }
  347. func GetSystemEntry(c *gin.Context) {
  348. entry := service.MyService.System().GetSystemEntry()
  349. if !gjson.Valid(entry) {
  350. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: ""})
  351. return
  352. }
  353. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: entry})
  354. }