mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-30 18:58:02 +08:00
229 lines
5.7 KiB
Go
229 lines
5.7 KiB
Go
package ansible
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"path"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/goodrain/rainbond/node/nodem/client"
|
|
"github.com/goodrain/rainbond/util"
|
|
)
|
|
|
|
//WriteHostsFile write hosts file
|
|
func WriteHostsFile(filePath, installConfPath string, hosts []*client.HostNode) error {
|
|
if os.Getenv("NOT_WRITE_ANSIBLE_HOSTS") != "" {
|
|
return nil
|
|
}
|
|
config := GetAnsibleHostConfig(filePath)
|
|
for i := range hosts {
|
|
config.AddHost(hosts[i], installConfPath)
|
|
}
|
|
return config.WriteFile()
|
|
}
|
|
|
|
//Host ansible host config
|
|
type Host struct {
|
|
AnsibleHostIP net.IP
|
|
//ssh port
|
|
AnsibleHostPort int
|
|
HostID string
|
|
Role client.HostRule
|
|
CreateTime time.Time
|
|
AnsibleSSHPrivateKeyFile string
|
|
}
|
|
|
|
// String reutrn Host string
|
|
func (a *Host) String() string {
|
|
if strings.TrimSpace(a.AnsibleSSHPrivateKeyFile) == "" {
|
|
return fmt.Sprintf("%s ansible_host=%s ansible_port=%d ip=%s port=%d role=%s", a.HostID, a.AnsibleHostIP, a.AnsibleHostPort, a.AnsibleHostIP, a.AnsibleHostPort, a.Role)
|
|
}
|
|
return fmt.Sprintf("%s ansible_host=%s ansible_port=%d ip=%s port=%d role=%s ansible_ssh_private_key_file=%s", a.HostID, a.AnsibleHostIP, a.AnsibleHostPort, a.AnsibleHostIP, a.AnsibleHostPort, a.Role, a.AnsibleSSHPrivateKeyFile)
|
|
}
|
|
|
|
// HostsList hosts list
|
|
type HostsList []*Host
|
|
|
|
func (list HostsList) Len() int {
|
|
return len(list)
|
|
}
|
|
|
|
func (list HostsList) Less(i, j int) bool {
|
|
return list[i].CreateTime.Before(list[j].CreateTime)
|
|
}
|
|
|
|
func (list HostsList) Swap(i, j int) {
|
|
list[i], list[j] = list[j], list[i]
|
|
}
|
|
|
|
//HostGroup ansible host group config
|
|
type HostGroup struct {
|
|
Name string
|
|
HostList HostsList
|
|
}
|
|
|
|
//AddHost add host
|
|
func (a *HostGroup) AddHost(h *Host) {
|
|
for _, old := range a.HostList {
|
|
if old.AnsibleHostIP.String() == h.AnsibleHostIP.String() {
|
|
return
|
|
}
|
|
}
|
|
a.HostList = append(a.HostList, h)
|
|
|
|
}
|
|
|
|
// String return HostList string
|
|
func (a *HostGroup) String() string {
|
|
rebuffer := bytes.NewBuffer(nil)
|
|
rebuffer.WriteString(fmt.Sprintf("[%s]\n", a.Name))
|
|
for i := range a.HostList {
|
|
if a.Name == "all" {
|
|
rebuffer.WriteString(a.HostList[i].String() + "\n")
|
|
} else {
|
|
rebuffer.WriteString(a.HostList[i].HostID + "\n")
|
|
}
|
|
}
|
|
rebuffer.WriteString("\n")
|
|
return rebuffer.String()
|
|
}
|
|
|
|
//HostConfig ansible hosts config
|
|
type HostConfig struct {
|
|
FileName string
|
|
GroupList map[string]*HostGroup
|
|
}
|
|
|
|
//GetAnsibleHostConfig get config
|
|
func GetAnsibleHostConfig(name string) *HostConfig {
|
|
return &HostConfig{
|
|
FileName: name,
|
|
GroupList: map[string]*HostGroup{
|
|
"all": &HostGroup{Name: "all"},
|
|
"manage": &HostGroup{Name: "manage"},
|
|
"new-manage": &HostGroup{Name: "new-manage"},
|
|
"gateway": &HostGroup{Name: "gateway"},
|
|
"new-gateway": &HostGroup{Name: "new-gateway"},
|
|
"compute": &HostGroup{Name: "compute"},
|
|
"new-compute": &HostGroup{Name: "new-compute"},
|
|
"etcd": &HostGroup{Name: "etcd"},
|
|
},
|
|
}
|
|
}
|
|
|
|
//Content return config file content
|
|
func (c *HostConfig) Content() string {
|
|
return c.ContentBuffer().String()
|
|
}
|
|
|
|
//ContentBuffer content buffer
|
|
func (c *HostConfig) ContentBuffer() *bytes.Buffer {
|
|
rebuffer := bytes.NewBuffer(nil)
|
|
for i := range c.GroupList {
|
|
sort.Sort(c.GroupList[i].HostList) // sort host by createTime
|
|
rebuffer.WriteString(c.GroupList[i].String())
|
|
}
|
|
return rebuffer
|
|
}
|
|
|
|
//WriteFile write config file
|
|
func (c *HostConfig) WriteFile() error {
|
|
if c.FileName == "" {
|
|
return fmt.Errorf("config file name can not be empty")
|
|
}
|
|
if err := util.CheckAndCreateDir(path.Dir(c.FileName)); err != nil {
|
|
return err
|
|
}
|
|
if err := ioutil.WriteFile(c.FileName+".tmp", c.ContentBuffer().Bytes(), 0755); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(c.FileName+".tmp", c.FileName)
|
|
}
|
|
|
|
func getSSHPort(configFile string) int {
|
|
if ok, _ := util.FileExists(configFile); !ok {
|
|
return 22
|
|
}
|
|
file, err := os.OpenFile(configFile, os.O_RDONLY, 0666)
|
|
if err != nil {
|
|
return 22
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
reader := bufio.NewReader(file)
|
|
for {
|
|
str, _, err := reader.ReadLine()
|
|
if err != nil {
|
|
break
|
|
}
|
|
line := strings.TrimSpace(string(str))
|
|
if strings.Contains(line, "=") && !strings.HasPrefix(line, "#") {
|
|
keyvalue := strings.SplitN(string(line), "=", 2)
|
|
if len(keyvalue) == 2 || keyvalue[0] == "INSTALL_SSH_PORT" {
|
|
port, err := strconv.Atoi(keyvalue[1])
|
|
if err != nil {
|
|
return 22
|
|
}
|
|
return port
|
|
}
|
|
}
|
|
}
|
|
return 22
|
|
}
|
|
|
|
//AddHost add host
|
|
func (c *HostConfig) AddHost(h *client.HostNode, installConfPath string) {
|
|
//check role
|
|
//check status
|
|
ansibleHost := &Host{
|
|
AnsibleHostIP: net.ParseIP(h.InternalIP),
|
|
AnsibleHostPort: getSSHPort(installConfPath),
|
|
HostID: h.ID,
|
|
Role: h.Role,
|
|
CreateTime: h.CreateTime,
|
|
AnsibleSSHPrivateKeyFile: h.KeyPath,
|
|
}
|
|
c.GroupList["all"].AddHost(ansibleHost)
|
|
checkNeedInstall := func(h *client.HostNode) bool {
|
|
return h.Status == client.NotInstalled || h.Status == client.InstallFailed || h.Status == client.Installing
|
|
}
|
|
if h.Role.HasRule("manage") {
|
|
if checkNeedInstall(h) {
|
|
c.GroupList["new-manage"].AddHost(ansibleHost)
|
|
} else {
|
|
c.GroupList["manage"].AddHost(ansibleHost)
|
|
}
|
|
if _, ok := h.Labels["noinstall_etcd"]; !ok {
|
|
c.GroupList["etcd"].AddHost(ansibleHost)
|
|
}
|
|
}
|
|
if h.Role.HasRule("compute") {
|
|
if checkNeedInstall(h) {
|
|
c.GroupList["new-compute"].AddHost(ansibleHost)
|
|
} else {
|
|
c.GroupList["compute"].AddHost(ansibleHost)
|
|
}
|
|
}
|
|
if h.Role.HasRule("gateway") {
|
|
if checkNeedInstall(h) {
|
|
c.GroupList["new-gateway"].AddHost(ansibleHost)
|
|
} else {
|
|
c.GroupList["gateway"].AddHost(ansibleHost)
|
|
}
|
|
}
|
|
for i := range h.NodeStatus.Conditions {
|
|
if h.NodeStatus.Conditions[i].Type == "etcd" {
|
|
c.GroupList["etcd"].AddHost(ansibleHost)
|
|
break
|
|
}
|
|
}
|
|
}
|