refactor ssh client (#1381)

* perf: ssh client

Signed-off-by: fengxsong <fengxsong@outlook.com>

* fix: use channel to collect all the returned errors

Signed-off-by: fengxsong <fengxsong@outlook.com>
This commit is contained in:
fengxsong
2022-07-22 12:20:57 +08:00
committed by GitHub
parent f24fc62d02
commit e86d168be7
3 changed files with 32 additions and 33 deletions
+9 -12
View File
@@ -37,27 +37,28 @@ func (a HostChecker) Check(cluster *v2.Cluster, phase string) error {
if len(a.IPs) != 0 {
ipList = a.IPs
}
if err := checkHostnameUnique(cluster, ipList); err != nil {
sshClient, err := ssh.NewSSHByCluster(cluster, false)
if err != nil {
return fmt.Errorf("checker: failed to create ssh client, %v", err)
}
if err := checkHostnameUnique(sshClient, ipList); err != nil {
return err
}
return checkTimeSync(cluster, ipList)
return checkTimeSync(sshClient, ipList)
}
func NewHostChecker() Interface {
return &HostChecker{}
}
func NewIPsHostChecker(ips []string) Interface {
return &HostChecker{IPs: ips}
}
func checkHostnameUnique(cluster *v2.Cluster, ipList []string) error {
func checkHostnameUnique(s ssh.Interface, ipList []string) error {
logger.Info("checker:hostname %v", ipList)
hostnameList := map[string]bool{}
for _, ip := range ipList {
s, err := ssh.NewSSHByCluster(cluster, false)
if err != nil {
return fmt.Errorf("checker: failed to get host %s hostname, %v", ip, err)
}
hostname, err := s.CmdToString(ip, "hostname", "")
if err != nil {
return fmt.Errorf("checker: failed to get host %s hostname, %v", ip, err)
@@ -71,13 +72,9 @@ func checkHostnameUnique(cluster *v2.Cluster, ipList []string) error {
}
//Check whether the node time is synchronized
func checkTimeSync(cluster *v2.Cluster, ipList []string) error {
func checkTimeSync(s ssh.Interface, ipList []string) error {
logger.Info("checker:timeSync %v", ipList)
for _, ip := range ipList {
s, err := ssh.NewSSHByCluster(cluster, false)
if err != nil {
return fmt.Errorf("checker: failed to get host %s hostname, %v", ip, err)
}
timeStamp, err := s.CmdToString(ip, "date +%s", "")
if err != nil {
return fmt.Errorf("checker: failed to get %s timestamp, %v", ip, err)
+22 -20
View File
@@ -15,8 +15,10 @@
package ssh
import (
"errors"
"fmt"
"net"
"strings"
"sync"
"time"
@@ -54,7 +56,8 @@ func NewSSHClient(ssh *v2.SSH, isStdout bool) Interface {
if ssh.User == "" {
ssh.User = v2.DefaultUserRoot
}
address, err := iputils.IsLocalHostAddrs()
address, err := iputils.ListLocalHostAddrs()
// todo: return error?
if err != nil {
logger.Warn("failed to get local address, %v", err)
}
@@ -69,29 +72,16 @@ func NewSSHClient(ssh *v2.SSH, isStdout bool) Interface {
}
func NewSSHByCluster(cluster *v2.Cluster, isStdout bool) (Interface, error) {
var (
ipList []string
)
address, err := iputils.IsLocalHostAddrs()
var ipList []string
sshClient := NewSSHClient(&cluster.Spec.SSH, isStdout)
if err != nil {
logger.Warn("failed to get local address, %v", err)
}
ipList = append(ipList, append(cluster.GetIPSByRole(v2.Master), cluster.GetIPSByRole(v2.Node)...)...)
err = WaitSSHReady(sshClient, 6, ipList...)
err := WaitSSHReady(sshClient, 6, ipList...)
if err != nil {
return nil, err
}
return &SSH{
isStdout: isStdout,
User: cluster.Spec.SSH.User,
Password: cluster.Spec.SSH.Passwd,
PkFile: cluster.Spec.SSH.Pk,
PkPassword: cluster.Spec.SSH.PkPasswd,
LocalAddress: address,
}, nil
return sshClient, nil
}
type Client struct {
@@ -100,22 +90,34 @@ type Client struct {
}
func WaitSSHReady(ssh Interface, tryTimes int, hosts ...string) error {
var err error
errCh := make(chan error, len(hosts))
var wg sync.WaitGroup
for _, h := range hosts {
wg.Add(1)
go func(host string) {
defer wg.Done()
var err error
for i := 0; i < tryTimes; i++ {
err = ssh.Ping(host)
if err == nil {
errCh <- nil
return
}
time.Sleep(time.Duration(i) * time.Second)
}
err = fmt.Errorf("wait for [%s] ssh ready timeout: %v, ensure that the IP address or password is correct", host, err)
errCh <- fmt.Errorf("wait for [%s] ssh ready timeout: %v, ensure that the IP address or password is correct", host, err)
}(h)
}
wg.Wait()
return err
close(errCh)
var ret []string
for err := range errCh {
if err != nil {
ret = append(ret, err.Error())
}
}
if len(ret) > 0 {
return errors.New(strings.Join(ret, ","))
}
return nil
}
+1 -1
View File
@@ -94,7 +94,7 @@ func GetHostIPSlice(hosts []string) (res []string) {
return
}
func IsLocalHostAddrs() (*[]net.Addr, error) {
func ListLocalHostAddrs() (*[]net.Addr, error) {
netInterfaces, err := net.Interfaces()
if err != nil {
logger.Warn("net.Interfaces failed, err:", err.Error())