* Copyright (c) KylinSoft Co., Ltd. 2024.All rights reserved.
* PilotGo-plugin licensed under the Mulan Permissive Software License, Version 2.
* See LICENSE file for more details.
* Author: wubijie <wubijie@kylinos.cn>
* Date: Wed Nov 6 09:40:00 2024 +0800
*/
package service
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"time"
"gitee.com/openeuler/PilotGo/sdk/common"
"gitee.com/openeuler/PilotGo/sdk/logger"
"gitee.com/openeuler/PilotGo/sdk/utils/httputils"
"github.com/google/uuid"
"openeuler.org/PilotGo/configmanage-plugin/global"
"openeuler.org/PilotGo/configmanage-plugin/internal"
)
sshd: 配置文件,sshd_config文件只有一个
一般方法: 1、在/etc/ssh/sshd_config中修改内容
2、执行命令systemctl restart sshd重启sshd服务
考虑的问题:
*/
type SSHDFile = internal.SSHDFile
type SSHDConfig struct {
UUID string `json:"uuid"`
ConfigInfoUUID string `json:"configinfouuid"`
Content json.RawMessage `json:"content"`
Version string `json:"version"`
Path string `json:"path"`
Name string `json:"name"`
IsActive bool `json:"isactive"`
}
func (sdc *SSHDConfig) toSSHDFile() SSHDFile {
return SSHDFile{
UUID: sdc.UUID,
ConfigInfoUUID: sdc.ConfigInfoUUID,
Path: sdc.Path,
Name: sdc.Name,
Content: sdc.Content,
Version: fmt.Sprintf("v%s", time.Now().Format("2006-01-02-15-04-05")),
IsActive: sdc.IsActive,
IsFromHost: false,
CreatedAt: time.Now(),
}
}
func toSSHDConfig(sdf *SSHDFile) SSHDConfig {
return SSHDConfig{
UUID: sdf.UUID,
ConfigInfoUUID: sdf.ConfigInfoUUID,
Path: sdf.Path,
Name: sdf.Name,
Content: sdf.Content,
Version: sdf.Version,
IsActive: sdf.IsActive,
}
}
func (sdc *SSHDConfig) Record() error {
sdf := sdc.toSSHDFile()
return sdf.Add()
}
func (sdc *SSHDConfig) Load() error {
sdf, err := internal.GetSSHFileByInfoUUID(sdc.ConfigInfoUUID, true)
if err != nil {
return err
}
sdc.UUID = sdf.UUID
sdc.Path = sdf.Path
sdc.Name = sdf.Name
sdc.Content = sdf.Content
sdc.Version = sdf.Version
sdc.IsActive = sdf.IsActive
return nil
}
func (sdc *SSHDConfig) Apply() ([]NodeResult, error) {
sdf, err := internal.GetSSHDFileByUUID(sdc.UUID)
if err != nil {
return nil, err
}
if sdf.ConfigInfoUUID != sdc.ConfigInfoUUID || sdf.UUID != sdc.UUID {
return nil, errors.New("数据库不存在此配置")
}
batchids, err := internal.GetConfigBatchByUUID(sdc.ConfigInfoUUID)
if err != nil {
return nil, err
}
departids, err := internal.GetConfigDepartByUUID(sdc.ConfigInfoUUID)
if err != nil {
return nil, err
}
nodes, err := internal.GetConfigNodesByUUID(sdc.ConfigInfoUUID)
if err != nil {
return nil, err
}
sshdfile := common.File{}
err = json.Unmarshal([]byte(sdf.Content), &sshdfile)
if err != nil {
return nil, err
}
results := []NodeResult{}
de := Deploy{
DeployBatch: common.Batch{
BatchIds: batchids,
DepartmentIDs: departids,
MachineUUIDs: nodes,
},
DeployPath: sshdfile.Path,
DeployFileName: sshdfile.Name,
DeployText: sshdfile.Content,
}
serverInfo, err := global.GlobalClient.Registry.Get("pilotgo-server")
if err != nil {
return nil, err
}
url := fmt.Sprintf("http://%s:%s/api/v1/pluginapi/file_deploy", serverInfo.Address, serverInfo.Port)
r, err := httputils.Post(url, &httputils.Params{
Body: de,
})
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, errors.New("server process error:" + strconv.Itoa(r.StatusCode))
}
resp := &common.CommonResult{}
if err := json.Unmarshal(r.Body, resp); err != nil {
return nil, err
}
if resp.Code != http.StatusOK {
return nil, errors.New(resp.Message)
}
data := []common.NodeResult{}
if err := resp.ParseData(&data); err != nil {
return nil, err
}
for _, d := range data {
sdfNode := SSHDFile{
UUID: sdf.UUID,
ConfigInfoUUID: sdf.ConfigInfoUUID,
Path: sdf.Path,
Name: sdf.Name,
Content: sdf.Content,
Version: sdf.Version,
IsActive: true,
IsFromHost: false,
Hostuuid: d.UUID,
CreatedAt: time.Now(),
}
if d.Error != "" {
sdfNode.IsActive = false
results = append(results, NodeResult{
Type: global.SSHD,
NodeUUID: d.UUID,
Detail: sshdfile.Content,
Result: false,
Err: d.Error,
})
}
err = sdfNode.Add()
if err != nil {
results = append(results, NodeResult{
Type: global.SSHD,
NodeUUID: d.UUID,
Detail: "failed to collect sshd config to db",
Result: false,
Err: err.Error(),
})
}
}
if results == nil {
err = sdf.UpdateByuuid()
return nil, err
}
return results, errors.New("failed to apply SSHDConfig")
}
func (sdc *SSHDConfig) Collect() ([]NodeResult, error) {
ci, err := GetConfigByUUID(sdc.ConfigInfoUUID)
if err != nil {
return nil, err
}
serverInfo, err := global.GlobalClient.Registry.Get("pilotgo-server")
if err != nil {
return nil, err
}
url := fmt.Sprintf("http://%s:%s/api/v1/pluginapi/getnodefiles", serverInfo.Address, serverInfo.Port)
p := struct {
DeployBatch common.Batch `json:"deploybatch"`
Path string `json:"path"`
FileName string `json:"filename"`
}{
DeployBatch: common.Batch{
BatchIds: ci.BatchIds,
DepartmentIDs: ci.DepartIds,
MachineUUIDs: ci.Nodes,
},
Path: sdc.Path,
FileName: sdc.Name,
}
r, err := httputils.Post(url, &httputils.Params{
Body: p,
})
if err != nil {
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, errors.New("server process error:" + strconv.Itoa(r.StatusCode))
}
resp := &common.CommonResult{}
if err := json.Unmarshal(r.Body, resp); err != nil {
return nil, err
}
if resp.Code != http.StatusOK {
return nil, errors.New(resp.Message)
}
data := []common.NodeResult{}
if err := resp.ParseData(&data); err != nil {
return nil, err
}
results := []NodeResult{}
for _, v := range data {
if v.Error == "" {
file, _ := json.Marshal(v.Data)
sdf := SSHDFile{
UUID: uuid.New().String(),
ConfigInfoUUID: sdc.ConfigInfoUUID,
Path: sdc.Path,
Name: sdc.Name,
Content: file,
Version: fmt.Sprintf("v%s", time.Now().Format("2006-01-02-15-04-05")),
IsFromHost: true,
IsActive: true,
Hostuuid: v.UUID,
CreatedAt: time.Now(),
}
err = sdf.Add()
if err != nil {
logger.Error("failed to add sshd config: %s", err.Error())
results = append(results, NodeResult{
Type: global.SSHD,
NodeUUID: v.UUID,
Detail: "failed to collect sshd config to db",
Result: false,
Err: err.Error()})
}
} else {
results = append(results, NodeResult{
Type: global.SSHD,
NodeUUID: v.UUID,
Detail: "failed to collect sshd config:" + v.Data.(string),
Result: false,
Err: v.Error})
}
}
if results != nil {
return results, errors.New("failed to collect sshd config")
}
return nil, nil
}
func GetSSHDFileByInfoUUID(uuid string, isindex interface{}) (SSHDFile, error) {
return internal.GetSSHDFileByInfoUUID(uuid, isindex)
}
func GetSSHDFilesByConfigUUID(uuid string) ([]SSHDFile, error) {
return internal.GetSSHDFilesByConfigUUID(uuid)
}
func GetSSHDFilesByNode(nodeid string) ([]SSHDConfig, error) {
config_nodes, err := internal.GetConfigNodesByNode(nodeid)
if err != nil {
return nil, err
}
var sdcs []SSHDConfig
for _, v := range config_nodes {
sdf, err := internal.GetSSHDFileByInfoUUID(v.ConfigInfoUUID, nil)
if err != nil {
return nil, err
}
sdc := toSSHDConfig(&sdf)
sdcs = append(sdcs, sdc)
}
return sdcs, nil
}