From 0588fc3c2a84a718634f7d7ad48536e97ec252bf Mon Sep 17 00:00:00 2001 From: chenglch Date: Tue, 14 Nov 2017 19:44:37 +0800 Subject: [PATCH] Modify the default port for goconserver rest api This commit modify the default port for rest api interface, use 12429 by default. This commit also includes the fix for the tty window size. --- benchmark/api.py | 4 ++- common/conf.go | 4 +-- common/errors.go | 8 +++++ console/client.go | 55 ++++++++++++++++++++++++++++++--- console/console.go | 7 ++--- etc/goconserver/client.sh | 2 +- etc/goconserver/server.conf | 4 +-- etc/systemd/goconserver.service | 2 +- plugins/ssh.go | 47 +++++++++++++++++++++++++--- scripts/setup.sh | 2 +- 10 files changed, 113 insertions(+), 22 deletions(-) diff --git a/benchmark/api.py b/benchmark/api.py index 26c399f..fa29f7c 100755 --- a/benchmark/api.py +++ b/benchmark/api.py @@ -34,7 +34,7 @@ def __init__(self, count): if 'consoleserver_host' in os.environ: self.host = os.environ["consoleserver_host"] else: - self.host = 'http://localhost:8089' + self.host = 'http://localhost:12429' @elaspe_run(desc="post") def test_post(self): @@ -153,6 +153,8 @@ def _test_get(i): api.test_bulk_post() elif method == 'bulk_delete': api.test_bulk_delete() + elif method == 'list': + api.test_list() else: print("Unsupport sub command %s." % method) else: diff --git a/common/conf.go b/common/conf.go index 27467ba..7a789ef 100644 --- a/common/conf.go +++ b/common/conf.go @@ -51,7 +51,7 @@ func InitServerConfig(confFile string) (*ServerConfig, error) { serverConfig.Global.Worker = 1 serverConfig.Global.LogLevel = "info" serverConfig.Global.StorageType = "file" - serverConfig.API.Port = "8089" + serverConfig.API.Port = "12429" serverConfig.API.HttpTimeout = 10 serverConfig.Console.Port = "12430" serverConfig.Console.DataDir = "/var/lib/goconserver/" @@ -93,7 +93,7 @@ type ClientConfig struct { func NewClientConfig() (*ClientConfig, error) { var err error clientConfig = new(ClientConfig) - clientConfig.HTTPUrl = "http://127.0.0.1:8089" + clientConfig.HTTPUrl = "http://127.0.0.1:12429" clientConfig.ServerHost = "127.0.0.1" clientConfig.ConsolePort = "12430" clientConfig.ConsoleTimeout = 30 diff --git a/common/errors.go b/common/errors.go index 09dc9c0..e864b1a 100644 --- a/common/errors.go +++ b/common/errors.go @@ -19,6 +19,8 @@ const ( HOST_NOT_EXIST INVALID_TYPE ETCD_NOT_INIT + SET_DEADLINE_ERROR + SEND_KEEPALIVE_ERROR // error message STRING_NOT_EXIST = "Not exist" @@ -39,6 +41,9 @@ const ( STRING_NOT_TERMINAL = "Not terminal" STRING_INVALID_TYPE = "Invalid type" STRING_ETCD_NOT_INIT = "Etcd is not initialized" + //ssh + STRING_SET_DEADLINE_ERROR = "failed to set deadline" + STRING_SEND_KEEPALIVE_ERROR = "failed to send keep alive" ) var ( @@ -59,6 +64,9 @@ var ( ErrNotTerminal = NewErr(NOT_TERMINAL, STRING_NOT_TERMINAL) ErrInvalidType = NewErr(INVALID_TYPE, STRING_INVALID_TYPE) + // ssh + ErrSetDeadline = NewErr(SET_DEADLINE_ERROR, STRING_SET_DEADLINE_ERROR) + ErrSendKeepalive = NewErr(SEND_KEEPALIVE_ERROR, STRING_SEND_KEEPALIVE_ERROR) // etcd ErrETCDNotInit = NewErr(ETCD_NOT_INIT, STRING_ETCD_NOT_INIT) ) diff --git a/console/client.go b/console/client.go index 48355b2..fc94f5b 100644 --- a/console/client.go +++ b/console/client.go @@ -21,6 +21,7 @@ type ConsoleClient struct { host, port string origState *terminal.State escape int // client exit signal + cr int exit chan bool retry bool inputTask *common.Task @@ -69,11 +70,16 @@ func (c *ConsoleClient) output(args ...interface{}) { c.exit <- true return } - n, err = os.Stdout.Write(b) - if err != nil { - fmt.Printf("\rCould not send message, error: %s\r\n", err.Error()) - c.exit <- true - return + b = c.transCr(b, n) + n = len(b) + for n > 0 { + tmp, err := os.Stdout.Write(b) + if err != nil { + fmt.Printf("\rCould not send message, error: %s\r\n", err.Error()) + c.exit <- true + return + } + n -= tmp } } @@ -127,6 +133,45 @@ func (c *ConsoleClient) checkEscape(b []byte, n int) (bool, int) { return false, pos } +func (c *ConsoleClient) transCr(b []byte, n int) []byte { + temp := make([]byte, 4096) + j := 0 + for i := 0; i < n; i++ { + ch := b[i] + if c.cr == 0 { + if ch == ' ' { + c.cr = 1 + } else { + temp[j] = ch + j++ + } + } else if c.cr == 1 { + if ch == '\r' { + c.cr = 2 + } else { + temp[j], temp[j+1] = ' ', ch + j += 2 + c.cr = 0 + } + } else if c.cr == 2 { + if ch == '\n' { + temp[j], temp[j+1], temp[j+2] = ' ', '\r', ch + j += 3 + } else { + temp[j] = ch // ignore " \r" + j++ + } + c.cr = 0 + } + } + if c.cr == 1 { + c.cr = 0 + temp[j] = ' ' + j++ + } + return temp[0:j] +} + func (c *ConsoleClient) tryConnect(conn net.Conn, name string) (int, error) { m := make(map[string]string) m["name"] = name diff --git a/console/console.go b/console/console.go index bf7e55d..94928f8 100644 --- a/console/console.go +++ b/console/console.go @@ -133,7 +133,6 @@ func (c *Console) writeClient(conn net.Conn) { err = c.logger(logFile, []byte(welcome)) if err != nil { plog.WarningNode(c.node.StorageNode.Name, fmt.Sprintf("Failed to log message to %s. Error:%s", logFile, err.Error())) - return } for { if bufChan, ok = c.bufConn[conn]; !ok { @@ -163,7 +162,6 @@ func (c *Console) readTarget() { err = c.logger(logFile, []byte(msg)) if err != nil { plog.WarningNode(c.node.StorageNode.Name, fmt.Sprintf("Failed to log message to %s. Error:%s", logFile, err.Error())) - return } for { select { @@ -185,15 +183,16 @@ func (c *Console) readTarget() { err = c.logger(logFile, b[:n]) if err != nil { plog.WarningNode(c.node.StorageNode.Name, fmt.Sprintf("Failed to log message to %s. Error:%s", logFile, err.Error())) - return } } } } func (c *Console) writeClientChan(buf []byte) { + b := make([]byte, len(buf)) + copy(b, buf) for _, v := range c.bufConn { - v <- buf + v <- b } } diff --git a/etc/goconserver/client.sh b/etc/goconserver/client.sh index 8eb8476..3b3f64d 100644 --- a/etc/goconserver/client.sh +++ b/etc/goconserver/client.sh @@ -1,4 +1,4 @@ -export CONGO_URL="http://127.0.0.1:8089" +export CONGO_URL="http://127.0.0.1:12429" export CONGO_SERVER_HOST="127.0.0.1" export CONGO_PORT="12430" export CONGO_CONSOLE_TIMEOUT=3 diff --git a/etc/goconserver/server.conf b/etc/goconserver/server.conf index 413a279..4f09f20 100644 --- a/etc/goconserver/server.conf +++ b/etc/goconserver/server.conf @@ -4,12 +4,12 @@ global: # ssl_cert_file: /etc/goconserver/cert/server-cert.pem # ssl_ca_cert_file: /etc/goconserver/cert/ca.pem logfile: "/var/log/goconserver/server.log" # the log file for goconserver daemon. - log_level: "info" # debug, info, warn, error, fatal, panic + log_level: info # debug, info, warn, error, fatal, panic worker: 4 # the max cpu cores for user workload storage_type: file # file or etcd, etcd is just experimental option. api: - port: "8089" # http(s) port + port: "12429" # http(s) port http_timeout: 5 # in second console: diff --git a/etc/systemd/goconserver.service b/etc/systemd/goconserver.service index 752bb06..fab2fb1 100644 --- a/etc/systemd/goconserver.service +++ b/etc/systemd/goconserver.service @@ -2,7 +2,7 @@ Description=goconserver [Service] LimitNOFILE=65535 -ExecStart=/usr/local/bin/goconserver +ExecStart=/usr/bin/goconserver ExecStop=/bin/kill -TERM $MAINPID ExecReload=/bin/kill -HUP $MAINPID killMode=process diff --git a/plugins/ssh.go b/plugins/ssh.go index 3fa6c07..b14dfa3 100644 --- a/plugins/ssh.go +++ b/plugins/ssh.go @@ -8,6 +8,7 @@ import ( "github.com/chenglch/goconserver/common" "golang.org/x/crypto/ssh" + "net" "os" ) @@ -41,6 +42,7 @@ type SSHConsole struct { host string client *ssh.Client session *ssh.Session + exit chan bool } func NewSSHConsole(node string, params map[string]string) (ConsolePlugin, error) { @@ -73,9 +75,11 @@ func NewSSHConsole(node string, params map[string]string) (ConsolePlugin, error) var sshInst *SSHConsole if privateKey != "" { - sshInst = &SSHConsole{host: fmt.Sprintf("%s:%s", host, port), user: user, privateKeyFile: privateKey, node: node} + sshInst = &SSHConsole{host: fmt.Sprintf("%s:%s", host, port), user: user, + privateKeyFile: privateKey, node: node, exit: make(chan bool, 0)} } else if password != "" { - sshInst = &SSHConsole{host: fmt.Sprintf("%s:%s", host, port), user: user, password: password, node: node} + sshInst = &SSHConsole{host: fmt.Sprintf("%s:%s", host, port), user: user, + password: password, node: node, exit: make(chan bool, 0)} } else { return nil, common.NewErr(common.INVALID_PARAMETER, fmt.Sprintf("%s: Please specify the parameter password or private_key", node)) } @@ -105,8 +109,35 @@ func (s *SSHConsole) appendPasswordAuthMethod(autoMethods *[]ssh.AuthMethod) { } } +func (s *SSHConsole) keepSSHAlive(cl *ssh.Client, conn net.Conn) error { + const keepAliveInterval = time.Minute + t := time.NewTicker(keepAliveInterval) + defer t.Stop() + for { + plog.DebugNode(s.node, "Keep alive goruntine for ssh connection started") + deadline := time.Now().Add(keepAliveInterval).Add(15 * time.Second) + err := conn.SetDeadline(deadline) + if err != nil { + plog.ErrorNode(s.node, "Failed to set deadline for ssh connection") + return common.ErrSetDeadline + } + select { + case <-t.C: + _, _, err = cl.SendRequest("keepalive@golang.org", true, nil) + if err != nil { + plog.ErrorNode(s.node, "Faild to send keepalive request") + return common.ErrSendKeepalive + } + case <-s.exit: + plog.Debug("Exit keepalive goroutine") + return nil + } + } +} + func (s *SSHConsole) connectToHost() error { var err error + timeout := 5 * time.Second autoMethods := make([]ssh.AuthMethod, 0) s.appendPrivateKeyAuthMethod(&autoMethods) s.appendPasswordAuthMethod(&autoMethods) @@ -114,13 +145,18 @@ func (s *SSHConsole) connectToHost() error { User: s.user, Auth: autoMethods, HostKeyCallback: ssh.InsecureIgnoreHostKey(), - Timeout: 5 * time.Second, + Timeout: timeout, } - s.client, err = ssh.Dial("tcp", s.host, sshConfig) + conn, err := net.DialTimeout("tcp", s.host, timeout) if err != nil { return err } - + c, chans, reqs, err := ssh.NewClientConn(conn, s.host, sshConfig) + if err != nil { + return err + } + s.client = ssh.NewClient(c, chans, reqs) + go s.keepSSHAlive(s.client, conn) s.session, err = s.client.NewSession() if err != nil { s.client.Close() @@ -180,6 +216,7 @@ func (s *SSHConsole) Start() (*BaseSession, error) { func (s *SSHConsole) Close() error { if s.client != nil { + s.exit <- true return s.client.Close() } return nil diff --git a/scripts/setup.sh b/scripts/setup.sh index f561315..370b54f 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -5,7 +5,7 @@ set -x BASEPATH=$(cd `dirname $0`; pwd) -cp $BASEPATH/goconserver $BASEPATH/congo /usr/local/bin/ +cp $BASEPATH/goconserver $BASEPATH/congo /usr/bin/ mkdir -p /etc/goconserver /var/log/goconserver/nodes /var/lib/goconserver chmod 700 /etc/goconserver /var/log/goconserver/nodes /var/lib/goconserver