system.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. package v1
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "unsafe"
  12. "github.com/IceWhaleTech/CasaOS/model"
  13. "github.com/IceWhaleTech/CasaOS/pkg/config"
  14. "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
  15. port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
  16. "github.com/IceWhaleTech/CasaOS/pkg/utils/version"
  17. "github.com/IceWhaleTech/CasaOS/service"
  18. model2 "github.com/IceWhaleTech/CasaOS/service/model"
  19. "github.com/IceWhaleTech/CasaOS/types"
  20. "github.com/gin-gonic/gin"
  21. uuid "github.com/satori/go.uuid"
  22. )
  23. // @Summary check version
  24. // @Produce application/json
  25. // @Accept application/json
  26. // @Tags sys
  27. // @Security ApiKeyAuth
  28. // @Success 200 {string} string "ok"
  29. // @Router /sys/version/check [get]
  30. func GetSystemCheckVersion(c *gin.Context) {
  31. need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
  32. if need {
  33. installLog := model2.AppNotify{}
  34. installLog.State = 0
  35. installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
  36. installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
  37. installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  38. installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
  39. installLog.Name = "CasaOS System"
  40. service.MyService.Notify().AddLog(installLog)
  41. }
  42. data := make(map[string]interface{}, 3)
  43. data["is_need"] = need
  44. data["version"] = version
  45. data["current_version"] = types.CURRENTVERSION
  46. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
  47. }
  48. // @Summary 系统信息
  49. // @Produce application/json
  50. // @Accept application/json
  51. // @Tags sys
  52. // @Security ApiKeyAuth
  53. // @Success 200 {string} string "ok"
  54. // @Router /sys/update [post]
  55. func SystemUpdate(c *gin.Context) {
  56. need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
  57. if need {
  58. service.MyService.System().UpdateSystemVersion(version.Version)
  59. }
  60. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
  61. }
  62. //Get system config
  63. func GetSystemConfig(c *gin.Context) {
  64. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.ConfigStr)})
  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(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
  76. }
  77. // @Summary 修改配置文件
  78. // @Produce application/json
  79. // @Accept multipart/form-data
  80. // @Tags sys
  81. // @Param config formData string true "config json string"
  82. // @Security ApiKeyAuth
  83. // @Success 200 {string} string "ok"
  84. // @Router /sys/changhead [post]
  85. func PostSetSystemConfig(c *gin.Context) {
  86. buf := make([]byte, 1024)
  87. n, _ := c.Request.Body.Read(buf)
  88. service.MyService.System().UpSystemConfig(string(buf[0:n]), "")
  89. c.JSON(http.StatusOK,
  90. model.Result{
  91. Success: common_err.SUCCESS,
  92. Message: common_err.GetMsg(common_err.SUCCESS),
  93. Data: json.RawMessage(config.SystemConfigInfo.ConfigStr),
  94. })
  95. }
  96. //系统配置
  97. func GetSystemConfigDebug(c *gin.Context) {
  98. array := service.MyService.System().GetSystemConfigDebug()
  99. disk := service.MyService.System().GetDiskInfo()
  100. sys := service.MyService.System().GetSysInfo()
  101. //todo 准备sync需要显示的数据(镜像,容器)
  102. var systemAppStatus string
  103. images := service.MyService.Docker().IsExistImage("linuxserver/syncthing")
  104. systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
  105. list := service.MyService.App().GetSystemAppList()
  106. for _, v := range list {
  107. systemAppStatus += v.Image + ",\n\t"
  108. }
  109. systemAppStatus += "Sync Key length: " + strconv.Itoa(len(config.SystemConfigInfo.SyncKey))
  110. var bugContent string = fmt.Sprintf(`
  111. - OS: %s
  112. - CasaOS Version: %s
  113. - Disk Total: %v
  114. - Disk Used: %v
  115. - Sync State: %s
  116. - System Info: %s
  117. - Browser: $Browser$
  118. - Version: $Version$
  119. `, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, systemAppStatus, array)
  120. // array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
  121. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
  122. }
  123. //widget配置
  124. func GetWidgetConfig(c *gin.Context) {
  125. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.WidgetList)})
  126. }
  127. // @Summary 修改组件配置文件
  128. // @Produce application/json
  129. // @Accept application/json
  130. // @Tags sys
  131. // @Security ApiKeyAuth
  132. // @Success 200 {string} string "ok"
  133. // @Router /sys/widget/config [post]
  134. func PostSetWidgetConfig(c *gin.Context) {
  135. buf := make([]byte, 1024)
  136. n, _ := c.Request.Body.Read(buf)
  137. service.MyService.System().UpSystemConfig("", string(buf[0:n]))
  138. c.JSON(http.StatusOK,
  139. model.Result{
  140. Success: common_err.SUCCESS,
  141. Message: common_err.GetMsg(common_err.SUCCESS),
  142. Data: json.RawMessage(config.SystemConfigInfo.WidgetList),
  143. })
  144. }
  145. // @Summary get casaos server port
  146. // @Produce application/json
  147. // @Accept application/json
  148. // @Tags sys
  149. // @Security ApiKeyAuth
  150. // @Success 200 {string} string "ok"
  151. // @Router /sys/port [get]
  152. func GetCasaOSPort(c *gin.Context) {
  153. c.JSON(http.StatusOK,
  154. model.Result{
  155. Success: common_err.SUCCESS,
  156. Message: common_err.GetMsg(common_err.SUCCESS),
  157. Data: config.ServerInfo.HttpPort,
  158. })
  159. }
  160. // @Summary edit casaos server port
  161. // @Produce application/json
  162. // @Accept application/json
  163. // @Tags sys
  164. // @Security ApiKeyAuth
  165. // @Param port json string true "port"
  166. // @Success 200 {string} string "ok"
  167. // @Router /sys/port [put]
  168. func PutCasaOSPort(c *gin.Context) {
  169. json := make(map[string]string)
  170. c.BindJSON(&json)
  171. portStr := json["port"]
  172. port, err := strconv.Atoi(portStr)
  173. if err != nil {
  174. c.JSON(http.StatusOK,
  175. model.Result{
  176. Success: common_err.ERROR,
  177. Message: err.Error(),
  178. })
  179. return
  180. }
  181. isAvailable := port2.IsPortAvailable(port, "tcp")
  182. if !isAvailable {
  183. c.JSON(http.StatusOK,
  184. model.Result{
  185. Success: common_err.PORT_IS_OCCUPIED,
  186. Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED),
  187. })
  188. return
  189. }
  190. service.MyService.System().UpSystemPort(strconv.Itoa(port))
  191. c.JSON(http.StatusOK,
  192. model.Result{
  193. Success: common_err.SUCCESS,
  194. Message: common_err.GetMsg(common_err.SUCCESS),
  195. })
  196. }
  197. // @Summary 检查是否进入引导状态
  198. // @Produce application/json
  199. // @Accept application/json
  200. // @Tags sys
  201. // @Security ApiKeyAuth
  202. // @Success 200 {string} string "ok"
  203. // @Router /sys/init/check [get]
  204. func GetSystemInitCheck(c *gin.Context) {
  205. data := make(map[string]interface{}, 2)
  206. if service.MyService.User().GetUserCount() > 0 {
  207. data["initialized"] = true
  208. data["key"] = ""
  209. } else {
  210. key := uuid.NewV4().String()
  211. service.UserRegisterHash[key] = key
  212. data["key"] = key
  213. data["initialized"] = false
  214. }
  215. c.JSON(http.StatusOK,
  216. model.Result{
  217. Success: common_err.SUCCESS,
  218. Message: common_err.GetMsg(common_err.SUCCESS),
  219. Data: data,
  220. })
  221. }
  222. // @Summary active killing casaos
  223. // @Produce application/json
  224. // @Accept application/json
  225. // @Tags sys
  226. // @Security ApiKeyAuth
  227. // @Success 200 {string} string "ok"
  228. // @Router /sys/restart [post]
  229. func PostKillCasaOS(c *gin.Context) {
  230. os.Exit(0)
  231. }
  232. // @Summary Turn off usb auto-mount
  233. // @Produce application/json
  234. // @Accept application/json
  235. // @Tags sys
  236. // @Security ApiKeyAuth
  237. // @Success 200 {string} string "ok"
  238. // @Router /sys/usb/off [put]
  239. func PutSystemUSBAutoMount(c *gin.Context) {
  240. status := c.Param("status")
  241. if status == "on" {
  242. service.MyService.System().UpdateUSBAutoMount("True")
  243. service.MyService.System().ExecUSBAutoMountShell("True")
  244. } else {
  245. service.MyService.System().UpdateUSBAutoMount("False")
  246. service.MyService.System().ExecUSBAutoMountShell("False")
  247. }
  248. c.JSON(http.StatusOK,
  249. model.Result{
  250. Success: common_err.SUCCESS,
  251. Message: common_err.GetMsg(common_err.SUCCESS),
  252. })
  253. }
  254. // @Summary Turn off usb auto-mount
  255. // @Produce application/json
  256. // @Accept application/json
  257. // @Tags sys
  258. // @Security ApiKeyAuth
  259. // @Success 200 {string} string "ok"
  260. // @Router /sys/usb [get]
  261. func GetSystemUSBAutoMount(c *gin.Context) {
  262. state := "True"
  263. if config.ServerInfo.USBAutoMount == "False" {
  264. state = "False"
  265. }
  266. c.JSON(http.StatusOK,
  267. model.Result{
  268. Success: common_err.SUCCESS,
  269. Message: common_err.GetMsg(common_err.SUCCESS),
  270. Data: state,
  271. })
  272. }
  273. // @Summary get system hardware info
  274. // @Produce application/json
  275. // @Accept application/json
  276. // @Tags sys
  277. // @Security ApiKeyAuth
  278. // @Success 200 {string} string "ok"
  279. // @Router /sys/hardware/info [get]
  280. func GetSystemHardwareInfo(c *gin.Context) {
  281. data := make(map[string]string, 1)
  282. data["drive_model"] = service.MyService.System().GetDeviceTree()
  283. c.JSON(http.StatusOK,
  284. model.Result{
  285. Success: common_err.SUCCESS,
  286. Message: common_err.GetMsg(common_err.SUCCESS),
  287. Data: data,
  288. })
  289. }
  290. // @Summary system utilization
  291. // @Produce application/json
  292. // @Accept application/json
  293. // @Tags sys
  294. // @Security ApiKeyAuth
  295. // @Success 200 {string} string "ok"
  296. // @Router /sys/utilization [get]
  297. func GetSystemUtilization(c *gin.Context) {
  298. var data = make(map[string]interface{}, 6)
  299. list := service.MyService.Disk().LSBLK(true)
  300. summary := model.Summary{}
  301. healthy := true
  302. findSystem := 0
  303. for i := 0; i < len(list); i++ {
  304. if len(list[i].Children) > 0 && findSystem == 0 {
  305. for j := 0; j < len(list[i].Children); j++ {
  306. if len(list[i].Children[j].Children) > 0 {
  307. for _, v := range list[i].Children[j].Children {
  308. if v.MountPoint == "/" {
  309. s, _ := strconv.ParseUint(v.FSSize, 10, 64)
  310. a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
  311. u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
  312. summary.Size += s
  313. summary.Avail += a
  314. summary.Used += u
  315. findSystem = 1
  316. break
  317. }
  318. }
  319. } else {
  320. if list[i].Children[j].MountPoint == "/" {
  321. s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
  322. a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
  323. u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
  324. summary.Size += s
  325. summary.Avail += a
  326. summary.Used += u
  327. findSystem = 1
  328. break
  329. }
  330. }
  331. }
  332. }
  333. if findSystem == 1 {
  334. findSystem += 1
  335. continue
  336. }
  337. 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" {
  338. temp := service.MyService.Disk().SmartCTL(list[i].Path)
  339. if reflect.DeepEqual(temp, model.SmartctlA{}) {
  340. continue
  341. }
  342. //list[i].Temperature = temp.Temperature.Current
  343. if !temp.SmartStatus.Passed {
  344. healthy = false
  345. }
  346. if len(list[i].Children) > 0 {
  347. for _, v := range list[i].Children {
  348. s, _ := strconv.ParseUint(v.FSSize, 10, 64)
  349. a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
  350. u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
  351. summary.Size += s
  352. summary.Avail += a
  353. summary.Used += u
  354. }
  355. }
  356. }
  357. }
  358. summary.Health = healthy
  359. data["disk"] = summary
  360. usbList := service.MyService.Disk().LSBLK(false)
  361. usb := []model.DriveUSB{}
  362. for _, v := range usbList {
  363. if v.Tran == "usb" {
  364. temp := model.DriveUSB{}
  365. temp.Model = v.Model
  366. temp.Name = v.Name
  367. temp.Size = v.Size
  368. mountTemp := true
  369. if len(v.Children) == 0 {
  370. mountTemp = false
  371. }
  372. for _, child := range v.Children {
  373. if len(child.MountPoint) > 0 {
  374. avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
  375. temp.Avail += avail
  376. used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
  377. temp.Used += used
  378. } else {
  379. mountTemp = false
  380. }
  381. }
  382. temp.Mount = mountTemp
  383. usb = append(usb, temp)
  384. }
  385. }
  386. data["usb"] = usb
  387. cpu := service.MyService.System().GetCpuPercent()
  388. num := service.MyService.System().GetCpuCoreNum()
  389. cpuData := make(map[string]interface{})
  390. cpuData["percent"] = cpu
  391. cpuData["num"] = num
  392. data["cpu"] = cpuData
  393. data["mem"] = service.MyService.System().GetMemInfo()
  394. //拼装网络信息
  395. netList := service.MyService.System().GetNetInfo()
  396. newNet := []model.IOCountersStat{}
  397. nets := service.MyService.System().GetNet(true)
  398. for _, n := range netList {
  399. for _, netCardName := range nets {
  400. if n.Name == netCardName {
  401. item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
  402. item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
  403. item.Time = time.Now().Unix()
  404. newNet = append(newNet, item)
  405. break
  406. }
  407. }
  408. }
  409. data["net"] = newNet
  410. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
  411. }
  412. // @Summary Get notification port
  413. // @Produce application/json
  414. // @Accept application/json
  415. // @Tags sys
  416. // @Security ApiKeyAuth
  417. // @Success 200 {string} string "ok"
  418. // @Router /sys/socket/port [get]
  419. func GetSystemSocketPort(c *gin.Context) {
  420. c.JSON(http.StatusOK,
  421. model.Result{
  422. Success: common_err.SUCCESS,
  423. Message: common_err.GetMsg(common_err.SUCCESS),
  424. Data: config.ServerInfo.SocketPort,
  425. })
  426. }
  427. // @Summary get cpu info
  428. // @Produce application/json
  429. // @Accept application/json
  430. // @Tags sys
  431. // @Security ApiKeyAuth
  432. // @Success 200 {string} string "ok"
  433. // @Router /sys/cpu [get]
  434. func GetSystemCupInfo(c *gin.Context) {
  435. cpu := service.MyService.System().GetCpuPercent()
  436. num := service.MyService.System().GetCpuCoreNum()
  437. data := make(map[string]interface{})
  438. data["percent"] = cpu
  439. data["num"] = num
  440. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
  441. }
  442. // @Summary get mem info
  443. // @Produce application/json
  444. // @Accept application/json
  445. // @Tags sys
  446. // @Security ApiKeyAuth
  447. // @Success 200 {string} string "ok"
  448. // @Router /sys/mem [get]
  449. func GetSystemMemInfo(c *gin.Context) {
  450. mem := service.MyService.System().GetMemInfo()
  451. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem})
  452. }
  453. // @Summary get disk info
  454. // @Produce application/json
  455. // @Accept application/json
  456. // @Tags sys
  457. // @Security ApiKeyAuth
  458. // @Success 200 {string} string "ok"
  459. // @Router /sys/disk [get]
  460. func GetSystemDiskInfo(c *gin.Context) {
  461. disk := service.MyService.System().GetDiskInfo()
  462. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: disk})
  463. }
  464. // @Summary get Net info
  465. // @Produce application/json
  466. // @Accept application/json
  467. // @Tags sys
  468. // @Security ApiKeyAuth
  469. // @Success 200 {string} string "ok"
  470. // @Router /sys/net [get]
  471. func GetSystemNetInfo(c *gin.Context) {
  472. netList := service.MyService.System().GetNetInfo()
  473. newNet := []model.IOCountersStat{}
  474. for _, n := range netList {
  475. for _, netCardName := range service.MyService.System().GetNet(true) {
  476. if n.Name == netCardName {
  477. item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
  478. item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
  479. item.Time = time.Now().Unix()
  480. newNet = append(newNet, item)
  481. break
  482. }
  483. }
  484. }
  485. c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
  486. }
  487. //********************************************* Soon to be removed ***********************************************
  488. // @Summary 检查是否进入引导状态
  489. // @Produce application/json
  490. // @Accept application/json
  491. // @Tags sys
  492. // @Security ApiKeyAuth
  493. // @Success 200 {string} string "ok"
  494. // @Router /guide/check [get]
  495. func GetGuideCheck(c *gin.Context) {
  496. initUser := false
  497. if !config.UserInfo.Initialized {
  498. initUser = true
  499. }
  500. data := make(map[string]interface{}, 1)
  501. data["need_init_user"] = initUser
  502. c.JSON(http.StatusOK,
  503. model.Result{
  504. Success: common_err.SUCCESS,
  505. Message: common_err.GetMsg(common_err.SUCCESS),
  506. Data: data,
  507. })
  508. }