Files
EdgeAdmin/internal/nodes/admin_node.go

318 lines
6.5 KiB
Go
Raw Normal View History

2020-10-14 14:46:22 +08:00
package nodes
import (
2020-10-25 11:22:11 +08:00
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
2020-12-07 11:45:45 +08:00
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
2020-10-14 14:46:22 +08:00
"github.com/TeaOSLab/EdgeAdmin/internal/errors"
"github.com/TeaOSLab/EdgeAdmin/internal/events"
2021-01-12 11:49:37 +08:00
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
2020-10-14 14:46:22 +08:00
"github.com/iwind/TeaGo"
"github.com/iwind/TeaGo/Tea"
2021-01-12 11:49:37 +08:00
"github.com/iwind/TeaGo/lists"
2020-10-14 14:46:22 +08:00
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/rands"
"github.com/iwind/TeaGo/sessions"
"io/ioutil"
2021-01-12 11:49:37 +08:00
"log"
"net"
2020-10-14 14:46:22 +08:00
"os"
"os/exec"
"os/signal"
"syscall"
2020-11-10 12:47:24 +08:00
"time"
2020-10-14 14:46:22 +08:00
)
var SharedAdminNode *AdminNode = nil
2020-10-14 14:46:22 +08:00
type AdminNode struct {
subPIDs []int
2020-10-14 14:46:22 +08:00
}
func NewAdminNode() *AdminNode {
return &AdminNode{}
}
func (this *AdminNode) Run() {
SharedAdminNode = this
2020-10-14 14:46:22 +08:00
// 启动管理界面
secret := this.genSecret()
2020-10-25 11:22:11 +08:00
configs.Secret = secret
2020-10-14 14:46:22 +08:00
2021-01-12 11:49:37 +08:00
// 本地Sock
err := this.listenSock()
if err != nil {
logs.Println("NODE" + err.Error())
return
}
2020-10-14 14:46:22 +08:00
// 检查server配置
2021-01-12 11:49:37 +08:00
err = this.checkServer()
2020-10-14 14:46:22 +08:00
if err != nil {
2020-12-14 21:24:21 +08:00
if err != nil {
logs.Println("[NODE]" + err.Error())
return
}
2020-10-14 14:46:22 +08:00
return
}
// 监听信号
sigQueue := make(chan os.Signal)
signal.Notify(sigQueue, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT)
go func() {
for range sigQueue {
for _, pid := range this.subPIDs {
p, err := os.FindProcess(pid)
if err == nil && p != nil {
_ = p.Kill()
}
}
os.Exit(0)
}
}()
// 触发事件
events.Notify(events.EventStart)
2020-10-14 14:46:22 +08:00
// 启动API节点
this.startAPINode()
2020-12-14 21:24:21 +08:00
// 启动Web服务
2020-11-10 12:47:24 +08:00
TeaGo.NewServer(false).
2020-10-14 14:46:22 +08:00
AccessLog(false).
EndAll().
2020-12-07 11:45:45 +08:00
Session(sessions.NewFileSessionManager(86400, secret), teaconst.CookieSID).
2020-11-10 12:47:24 +08:00
ReadHeaderTimeout(3 * time.Second).
ReadTimeout(600 * time.Second).
Start()
2020-10-14 14:46:22 +08:00
}
2021-01-12 11:49:37 +08:00
// 实现守护进程
func (this *AdminNode) Daemon() {
path := os.TempDir() + "/edge-admin.sock"
isDebug := lists.ContainsString(os.Args, "debug")
isDebug = true
for {
conn, err := net.DialTimeout("unix", path, 1*time.Second)
if err != nil {
if isDebug {
log.Println("[DAEMON]starting ...")
}
// 尝试启动
err = func() error {
exe, err := os.Executable()
if err != nil {
return err
}
cmd := exec.Command(exe)
err = cmd.Start()
if err != nil {
return err
}
err = cmd.Wait()
if err != nil {
return err
}
return nil
}()
if err != nil {
if isDebug {
log.Println("[DAEMON]", err)
}
time.Sleep(1 * time.Second)
} else {
time.Sleep(5 * time.Second)
}
} else {
_ = conn.Close()
time.Sleep(5 * time.Second)
}
}
}
// 安装系统服务
func (this *AdminNode) InstallSystemService() error {
shortName := teaconst.SystemdServiceName
exe, err := os.Executable()
if err != nil {
return err
}
manager := utils.NewServiceManager(shortName, teaconst.ProductName)
err = manager.Install(exe, []string{})
if err != nil {
return err
}
return nil
}
// 添加子PID
func (this *AdminNode) AddSubPID(pid int) {
this.subPIDs = append(this.subPIDs, pid)
}
2020-10-14 14:46:22 +08:00
// 检查Server配置
func (this *AdminNode) checkServer() error {
configFile := Tea.ConfigFile("server.yaml")
_, err := os.Stat(configFile)
if err == nil {
return nil
}
if os.IsNotExist(err) {
// 创建文件
templateFile := Tea.ConfigFile("server.template.yaml")
data, err := ioutil.ReadFile(templateFile)
if err == nil {
err = ioutil.WriteFile(configFile, data, 0666)
if err != nil {
return errors.New("create config file failed: " + err.Error())
}
} else {
templateYAML := `# environment code
env: prod
# http
http:
"on": true
listen: [ "0.0.0.0:7788" ]
# https
https:
"on": false
listen: [ "0.0.0.0:443"]
cert: ""
key: ""
`
err = ioutil.WriteFile(configFile, []byte(templateYAML), 0666)
if err != nil {
return errors.New("create config file failed: " + err.Error())
}
}
} else {
return errors.New("can not read config from 'configs/server.yaml': " + err.Error())
}
return nil
}
// 启动API节点
func (this *AdminNode) startAPINode() {
configPath := Tea.Root + "/edge-api/configs/api.yaml"
_, err := os.Stat(configPath)
canStart := false
2020-10-14 14:46:22 +08:00
if err == nil {
canStart = true
} else if err != nil && os.IsNotExist(err) {
// 尝试恢复api.yaml
homeDir, _ := os.UserHomeDir()
paths := []string{}
if len(homeDir) > 0 {
paths = append(paths, homeDir+"/.edge-api/api.yaml")
}
paths = append(paths, "/etc/edge-api/api.yaml")
for _, path := range paths {
_, err = os.Stat(path)
if err == nil {
data, err := ioutil.ReadFile(path)
if err == nil {
err = ioutil.WriteFile(configPath, data, 0666)
if err == nil {
logs.Println("[NODE]recover 'edge-api/configs/api.yaml' from '" + path + "'")
canStart = true
break
}
}
}
}
}
dbPath := Tea.Root + "/edge-api/configs/db.yaml"
_, err = os.Stat(dbPath)
if err != nil && os.IsNotExist(err) {
// 尝试恢复db.yaml
homeDir, _ := os.UserHomeDir()
paths := []string{}
if len(homeDir) > 0 {
paths = append(paths, homeDir+"/.edge-api/db.yaml")
}
paths = append(paths, "/etc/edge-api/db.yaml")
for _, path := range paths {
_, err = os.Stat(path)
if err == nil {
data, err := ioutil.ReadFile(path)
if err == nil {
err = ioutil.WriteFile(dbPath, data, 0666)
if err == nil {
logs.Println("[NODE]recover 'edge-api/configs/db.yaml' from '" + path + "'")
break
}
}
}
}
}
if canStart {
2020-10-14 14:46:22 +08:00
logs.Println("start edge-api")
cmd := exec.Command(Tea.Root + "/edge-api/bin/edge-api")
err = cmd.Start()
2020-10-14 14:46:22 +08:00
if err != nil {
logs.Println("[ERROR]start edge-api failed: " + err.Error())
} else {
this.subPIDs = append(this.subPIDs, cmd.Process.Pid)
2020-10-14 14:46:22 +08:00
}
}
}
// 生成Secret
func (this *AdminNode) genSecret() string {
2020-12-14 21:24:21 +08:00
tmpFile := os.TempDir() + "/edge-admin-secret.tmp"
data, err := ioutil.ReadFile(tmpFile)
if err == nil && len(data) == 32 {
return string(data)
}
secret := rands.String(32)
_ = ioutil.WriteFile(tmpFile, []byte(secret), 0666)
return secret
}
2021-01-12 11:49:37 +08:00
// 监听本地sock
func (this *AdminNode) listenSock() error {
path := os.TempDir() + "/edge-admin.sock"
// 检查是否已经存在
_, err := os.Stat(path)
if err == nil {
conn, err := net.Dial("unix", path)
if err != nil {
_ = os.Remove(path)
} else {
_ = conn.Close()
}
}
// 新的监听任务
listener, err := net.Listen("unix", path)
if err != nil {
return err
}
events.On(events.EventQuit, func() {
logs.Println("NODE", "quit unix sock")
_ = listener.Close()
})
go func() {
for {
_, err := listener.Accept()
if err != nil {
return
}
}
}()
return nil
}