From 7d83add0f0b728947e57303a39521e4787b6de61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=A1=E7=BE=8A=E7=BE=8A?= Date: Wed, 7 Aug 2019 11:05:57 +0800 Subject: [PATCH] fix bugs use chan transport log and use env for installNodeShellPath --- grctl/cmd/node.go | 23 +++++++++--- node/core/service/node_service.go | 33 ++++++++++++------ util/node.go | 58 ++++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 28 deletions(-) diff --git a/grctl/cmd/node.go b/grctl/cmd/node.go index 017c7166a..b82dab8ee 100644 --- a/grctl/cmd/node.go +++ b/grctl/cmd/node.go @@ -25,6 +25,7 @@ import ( "os" "strconv" "strings" + "sync" "github.com/fatih/color" @@ -636,12 +637,21 @@ func installNode(node *client.HostNode) { 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 - }) + + logChan := make(chan string, 10) + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + // write log + for line := range logChan { + fmt.Fprint(os.Stdout, line) // write log to os.Stdout + } + wg.Done() + }() + + err := coreutil.RunNodeInstallCmd(option, logChan) + if err != nil { logrus.Errorf("Error executing shell script %s", err.Error()) if _, err := clients.RegionClient.Nodes().UpdateNodeStatus(node.ID, client.InstallFailed); err != nil { @@ -650,6 +660,9 @@ func installNode(node *client.HostNode) { return } + // wait log write finish + wg.Wait() + // 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()) diff --git a/node/core/service/node_service.go b/node/core/service/node_service.go index 595a31836..018dbdd29 100644 --- a/node/core/service/node_service.go +++ b/node/core/service/node_service.go @@ -24,6 +24,7 @@ import ( "os" "sort" "strconv" + "sync" "time" "github.com/goodrain/rainbond/event" @@ -210,21 +211,30 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) { 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 + + logChan := make(chan string, 10) + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + // write log + for line := range logChan { + 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 } - // fmt.Fprint(os.Stdout, line) //write os.Stdout - }) + wg.Done() + }() + + err = coreutil.RunNodeInstallCmd(option, logChan) + if err != nil { if _, err := f.Write([]byte(err.Error())); err != nil { logrus.Errorf("Error write file %s", err.Error()) @@ -236,6 +246,9 @@ func (n *NodeService) AsynchronousInstall(node *client.HostNode) { return } + // wait log write finish + wg.Wait() + logrus.Infof("Install node %s successful", node.ID) node.Status = client.InstallSuccess diff --git a/util/node.go b/util/node.go index b0e06df27..63512f247 100644 --- a/util/node.go +++ b/util/node.go @@ -25,6 +25,7 @@ import ( "os" "os/exec" "strings" + "sync" "github.com/Sirupsen/logrus" ) @@ -38,12 +39,16 @@ type NodeInstallOption struct { KeyPath string NodeID string Stdin *os.File - Stderr *os.File } -func RunNodeInstallCmd(option NodeInstallOption, runLog func(line string)) (err error) { +func RunNodeInstallCmd(option NodeInstallOption, logChan chan string) (err error) { + installNodeShellPath := os.Getenv("INSTALL_NODE_SHELL_PATH") + if installNodeShellPath == "" { + installNodeShellPath = "/opt/rainbond/rainbond-ansible/scripts/node.sh" + } + // ansible file must exists - if ok, _ := FileExists("/opt/rainbond/rainbond-ansible/scripts/node.sh"); !ok { + if ok, _ := FileExists(installNodeShellPath); !ok { err = fmt.Errorf("install node scripts is not found") logrus.Error(err) return err @@ -54,21 +59,28 @@ func RunNodeInstallCmd(option NodeInstallOption, runLog func(line string)) (err return } - line := fmt.Sprintf("/opt/rainbond/rainbond-ansible/scripts/node.sh %s %s %s %s %s %s %s", + line := fmt.Sprintf(installNodeShellPath+" %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 + stderr, err := cmd.StderrPipe() + if err != nil { + logrus.Errorf("install node failed") + return err + } stdout, err := cmd.StdoutPipe() if err != nil { logrus.Errorf("install node failed") return err } + wg := sync.WaitGroup{} + // for another log reader := bufio.NewReader(stdout) + wg.Add(1) go func() { for { line, err := reader.ReadString('\n') @@ -80,10 +92,26 @@ func RunNodeInstallCmd(option NodeInstallOption, runLog func(line string)) (err return } - if runLog != nil { - runLog(line) - } + logChan <- line } + wg.Done() + }() + + readerStderr := bufio.NewReader(stderr) + wg.Add(1) + go func() { + for { + line, err := readerStderr.ReadString('\n') + if err == io.EOF { + break + } + if err != nil { + logrus.Error("install node failed") + return + } + logChan <- line + } + wg.Done() }() err = cmd.Start() @@ -96,6 +124,9 @@ func RunNodeInstallCmd(option NodeInstallOption, runLog func(line string)) (err if err != nil { logrus.Errorf("install node finished with error : %v", err.Error()) } + // wait clse logChan + wg.Wait() + close(logChan) return } @@ -126,11 +157,12 @@ func preCheckNodeInstall(option NodeInstallOption) (err error) { 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 rootPass is not empty then keyPath can be empty + // 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)