mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-30 18:58:02 +08:00
[ADD] modify install node
This commit is contained in:
parent
d4a49a18f1
commit
eafe220983
@ -19,18 +19,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/goodrain/rainbond/grctl/clients"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
"github.com/goodrain/rainbond/node/nodem/client"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/goodrain/rainbond/node/nodem/client"
|
||||
ansibleUtil "github.com/goodrain/rainbond/util/ansible"
|
||||
)
|
||||
|
||||
//NewCmdAnsible ansible config cmd
|
||||
@ -44,16 +37,21 @@ func NewCmdAnsible() cli.Command {
|
||||
Usage: "Manage the ansible hosts config environment",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "hosts-file-path,p",
|
||||
Name: "hosts-file-path",
|
||||
Usage: "hosts file path",
|
||||
Value: "/opt/rainbond/rainbond-ansible/inventory/hosts",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config-file-path",
|
||||
Usage: "install config path",
|
||||
Value: "/opt/rainbond/rainbond-ansible/scripts/installer/global.sh",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
Common(c)
|
||||
hosts, err := clients.RegionClient.Nodes().List()
|
||||
handleErr(err)
|
||||
return WriteHostsFile(c.String("p"), hosts)
|
||||
return WriteHostsFile(c.String("hosts-file-path"), c.String("config-file-path"), hosts)
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -62,139 +60,6 @@ func NewCmdAnsible() cli.Command {
|
||||
}
|
||||
|
||||
//WriteHostsFile write hosts file
|
||||
func WriteHostsFile(filePath string, hosts []*client.HostNode) error {
|
||||
config := GetAnsibleHostConfig(filePath)
|
||||
for i := range hosts {
|
||||
config.AddHost(hosts[i])
|
||||
}
|
||||
return config.WriteFile()
|
||||
}
|
||||
|
||||
//AnsibleHost ansible host config
|
||||
type AnsibleHost struct {
|
||||
AnsibleHostIP net.IP
|
||||
//ssh port
|
||||
AnsibleHostPort int
|
||||
HostID string
|
||||
Role client.HostRule
|
||||
}
|
||||
|
||||
func (a *AnsibleHost) String() string {
|
||||
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)
|
||||
}
|
||||
|
||||
//AnsibleHostGroup ansible host group config
|
||||
type AnsibleHostGroup struct {
|
||||
Name string
|
||||
HostList []*AnsibleHost
|
||||
}
|
||||
|
||||
//AddHost add host
|
||||
func (a *AnsibleHostGroup) AddHost(h *AnsibleHost) {
|
||||
for _, old := range a.HostList {
|
||||
if old.AnsibleHostIP.String() == h.AnsibleHostIP.String() {
|
||||
return
|
||||
}
|
||||
}
|
||||
a.HostList = append(a.HostList, h)
|
||||
}
|
||||
func (a *AnsibleHostGroup) 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()
|
||||
}
|
||||
|
||||
//AnsibleHostConfig ansible hosts config
|
||||
type AnsibleHostConfig struct {
|
||||
FileName string
|
||||
GroupList map[string]*AnsibleHostGroup
|
||||
}
|
||||
|
||||
//GetAnsibleHostConfig get config
|
||||
func GetAnsibleHostConfig(name string) *AnsibleHostConfig {
|
||||
return &AnsibleHostConfig{
|
||||
FileName: name,
|
||||
GroupList: map[string]*AnsibleHostGroup{
|
||||
"all": &AnsibleHostGroup{Name: "all"},
|
||||
"manage": &AnsibleHostGroup{Name: "manage"},
|
||||
"new-manage": &AnsibleHostGroup{Name: "new-manage"},
|
||||
"gateway": &AnsibleHostGroup{Name: "gateway"},
|
||||
"new-gateway": &AnsibleHostGroup{Name: "new-gateway"},
|
||||
"compute": &AnsibleHostGroup{Name: "compute"},
|
||||
"new-compute": &AnsibleHostGroup{Name: "new-compute"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
//Content return config file content
|
||||
func (c *AnsibleHostConfig) Content() string {
|
||||
return c.ContentBuffer().String()
|
||||
}
|
||||
|
||||
//ContentBuffer content buffer
|
||||
func (c *AnsibleHostConfig) ContentBuffer() *bytes.Buffer {
|
||||
rebuffer := bytes.NewBuffer(nil)
|
||||
for i := range c.GroupList {
|
||||
rebuffer.WriteString(c.GroupList[i].String())
|
||||
}
|
||||
return rebuffer
|
||||
}
|
||||
|
||||
//WriteFile write config file
|
||||
func (c *AnsibleHostConfig) 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() int {
|
||||
return 22
|
||||
}
|
||||
|
||||
//AddHost add host
|
||||
func (c *AnsibleHostConfig) AddHost(h *client.HostNode) {
|
||||
//check role
|
||||
//check status
|
||||
ansibleHost := &AnsibleHost{
|
||||
AnsibleHostIP: net.ParseIP(h.InternalIP),
|
||||
AnsibleHostPort: getSSHPort(),
|
||||
HostID: h.ID,
|
||||
Role: h.Role,
|
||||
}
|
||||
c.GroupList["all"].AddHost(ansibleHost)
|
||||
if h.Role.HasRule("manage") {
|
||||
if h.Status == client.NotInstalled || h.Status == client.InstallFailed {
|
||||
c.GroupList["new-manage"].AddHost(ansibleHost)
|
||||
} else {
|
||||
c.GroupList["manage"].AddHost(ansibleHost)
|
||||
}
|
||||
}
|
||||
if h.Role.HasRule("compute") {
|
||||
if h.Status == client.NotInstalled || h.Status == client.InstallFailed {
|
||||
c.GroupList["new-compute"].AddHost(ansibleHost)
|
||||
} else {
|
||||
c.GroupList["compute"].AddHost(ansibleHost)
|
||||
}
|
||||
}
|
||||
if h.Role.HasRule("gateway") {
|
||||
if h.Status == client.NotInstalled || h.Status == client.InstallFailed {
|
||||
c.GroupList["new-gateway"].AddHost(ansibleHost)
|
||||
} else {
|
||||
c.GroupList["gateway"].AddHost(ansibleHost)
|
||||
}
|
||||
}
|
||||
func WriteHostsFile(filePath, installConfPath string, hosts []*client.HostNode) error {
|
||||
return ansibleUtil.WriteHostsFile(filePath, installConfPath, hosts)
|
||||
}
|
||||
|
@ -200,6 +200,11 @@ func NewCmdInit() cli.Command {
|
||||
Usage: "use test shell",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "install_ssh_port",
|
||||
Usage: "new node ssh port",
|
||||
Value: "22",
|
||||
},
|
||||
},
|
||||
Usage: "grctl init cluster",
|
||||
Action: func(c *cli.Context) error {
|
||||
@ -322,6 +327,7 @@ func getConfig(c *cli.Context) map[string]string {
|
||||
configs["EXCSDB_PORT"] = c.String("excsdb-port")
|
||||
configs["EXCSDB_USER"] = c.String("excsdb-user")
|
||||
configs["EXDB_TYPE"] = c.String("exdb-type")
|
||||
configs["INSTALL_SSH_PORT"] = c.String("install_ssh_port")
|
||||
return configs
|
||||
}
|
||||
func initCluster(c *cli.Context) {
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -582,7 +581,7 @@ func NewCmdNode() cli.Command {
|
||||
Usage: "Install a exist node into the cluster",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "hosts-file-path,p",
|
||||
Name: "hosts-file-path",
|
||||
Usage: "hosts file path",
|
||||
Value: "/opt/rainbond/rainbond-ansible/inventory/hosts",
|
||||
},
|
||||
@ -616,16 +615,28 @@ func installNode(node *client.HostNode) {
|
||||
logrus.Errorf("install node scripts is not found")
|
||||
return
|
||||
}
|
||||
line := fmt.Sprintf("/opt/rainbond/rainbond-ansible/scripts/node.sh %s %s %s %s %s %s %s", node.Role[0], node.HostName,
|
||||
node.InternalIP, linkModel, node.RootPass, node.KeyPath, node.ID)
|
||||
cmd := exec.Command("bash", "-c", line)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
|
||||
// node stauts: installing
|
||||
if _, err := clients.RegionClient.Nodes().UpdateNodeStatus(node.ID, client.Installing); err != nil {
|
||||
logrus.Errorf("update node %s status failure %s", node.ID, err.Error())
|
||||
}
|
||||
err := cmd.Run()
|
||||
|
||||
// install node
|
||||
option := coreutil.NodeInstallOption{
|
||||
HostRole: node.Role[0],
|
||||
HostName: node.HostName,
|
||||
InternalIP: node.InternalIP,
|
||||
LinkModel: linkModel,
|
||||
RootPass: node.RootPass,
|
||||
KeyPath: node.KeyPath,
|
||||
NodeID: node.ID,
|
||||
Stdin: os.Stdin,
|
||||
Stderr: os.Stderr,
|
||||
}
|
||||
err := coreutil.RunNodeInstallCmd(option, func(line string) {
|
||||
// run log func
|
||||
fmt.Fprint(os.Stdout, line) // write log to os.Stdout
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("Error executing shell script %s", err.Error())
|
||||
if _, err := clients.RegionClient.Nodes().UpdateNodeStatus(node.ID, client.InstallFailed); err != nil {
|
||||
@ -633,6 +644,8 @@ func installNode(node *client.HostNode) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// node status success
|
||||
if _, err := clients.RegionClient.Nodes().UpdateNodeStatus(node.ID, client.InstallSuccess); err != nil {
|
||||
logrus.Errorf("update node %s status failure %s", node.ID, err.Error())
|
||||
}
|
||||
@ -700,7 +713,7 @@ func installNodeCommand(c *cli.Context) error {
|
||||
nodes, err := clients.RegionClient.Nodes().List()
|
||||
handleErr(err)
|
||||
//write ansible hosts file
|
||||
WriteHostsFile(c.String("p"), nodes)
|
||||
WriteHostsFile(c.String("hosts-file-path"), nodes)
|
||||
installNode(node)
|
||||
return nil
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
@ -30,6 +29,7 @@ import (
|
||||
"github.com/goodrain/rainbond/event"
|
||||
|
||||
"github.com/goodrain/rainbond/util"
|
||||
ansibleUtil "github.com/goodrain/rainbond/util/ansible"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
@ -38,6 +38,7 @@ import (
|
||||
"github.com/goodrain/rainbond/node/masterserver/node"
|
||||
"github.com/goodrain/rainbond/node/nodem/client"
|
||||
"github.com/goodrain/rainbond/node/utils"
|
||||
coreutil "github.com/goodrain/rainbond/util"
|
||||
"github.com/twinj/uuid"
|
||||
)
|
||||
|
||||
@ -99,10 +100,48 @@ func (n *NodeService) InstallNode(node *client.HostNode) *utils.APIHandleError {
|
||||
node.Status = client.Installing
|
||||
node.NodeStatus.Status = client.Installing
|
||||
n.nodecluster.UpdateNode(node)
|
||||
|
||||
// prepare install scripts
|
||||
flag, err := n.beforeInstall()
|
||||
if err != nil {
|
||||
return utils.CreateAPIHandleError(400, err)
|
||||
}
|
||||
|
||||
if !flag {
|
||||
return nil
|
||||
}
|
||||
|
||||
go n.AsynchronousInstall(node)
|
||||
return nil
|
||||
}
|
||||
|
||||
// check install scripts exists or not, if more than one master node has install scripts, choose one master node do it
|
||||
func (n *NodeService) beforeInstall() (flag bool, err error) {
|
||||
// ansible file must exists
|
||||
// if ok, _ := util.FileExists("/opt/rainbond/rainbond-ansible/scripts/node.sh"); !ok {
|
||||
// // TODO 通过etcd创建任务?
|
||||
// return false, nil
|
||||
// }
|
||||
|
||||
// TODO 存在任务则加锁(etcd全局锁),让自己能够执行,加锁失败则不让执行
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// write ansible hosts file
|
||||
func (n *NodeService) writeHostsFile() error {
|
||||
hosts, err := n.GetAllNode()
|
||||
if err != nil {
|
||||
return err.Err
|
||||
}
|
||||
// use default hosts file path and default install config file path
|
||||
erro := ansibleUtil.WriteHostsFile("/opt/rainbond/rainbond-ansible/inventory/hosts", "/opt/rainbond/rainbond-ansible/scripts/installer/global.sh", hosts)
|
||||
if erro != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//UpdateNodeStatus update node status
|
||||
func (n *NodeService) UpdateNodeStatus(nodeID, status string) *utils.APIHandleError {
|
||||
node := n.nodecluster.GetNode(nodeID)
|
||||
@ -120,6 +159,12 @@ func (n *NodeService) UpdateNodeStatus(nodeID, status string) *utils.APIHandleEr
|
||||
|
||||
//AsynchronousInstall AsynchronousInstall
|
||||
func (n *NodeService) AsynchronousInstall(node *client.HostNode) {
|
||||
// write ansible hosts file
|
||||
err := n.writeHostsFile()
|
||||
if err != nil {
|
||||
logrus.Error("write hosts file error ", err.Error())
|
||||
return
|
||||
}
|
||||
linkModel := "pass"
|
||||
if node.KeyPath != "" {
|
||||
linkModel = "key"
|
||||
@ -129,18 +174,15 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) {
|
||||
}); err != nil {
|
||||
logrus.Errorf("create event manager faliure")
|
||||
}
|
||||
//TODO: write log to event log
|
||||
//logger := event.GetManager().GetLogger(node.ID + "-insatll")
|
||||
|
||||
// start add node script
|
||||
logrus.Infof("Begin install node %s", node.ID)
|
||||
// TODO: write ansible hosts file
|
||||
line := fmt.Sprintf("./node.sh %s %s %s %s %s %s %s", node.Role[0], node.HostName,
|
||||
node.InternalIP, linkModel, node.RootPass, node.KeyPath, node.ID)
|
||||
fileName := node.HostName + ".log"
|
||||
cmd := exec.Command("bash", "-c", line)
|
||||
|
||||
if err := util.CheckAndCreateDir("/grdata/downloads/log/"); err != nil {
|
||||
logrus.Errorf("check and create log dir failure %s", err.Error())
|
||||
}
|
||||
|
||||
fileName := node.HostName + ".log"
|
||||
f, err := os.OpenFile("/grdata/downloads/log/"+fileName, os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0755)
|
||||
if err != nil {
|
||||
logrus.Errorf("open log file %s failure %s", "/grdata/downloads/log/"+fileName, err.Error())
|
||||
@ -150,10 +192,31 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
cmd.Stdout = f
|
||||
cmd.Dir = "/opt/rainbond/rainbond-ansible/scripts"
|
||||
cmd.Stderr = f
|
||||
err = cmd.Run()
|
||||
|
||||
option := coreutil.NodeInstallOption{
|
||||
HostRole: node.Role[0],
|
||||
HostName: node.HostName,
|
||||
InternalIP: node.InternalIP,
|
||||
LinkModel: linkModel,
|
||||
RootPass: node.RootPass,
|
||||
KeyPath: node.KeyPath,
|
||||
NodeID: node.ID,
|
||||
Stdin: nil,
|
||||
Stderr: f,
|
||||
}
|
||||
|
||||
// write log to event log
|
||||
logger := event.GetManager().GetLogger(node.ID + "-insatll")
|
||||
err = coreutil.RunNodeInstallCmd(option, func(line string) {
|
||||
// run log func
|
||||
logger.Info(line, map[string]string{"step": "node-install", "status": "installing"}) // write log to eventLog
|
||||
_, err = f.WriteString(line) // write log to file
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
// fmt.Fprint(os.Stdout, line) //write os.Stdout
|
||||
})
|
||||
if err != nil {
|
||||
if _, err := f.Write([]byte(err.Error())); err != nil {
|
||||
logrus.Errorf("Error write file %s", err.Error())
|
||||
@ -164,9 +227,12 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) {
|
||||
n.nodecluster.UpdateNode(node)
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Infof("Install node %s successful", node.ID)
|
||||
|
||||
node.Status = client.InstallSuccess
|
||||
node.NodeStatus.Status = client.InstallSuccess
|
||||
|
||||
n.nodecluster.UpdateNode(node)
|
||||
}
|
||||
|
||||
|
216
util/ansible/ansible.go
Normal file
216
util/ansible/ansible.go
Normal file
@ -0,0 +1,216 @@
|
||||
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 {
|
||||
config := GetAnsibleHostConfig(filePath)
|
||||
for i := range hosts {
|
||||
config.AddHost(hosts[i], installConfPath)
|
||||
}
|
||||
return config.WriteFile()
|
||||
}
|
||||
|
||||
//AnsibleHost ansible host config
|
||||
type AnsibleHost struct {
|
||||
AnsibleHostIP net.IP
|
||||
//ssh port
|
||||
AnsibleHostPort int
|
||||
HostID string
|
||||
Role client.HostRule
|
||||
CreateTime time.Time
|
||||
}
|
||||
|
||||
func (a *AnsibleHost) String() string {
|
||||
if a.Role.HasRule("all") {
|
||||
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)
|
||||
} else if a.Role.HasRule("etcd") {
|
||||
return fmt.Sprintf("%s ansible_host=%s NODE_NAME=etcd1", a.HostID, a.AnsibleHostIP)
|
||||
} else {
|
||||
return fmt.Sprintf("%s ansible_host=%s", a.HostID, a.AnsibleHostIP)
|
||||
}
|
||||
}
|
||||
|
||||
type HostsList []*AnsibleHost
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
//AnsibleHostGroup ansible host group config
|
||||
type AnsibleHostGroup struct {
|
||||
Name string
|
||||
HostList HostsList
|
||||
}
|
||||
|
||||
//AddHost add host
|
||||
func (a *AnsibleHostGroup) AddHost(h *AnsibleHost) {
|
||||
for _, old := range a.HostList {
|
||||
if old.AnsibleHostIP.String() == h.AnsibleHostIP.String() {
|
||||
return
|
||||
}
|
||||
}
|
||||
a.HostList = append(a.HostList, h)
|
||||
|
||||
}
|
||||
func (a *AnsibleHostGroup) 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()
|
||||
}
|
||||
|
||||
//AnsibleHostConfig ansible hosts config
|
||||
type AnsibleHostConfig struct {
|
||||
FileName string
|
||||
GroupList map[string]*AnsibleHostGroup
|
||||
}
|
||||
|
||||
//GetAnsibleHostConfig get config
|
||||
func GetAnsibleHostConfig(name string) *AnsibleHostConfig {
|
||||
return &AnsibleHostConfig{
|
||||
FileName: name,
|
||||
GroupList: map[string]*AnsibleHostGroup{
|
||||
"all": &AnsibleHostGroup{Name: "all"},
|
||||
"manage": &AnsibleHostGroup{Name: "manage"},
|
||||
"new-manage": &AnsibleHostGroup{Name: "new-manage"},
|
||||
"gateway": &AnsibleHostGroup{Name: "gateway"},
|
||||
"new-gateway": &AnsibleHostGroup{Name: "new-gateway"},
|
||||
"compute": &AnsibleHostGroup{Name: "compute"},
|
||||
"new-compute": &AnsibleHostGroup{Name: "new-compute"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
//Content return config file content
|
||||
func (c *AnsibleHostConfig) Content() string {
|
||||
return c.ContentBuffer().String()
|
||||
}
|
||||
|
||||
//ContentBuffer content buffer
|
||||
func (c *AnsibleHostConfig) 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 *AnsibleHostConfig) 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
|
||||
} else {
|
||||
return port
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 22
|
||||
}
|
||||
|
||||
//AddHost add host
|
||||
func (c *AnsibleHostConfig) AddHost(h *client.HostNode, installConfPath string) {
|
||||
//check role
|
||||
//check status
|
||||
ansibleHost := &AnsibleHost{
|
||||
AnsibleHostIP: net.ParseIP(h.InternalIP),
|
||||
AnsibleHostPort: getSSHPort(installConfPath),
|
||||
HostID: h.ID,
|
||||
Role: h.Role,
|
||||
CreateTime: h.CreateTime,
|
||||
}
|
||||
c.GroupList["all"].AddHost(ansibleHost)
|
||||
if h.Role.HasRule("manage") {
|
||||
if h.Status == client.NotInstalled || h.Status == client.InstallFailed {
|
||||
c.GroupList["new-manage"].AddHost(ansibleHost)
|
||||
} else {
|
||||
c.GroupList["manage"].AddHost(ansibleHost)
|
||||
}
|
||||
}
|
||||
if h.Role.HasRule("compute") {
|
||||
if h.Status == client.NotInstalled || h.Status == client.InstallFailed {
|
||||
c.GroupList["new-compute"].AddHost(ansibleHost)
|
||||
} else {
|
||||
c.GroupList["compute"].AddHost(ansibleHost)
|
||||
}
|
||||
}
|
||||
if h.Role.HasRule("gateway") {
|
||||
if h.Status == client.NotInstalled || h.Status == client.InstallFailed {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
140
util/node.go
Normal file
140
util/node.go
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
type NodeInstallOption struct {
|
||||
HostRole string
|
||||
HostName string
|
||||
InternalIP string
|
||||
LinkModel string
|
||||
RootPass string
|
||||
KeyPath string
|
||||
NodeID string
|
||||
Stdin *os.File
|
||||
Stderr *os.File
|
||||
}
|
||||
|
||||
func RunNodeInstallCmd(option NodeInstallOption, runLog func(line string)) (err error) {
|
||||
// ansible file must exists
|
||||
if ok, _ := FileExists("/opt/rainbond/rainbond-ansible/scripts/node.sh"); !ok {
|
||||
err = fmt.Errorf("install node scripts is not found")
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// ansible's param can't send nil nor empty string
|
||||
if err = preCheckNodeInstall(option); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
line := fmt.Sprintf("/opt/rainbond/rainbond-ansible/scripts/node.sh %s %s %s %s %s %s %s",
|
||||
option.HostRole, option.HostName, option.InternalIP, option.LinkModel, option.RootPass, option.KeyPath, option.NodeID)
|
||||
|
||||
cmd := exec.Command("bash", "-c", line)
|
||||
cmd.Stderr = option.Stderr
|
||||
cmd.Stdin = option.Stdin
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
logrus.Errorf("install node failed")
|
||||
return err
|
||||
}
|
||||
|
||||
// for another log
|
||||
reader := bufio.NewReader(stdout)
|
||||
go func() {
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Errorf("install node failed")
|
||||
return
|
||||
}
|
||||
|
||||
if runLog != nil {
|
||||
runLog(line)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
logrus.Errorf("install node failed")
|
||||
return err
|
||||
}
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
logrus.Errorf("install node finished with error : %v", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func preCheckNodeInstall(option NodeInstallOption) (err error) {
|
||||
// TODO check param
|
||||
if strings.TrimSpace(option.HostRole) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param hostRole")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(option.HostName) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param hostName")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(option.InternalIP) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param internalIP")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(option.LinkModel) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param linkModel")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(option.RootPass) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param rootPass")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(option.KeyPath) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param keyPath")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(option.NodeID) == "" {
|
||||
err = fmt.Errorf("install node failed, install scripts needs param nodeID")
|
||||
logrus.Error(err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user