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  }