[REV]Improved logic for node installation #342

This commit is contained in:
barnett 2019-08-07 14:28:20 +08:00
parent c815b86204
commit e86e5e258e
9 changed files with 77 additions and 98 deletions

View File

@ -258,7 +258,7 @@ func (r *resourcesTenant) Get() (*model.TenantResource, *util.APIHandleError) {
func handleAPIResult(code int, res utilhttp.ResponseBody) *util.APIHandleError {
if code >= 300 {
return util.CreateAPIHandleErrorf(code, res.Msg)
return util.CreateAPIHandleErrorf(code, "msg:%s validation_error %+v", res.Msg, res.ValidationError)
}
return nil
}

View File

@ -76,7 +76,7 @@ func (a *APIHandleError) Error() string {
}
func (a *APIHandleError) String() string {
return fmt.Sprintf("%d:%s", a.Code, a.Err.Error())
return fmt.Sprintf("(Code:%d) %s", a.Code, a.Err.Error())
}
//Handle 处理

View File

@ -47,26 +47,26 @@ func TestAnsibleHostConfig(t *testing.T) {
}
ansibleConfig := &AnsibleHostConfig{
FileName: "/tmp/hosts",
GroupList: []*AnsibleHostGroup{
&AnsibleHostGroup{
GroupList: map[string]*AnsibleHostGroup{
"all": &AnsibleHostGroup{
Name: "all",
HostList: []*AnsibleHost{
h1, h2, h3,
},
},
&AnsibleHostGroup{
"manage": &AnsibleHostGroup{
Name: "manage",
HostList: []*AnsibleHost{
h1, h2, h3,
},
},
&AnsibleHostGroup{
"gateway": &AnsibleHostGroup{
Name: "gateway",
HostList: []*AnsibleHost{
h3,
},
},
&AnsibleHostGroup{
"compute": &AnsibleHostGroup{
Name: "compute",
HostList: []*AnsibleHost{
h2,

View File

@ -26,6 +26,8 @@ import (
"os/exec"
"strings"
"github.com/goodrain/rainbond/node/nodem/client"
"github.com/goodrain/rainbond/util"
"github.com/Sirupsen/logrus"
@ -195,6 +197,10 @@ func NewCmdInit() cli.Command {
Usage: "Additional support for the console to configure the database separately",
Value: "",
},
cli.BoolFlag{
Name: "not-install-ui",
Usage: "Whether or not to install the UI, normally no UI is installed when installing a second data center",
},
cli.BoolFlag{
Name: "test",
Usage: "use test shell",
@ -240,7 +246,6 @@ func NewCmdInstallStatus() cli.Command {
//Status(v.ID)
return nil
}
}
}
} else {
@ -251,8 +256,8 @@ func NewCmdInstallStatus() cli.Command {
}
return c
}
func updateConfigFile(path string, config map[string]string) error {
initConfig := make(map[string]string)
func updateConfigFile(path string, config map[string]interface{}) error {
initConfig := make(map[string]interface{})
var file *os.File
var err error
if ok, _ := util.FileExists(path); ok {
@ -289,16 +294,23 @@ func updateConfigFile(path string, config map[string]string) error {
if k == "" {
continue
}
if v == "" {
file.WriteString(fmt.Sprintf("%s=\"\"\n", k))
} else {
file.WriteString(fmt.Sprintf("%s=\"%s\"\n", k, v))
switch v.(type) {
case string:
if v == "" {
file.WriteString(fmt.Sprintf("%s=\"\"\n", k))
} else {
file.WriteString(fmt.Sprintf("%s=\"%s\"\n", k, v))
}
case bool:
file.WriteString(fmt.Sprintf("%s=%t\n", k, v))
default:
continue
}
}
return nil
}
func getConfig(c *cli.Context) map[string]string {
configs := make(map[string]string)
func getConfig(c *cli.Context) map[string]interface{} {
configs := make(map[string]interface{})
configs["ROLE"] = c.String("role")
//configs["work_dir"] = c.String("work_dir")
configs["IIP"] = c.String("iip")
@ -328,6 +340,7 @@ func getConfig(c *cli.Context) map[string]string {
configs["EXCSDB_USER"] = c.String("excsdb-user")
configs["EXDB_TYPE"] = c.String("exdb-type")
configs["INSTALL_SSH_PORT"] = c.String("install_ssh_port")
configs["INSTALL_UI"] = !c.Bool("not-install-ui")
return configs
}
func initCluster(c *cli.Context) {
@ -338,6 +351,16 @@ func initCluster(c *cli.Context) {
println("Rainbond is already installed, if you want reinstall, then please delete the file: /opt/rainbond/.rainbond.success")
return
}
role := c.String("role")
roles := client.HostRule(strings.Split(role, ","))
if err := roles.Validation(); err != nil {
println(err.Error())
return
}
if !roles.HasRule("manage") || !roles.HasRule("gateway") {
println("first node must have manage and gateway role")
return
}
// download source code from github if in online model
if c.String("install-type") == "online" {
fmt.Println("Download the installation configuration file remotely...")
@ -353,29 +376,20 @@ func initCluster(c *cli.Context) {
return
}
}
if err := updateConfigFile(c.String("config-file"), getConfig(c)); err != nil {
showError("update config file failure " + err.Error())
}
//storage file
//fmt.Println("Check storage type")
//ioutil.WriteFile("/tmp/.storage.value", []byte(c.String("storage-args")), 0644)
// start setup script to install rainbond
fmt.Println("Initializes the installation of the first node...")
cmd := exec.Command("bash", "-c", fmt.Sprintf("cd %s ; ./setup.sh", c.String("work_dir")))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err = cmd.Run()
if err != nil {
println(err.Error())
return
}
ioutil.WriteFile("/opt/rainbond/.rainbond.success", []byte(c.String("rainbond-version")), 0644)
return
}

View File

@ -40,7 +40,7 @@ import (
func handleErr(err *util.APIHandleError) {
if err != nil && err.Err != nil {
fmt.Printf("Code %d, Msg:%v\n", err.Code, err.String())
fmt.Printf(err.String())
os.Exit(1)
}
}
@ -536,10 +536,15 @@ func NewCmdNode() cli.Command {
Usage: "The option is required",
},
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: "ansible global config file path",
Value: "/opt/rainbond/rainbond-ansible/scripts/installer/global.sh",
},
cli.StringFlag{
Name: "internal-ip,iip",
Usage: "The option is required",
@ -587,7 +592,7 @@ func NewCmdNode() cli.Command {
},
cli.StringFlag{
Name: "config-file-path",
Usage: "install config path",
Usage: "ansible global config file path",
Value: "/opt/rainbond/rainbond-ansible/scripts/installer/global.sh",
},
},
@ -610,28 +615,17 @@ func isNodeReady(node *client.HostNode) bool {
}
func installNode(node *client.HostNode) {
linkModel := "pass"
if node.KeyPath != "" {
linkModel = "key"
}
// start add node script
logrus.Infof("Begin install node %s", node.ID)
if ok, _ := coreutil.FileExists("/opt/rainbond/rainbond-ansible/scripts/node.sh"); !ok {
logrus.Errorf("install node scripts is not found")
return
}
// 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())
}
// install node
option := coreutil.NodeInstallOption{
HostRole: node.Role[0],
HostRole: node.Role.String(),
HostName: node.HostName,
InternalIP: node.InternalIP,
LinkModel: linkModel,
RootPass: node.RootPass,
KeyPath: node.KeyPath,
NodeID: node.ID,
@ -687,7 +681,6 @@ func addNodeCommand(c *cli.Context) error {
if err := node.Role.Validation(); err != nil {
showError(err.Error())
}
fmt.Println(node.Role)
node.HostName = c.String("hostname")
node.RootPass = c.String("root-pass")
node.InternalIP = c.String("internal-ip")
@ -699,7 +692,10 @@ func addNodeCommand(c *cli.Context) error {
renode, err := clients.RegionClient.Nodes().Add(&node)
handleErr(err)
if c.Bool("install") {
nodes, err := clients.RegionClient.Nodes().List()
handleErr(err)
//write ansible hosts file
WriteHostsFile(c.String("hosts-file-path"), c.String("config-file-path"), nodes)
installNode(renode)
} else {
fmt.Printf("success add %s node %s \n you install it by running: grctl node install %s \n", renode.Role, renode.ID, renode.ID)

View File

@ -172,10 +172,6 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) {
logrus.Error("write hosts file error ", err.Error())
return
}
linkModel := "pass"
if node.KeyPath != "" {
linkModel = "key"
}
if err := event.NewManager(event.EventConfig{
DiscoverAddress: n.c.Etcd.Endpoints,
}); err != nil {
@ -189,10 +185,9 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) {
logger := event.GetManager().GetLogger(node.ID + "-insatll")
option := coreutil.NodeInstallOption{
HostRole: node.Role[0],
HostRole: node.Role.String(),
HostName: node.HostName,
InternalIP: node.InternalIP,
LinkModel: linkModel,
RootPass: node.RootPass,
KeyPath: node.KeyPath,
NodeID: node.ID,

View File

@ -26,7 +26,7 @@ func WriteHostsFile(filePath, installConfPath string, hosts []*client.HostNode)
return config.WriteFile()
}
//AnsibleHost ansible host config
//AnsibleHost ansible host config
type AnsibleHost struct {
AnsibleHostIP net.IP
//ssh port
@ -77,7 +77,7 @@ func (a *AnsibleHostGroup) String() string {
if a.Name == "all" {
rebuffer.WriteString(a.HostList[i].String() + "\n")
} else if a.Name == "etcd" {
rebuffer.WriteString(a.HostList[i].HostID + " NODE_NAME=etcd1" + "\n")
rebuffer.WriteString(a.HostList[i].HostID + "\n")
} else {
rebuffer.WriteString(a.HostList[i].HostID + "\n")
}

View File

@ -24,15 +24,13 @@ import (
"os"
"os/exec"
"strings"
"github.com/Sirupsen/logrus"
)
//NodeInstallOption node install option
type NodeInstallOption struct {
HostRole string
HostName string
InternalIP string
LinkModel string
RootPass string // ssh login password
KeyPath string // ssh login key path
NodeID string
@ -40,8 +38,10 @@ type NodeInstallOption struct {
Stdout io.Writer
Stderr io.Writer
loginValue string
linkModel string
}
//RunNodeInstallCmd install node
func RunNodeInstallCmd(option NodeInstallOption) (err error) {
installNodeShellPath := os.Getenv("INSTALL_NODE_SHELL_PATH")
if installNodeShellPath == "" {
@ -50,76 +50,49 @@ func RunNodeInstallCmd(option NodeInstallOption) (err error) {
// ansible file must exists
if ok, _ := FileExists(installNodeShellPath); !ok {
err = fmt.Errorf("install node scripts is not found")
logrus.Error(err)
return fmt.Errorf("install node scripts is not found")
}
fmt.Println(option)
// ansible's param can't send nil nor empty string
if err := preCheckNodeInstall(&option); err != nil {
return err
}
// ansible's param can't send nil nor empty string
if err = preCheckNodeInstall(option); err != nil {
return
}
line := fmt.Sprintf(installNodeShellPath+" %s %s %s %s %s %s",
option.HostRole, option.HostName, option.InternalIP, option.LinkModel, option.loginValue, option.NodeID)
option.HostRole, option.HostName, option.InternalIP, option.linkModel, option.loginValue, option.NodeID)
fmt.Println(line)
cmd := exec.Command("bash", "-c", line)
cmd.Stdin = option.Stdin
cmd.Stdout = option.Stdout
cmd.Stderr = option.Stderr
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
return cmd.Run()
}
// check param
func preCheckNodeInstall(option NodeInstallOption) (err error) {
func preCheckNodeInstall(option *NodeInstallOption) error {
if strings.TrimSpace(option.HostRole) == "" {
err = fmt.Errorf("install node failed, install scripts needs param hostRole")
logrus.Error(err)
return
return fmt.Errorf("install node failed, install scripts needs param hostRole")
}
if strings.TrimSpace(option.HostName) == "" {
err = fmt.Errorf("install node failed, install scripts needs param hostName")
logrus.Error(err)
return
return fmt.Errorf("install node failed, install scripts needs param hostName")
}
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
return fmt.Errorf("install node failed, install scripts needs param internalIP")
}
//login key path first, and then rootPass, so keyPath and RootPass can't all be empty
if strings.TrimSpace(option.KeyPath) == "" {
if strings.TrimSpace(option.RootPass) == "" {
err = fmt.Errorf("install node failed, install scripts needs login key path or login password")
logrus.Error(err)
return
return fmt.Errorf("install node failed, install scripts needs login key path or login password")
}
option.loginValue = strings.TrimSpace(option.RootPass)
option.linkModel = "pass"
} else {
option.loginValue = strings.TrimSpace(option.KeyPath)
option.linkModel = "key"
}
option.loginValue = strings.TrimSpace(option.KeyPath)
if strings.TrimSpace(option.NodeID) == "" {
err = fmt.Errorf("install node failed, install scripts needs param nodeID")
logrus.Error(err)
return
return fmt.Errorf("install node failed, install scripts needs param nodeID")
}
return
return nil
}

View File

@ -162,4 +162,5 @@ func (m *Controller) Scrape(ch chan<- prometheus.Metric, scrapeDurationDesc *pro
ch <- prometheus.MustNewConstMetric(scrapeDurationDesc, prometheus.GaugeValue, time.Since(scrapeTime).Seconds(), "collect.fs")
m.fsUse.Collect(ch)
m.memoryUse.Collect(ch)
logrus.Infof("success collect app disk and memory used metric")
}