github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/functional/agent/utils.go (about) 1 // Copyright 2018 The etcd Authors 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 agent 16 17 import ( 18 "fmt" 19 "io" 20 "net" 21 "net/url" 22 "os" 23 "os/exec" 24 "path/filepath" 25 "strconv" 26 "time" 27 28 "github.com/lfch/etcd-io/client/pkg/v3/fileutil" 29 30 "go.uber.org/zap" 31 ) 32 33 // TODO: support separate WAL directory 34 func archive(lg *zap.Logger, baseDir, etcdLogPath, dataDir string) error { 35 dir := filepath.Join(baseDir, "etcd-failure-archive", time.Now().Format(time.RFC3339)) 36 if existDir(dir) { 37 dir = filepath.Join(baseDir, "etcd-failure-archive", time.Now().Add(time.Second).Format(time.RFC3339)) 38 } 39 if err := fileutil.TouchDirAll(lg, dir); err != nil { 40 return err 41 } 42 43 dst := filepath.Join(dir, "etcd.log") 44 if err := copyFile(etcdLogPath, dst); err != nil { 45 if !os.IsNotExist(err) { 46 return err 47 } 48 } 49 if err := os.Rename(dataDir, filepath.Join(dir, filepath.Base(dataDir))); err != nil { 50 if !os.IsNotExist(err) { 51 return err 52 } 53 } 54 55 return nil 56 } 57 58 func existDir(fpath string) bool { 59 st, err := os.Stat(fpath) 60 if err != nil { 61 if os.IsNotExist(err) { 62 return false 63 } 64 } else { 65 return st.IsDir() 66 } 67 return false 68 } 69 70 func getURLAndPort(addr string) (urlAddr *url.URL, port int, err error) { 71 urlAddr, err = url.Parse(addr) 72 if err != nil { 73 return nil, -1, err 74 } 75 var s string 76 _, s, err = net.SplitHostPort(urlAddr.Host) 77 if err != nil { 78 return nil, -1, err 79 } 80 port, err = strconv.Atoi(s) 81 if err != nil { 82 return nil, -1, err 83 } 84 return urlAddr, port, err 85 } 86 87 func copyFile(src, dst string) error { 88 f, err := os.Open(src) 89 if err != nil { 90 return err 91 } 92 defer f.Close() 93 94 w, err := os.Create(dst) 95 if err != nil { 96 return err 97 } 98 defer w.Close() 99 100 if _, err = io.Copy(w, f); err != nil { 101 return err 102 } 103 return w.Sync() 104 } 105 106 func safeDataToFile(filePath string, fileData []byte, mode os.FileMode) error { 107 if filePath != "" { 108 if len(fileData) == 0 { 109 return fmt.Errorf("got empty data for %q", filePath) 110 } 111 if err := os.WriteFile(filePath, fileData, mode); err != nil { 112 return fmt.Errorf("writing file %q failed, %w", filePath, err) 113 } 114 } 115 return nil 116 } 117 118 func loadFileData(filePath string) ([]byte, error) { 119 if !fileutil.Exist(filePath) { 120 return nil, fmt.Errorf("cannot find %q", filePath) 121 } 122 data, err := os.ReadFile(filePath) 123 if err != nil { 124 return nil, fmt.Errorf("read file %q failed, %w", filePath, err) 125 } 126 return data, nil 127 } 128 129 func checkTCPConnect(lg *zap.Logger, target string) error { 130 for i := 0; i < 10; i++ { 131 if conn, err := net.Dial("tcp", target); err != nil { 132 lg.Error("The target isn't reachable", zap.Int("retries", i), zap.String("target", target), zap.Error(err)) 133 } else { 134 if conn != nil { 135 conn.Close() 136 lg.Info("The target is reachable", zap.Int("retries", i), zap.String("target", target)) 137 return nil 138 } 139 lg.Error("The target isn't reachable due to the returned conn is nil", zap.Int("retries", i), zap.String("target", target)) 140 } 141 time.Sleep(time.Second) 142 } 143 return fmt.Errorf("timed out waiting for the target (%s) to be reachable", target) 144 } 145 146 func cleanPageCache() error { 147 // https://www.kernel.org/doc/Documentation/sysctl/vm.txt 148 // https://github.com/torvalds/linux/blob/master/fs/drop_caches.c 149 cmd := exec.Command("/bin/sh", "-c", `echo "echo 1 > /proc/sys/vm/drop_caches" | sudo -s -n`) 150 return cmd.Run() 151 }