github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/utils/ssh/utils.go (about) 1 // Copyright © 2022 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ssh 16 17 import ( 18 "bufio" 19 "context" 20 "fmt" 21 "io" 22 "os" 23 "sync" 24 "time" 25 26 "golang.org/x/sync/errgroup" 27 28 "github.com/alibaba/sealer/common" 29 "github.com/alibaba/sealer/logger" 30 v1 "github.com/alibaba/sealer/types/api/v1" 31 v2 "github.com/alibaba/sealer/types/api/v2" 32 "github.com/alibaba/sealer/utils" 33 dockerstreams "github.com/docker/cli/cli/streams" 34 dockerioutils "github.com/docker/docker/pkg/ioutils" 35 dockerjsonmessage "github.com/docker/docker/pkg/jsonmessage" 36 "github.com/docker/docker/pkg/streamformatter" 37 ) 38 39 func displayInit() { 40 reader, writer = io.Pipe() 41 writeFlusher = dockerioutils.NewWriteFlusher(writer) 42 defer func() { 43 _ = reader.Close() 44 _ = writer.Close() 45 _ = writeFlusher.Close() 46 }() 47 progressChanOut = streamformatter.NewJSONProgressOutput(writeFlusher, false) 48 err := dockerjsonmessage.DisplayJSONMessagesToStream(reader, dockerstreams.NewOut(common.StdOut), nil) 49 if err != nil && err != io.ErrClosedPipe { 50 logger.Warn("error occurs in display progressing, err: %s", err) 51 } 52 } 53 54 func localMd5Sum(localPath string) string { 55 md5, err := utils.FileMD5(localPath) 56 if err != nil { 57 logger.Error("get file md5 failed %v", err) 58 return "" 59 } 60 return md5 61 } 62 63 func fileExist(path string) bool { 64 _, err := os.Stat(path) 65 return err == nil || os.IsExist(err) 66 } 67 68 func ReadPipe(stdout, stderr io.Reader, isStdout bool) { 69 var combineSlice []string 70 var combineLock sync.Mutex 71 doneout := make(chan error, 1) 72 doneerr := make(chan error, 1) 73 go func() { 74 doneerr <- readPipe(stderr, &combineSlice, &combineLock, isStdout) 75 }() 76 go func() { 77 doneout <- readPipe(stdout, &combineSlice, &combineLock, isStdout) 78 }() 79 <-doneerr 80 <-doneout 81 } 82 83 func readPipe(pipe io.Reader, combineSlice *[]string, combineLock *sync.Mutex, isStdout bool) error { 84 r := bufio.NewReader(pipe) 85 for { 86 line, _, err := r.ReadLine() 87 if err != nil { 88 return err 89 } 90 91 combineLock.Lock() 92 *combineSlice = append(*combineSlice, string(line)) 93 if isStdout { 94 fmt.Println(string(line)) 95 } 96 combineLock.Unlock() 97 } 98 } 99 100 func GetClusterPlatform(cluster *v2.Cluster) (map[string]v1.Platform, error) { 101 clusterStatus := make(map[string]v1.Platform) 102 for _, ip := range append(cluster.GetMasterIPList(), cluster.GetNodeIPList()...) { 103 IP := ip 104 ssh, err := GetHostSSHClient(IP, cluster) 105 if err != nil { 106 return nil, err 107 } 108 clusterStatus[IP], err = ssh.Platform(IP) 109 if err != nil { 110 return nil, err 111 } 112 } 113 return clusterStatus, nil 114 } 115 116 func WaitSSHReady(ssh Interface, tryTimes int, hosts ...string) error { 117 var err error 118 eg, _ := errgroup.WithContext(context.Background()) 119 for _, h := range hosts { 120 host := h 121 eg.Go(func() error { 122 for i := 0; i < tryTimes; i++ { 123 err = ssh.Ping(host) 124 if err == nil { 125 return nil 126 } 127 time.Sleep(time.Duration(i) * time.Second) 128 } 129 return fmt.Errorf("wait for [%s] ssh ready timeout: %v, ensure that the IP address or password is correct", host, err) 130 }) 131 } 132 return eg.Wait() 133 }