mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-30 23:49:10 +08:00
260 lines
7.5 KiB
Go
260 lines
7.5 KiB
Go
|
package service
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||
|
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
|
||
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||
|
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||
|
"github.com/1Panel-dev/1Panel/backend/utils/ini_conf"
|
||
|
"github.com/1Panel-dev/1Panel/backend/utils/systemctl"
|
||
|
"github.com/pkg/errors"
|
||
|
"gopkg.in/ini.v1"
|
||
|
"os/exec"
|
||
|
"path"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type HostToolService struct{}
|
||
|
|
||
|
type IHostToolService interface {
|
||
|
GetToolStatus(req request.HostToolReq) (*response.HostToolRes, error)
|
||
|
CreateToolConfig(req request.HostToolCreate) error
|
||
|
OperateTool(req request.HostToolReq) error
|
||
|
OperateToolConfig(req request.HostToolConfig) (*response.HostToolConfig, error)
|
||
|
GetToolLog(req request.HostToolLogReq) (string, error)
|
||
|
OperateSupervisorProcess(req request.SupervisorProcessConfig) error
|
||
|
}
|
||
|
|
||
|
func NewIHostToolService() IHostToolService {
|
||
|
return &HostToolService{}
|
||
|
}
|
||
|
|
||
|
func (h *HostToolService) GetToolStatus(req request.HostToolReq) (*response.HostToolRes, error) {
|
||
|
res := &response.HostToolRes{}
|
||
|
res.Type = req.Type
|
||
|
switch req.Type {
|
||
|
case constant.Supervisord:
|
||
|
exist, err := systemctl.IsExist(constant.Supervisord)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
supervisorConfig := &response.Supervisor{}
|
||
|
if !exist {
|
||
|
supervisorConfig.IsExist = false
|
||
|
return res, nil
|
||
|
}
|
||
|
supervisorConfig.IsExist = true
|
||
|
|
||
|
versionRes, _ := cmd.Exec("supervisord -v")
|
||
|
supervisorConfig.Version = strings.TrimSuffix(versionRes, "\n")
|
||
|
_, ctlRrr := exec.LookPath("supervisorctl")
|
||
|
supervisorConfig.CtlExist = ctlRrr == nil
|
||
|
|
||
|
active, err := systemctl.IsActive(constant.Supervisord)
|
||
|
if err != nil {
|
||
|
supervisorConfig.Status = "unhealthy"
|
||
|
supervisorConfig.Msg = err.Error()
|
||
|
res.Config = supervisorConfig
|
||
|
return res, nil
|
||
|
}
|
||
|
if active {
|
||
|
supervisorConfig.Status = "running"
|
||
|
} else {
|
||
|
supervisorConfig.Status = "stopped"
|
||
|
}
|
||
|
|
||
|
pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath))
|
||
|
if pathSet.ID != 0 || pathSet.Value != "" {
|
||
|
supervisorConfig.ConfigPath = pathSet.Value
|
||
|
res.Config = supervisorConfig
|
||
|
return res, nil
|
||
|
}
|
||
|
supervisorConfig.Init = true
|
||
|
|
||
|
servicePath := "/usr/lib/systemd/system/supervisord.service"
|
||
|
fileOp := files.NewFileOp()
|
||
|
if !fileOp.Stat(servicePath) {
|
||
|
servicePath = "/lib/systemd/system/supervisord.service"
|
||
|
}
|
||
|
if fileOp.Stat(servicePath) {
|
||
|
startCmd, _ := ini_conf.GetIniValue(servicePath, "Service", "ExecStart")
|
||
|
if startCmd != "" {
|
||
|
args := strings.Fields(startCmd)
|
||
|
cIndex := -1
|
||
|
for i, arg := range args {
|
||
|
if arg == "-c" {
|
||
|
cIndex = i
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if cIndex != -1 && cIndex+1 < len(args) {
|
||
|
supervisorConfig.ConfigPath = args[cIndex+1]
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
configPath := "/etc/supervisord.conf"
|
||
|
if !fileOp.Stat(configPath) {
|
||
|
configPath = "/etc/supervisor/supervisord.conf"
|
||
|
if !fileOp.Stat("configPath") {
|
||
|
return nil, errors.New("ErrConfigNotFound")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
res.Config = supervisorConfig
|
||
|
}
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
func (h *HostToolService) CreateToolConfig(req request.HostToolCreate) error {
|
||
|
switch req.Type {
|
||
|
case constant.Supervisord:
|
||
|
fileOp := files.NewFileOp()
|
||
|
if !fileOp.Stat(req.ConfigPath) {
|
||
|
return errors.New("ErrConfigNotFound")
|
||
|
}
|
||
|
cfg, err := ini.Load(req.ConfigPath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
service, err := cfg.GetSection("include")
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
targetKey, err := service.GetKey("files")
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if targetKey != nil {
|
||
|
_, err = service.NewKey(";files", targetKey.Value())
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
supervisorDir := path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord")
|
||
|
includeDir := path.Join(supervisorDir, "supervisor.d")
|
||
|
if !fileOp.Stat(includeDir) {
|
||
|
if err = fileOp.CreateDir(includeDir, 0755); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
logDir := path.Join(supervisorDir, "log")
|
||
|
if !fileOp.Stat(logDir) {
|
||
|
if err = fileOp.CreateDir(logDir, 0755); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
includePath := path.Join(includeDir, "*.ini")
|
||
|
targetKey.SetValue(includePath)
|
||
|
if err = cfg.SaveTo(req.ConfigPath); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err = settingRepo.Create(constant.SupervisorConfigPath, req.ConfigPath); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
go func() {
|
||
|
if err = systemctl.Restart(constant.Supervisord); err != nil {
|
||
|
global.LOG.Errorf("[init] restart supervisord failed err %s", err.Error())
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (h *HostToolService) OperateTool(req request.HostToolReq) error {
|
||
|
return systemctl.Operate(req.Operate, req.Type)
|
||
|
}
|
||
|
|
||
|
func (h *HostToolService) OperateToolConfig(req request.HostToolConfig) (*response.HostToolConfig, error) {
|
||
|
fileOp := files.NewFileOp()
|
||
|
res := &response.HostToolConfig{}
|
||
|
configPath := ""
|
||
|
switch req.Type {
|
||
|
case constant.Supervisord:
|
||
|
pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath))
|
||
|
if pathSet.ID != 0 || pathSet.Value != "" {
|
||
|
configPath = pathSet.Value
|
||
|
}
|
||
|
}
|
||
|
configPath = "/etc/supervisord.conf"
|
||
|
switch req.Operate {
|
||
|
case "get":
|
||
|
content, err := fileOp.GetContent(configPath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
res.Content = string(content)
|
||
|
case "set":
|
||
|
file, err := fileOp.OpenFile(configPath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
oldContent, err := fileOp.GetContent(configPath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
fileInfo, err := file.Stat()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if err = fileOp.WriteFile(configPath, strings.NewReader(req.Content), fileInfo.Mode()); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if err = systemctl.Restart(req.Type); err != nil {
|
||
|
_ = fileOp.WriteFile(configPath, bytes.NewReader(oldContent), fileInfo.Mode())
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
func (h *HostToolService) GetToolLog(req request.HostToolLogReq) (string, error) {
|
||
|
fileOp := files.NewFileOp()
|
||
|
logfilePath := ""
|
||
|
switch req.Type {
|
||
|
case constant.Supervisord:
|
||
|
configPath := "/etc/supervisord.conf"
|
||
|
pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath))
|
||
|
if pathSet.ID != 0 || pathSet.Value != "" {
|
||
|
configPath = pathSet.Value
|
||
|
}
|
||
|
logfilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
|
||
|
}
|
||
|
oldContent, err := fileOp.GetContent(logfilePath)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
return string(oldContent), nil
|
||
|
}
|
||
|
|
||
|
func (h *HostToolService) OperateSupervisorProcess(req request.SupervisorProcessConfig) error {
|
||
|
configFile := ini.Empty()
|
||
|
supervisordDir := path.Join(global.CONF.System.BaseDir, "1panel", "tools", "supervisord")
|
||
|
logDir := path.Join(supervisordDir, "log")
|
||
|
includeDir := path.Join(supervisordDir, "supervisor.d")
|
||
|
|
||
|
section, err := configFile.NewSection(fmt.Sprintf("program:%s", req.Name))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
_, _ = section.NewKey("command", req.Command)
|
||
|
_, _ = section.NewKey("directory", req.Dir)
|
||
|
_, _ = section.NewKey("autorestart", "true")
|
||
|
_, _ = section.NewKey("startsecs", "3")
|
||
|
_, _ = section.NewKey("stdout_logfile", path.Join(logDir, fmt.Sprintf("%s.out.log", req.Name)))
|
||
|
_, _ = section.NewKey("stderr_logfile", path.Join(logDir, fmt.Sprintf("%s.err.log", req.Name)))
|
||
|
_, _ = section.NewKey("stdout_logfile_maxbytes", "2MB")
|
||
|
_, _ = section.NewKey("stderr_logfile_maxbytes", "2MB")
|
||
|
_, _ = section.NewKey("user", req.User)
|
||
|
_, _ = section.NewKey("priority", "999")
|
||
|
_, _ = section.NewKey("numprocs", req.Numprocs)
|
||
|
_, _ = section.NewKey("process_name", "%(program_name)s_%(process_num)02d")
|
||
|
|
||
|
return configFile.SaveTo(path.Join(includeDir, fmt.Sprintf("%s.ini", req.Name)))
|
||
|
}
|