285 lines
6.1 KiB
Go
285 lines
6.1 KiB
Go
|
|
/*
|
||
|
|
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
|
||
|
|
* A-Tune is licensed under the Mulan PSL v1.
|
||
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||
|
|
* You may obtain a copy of Mulan PSL v1 at:
|
||
|
|
* http://license.coscl.org.cn/MulanPSL
|
||
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||
|
|
* PURPOSE.
|
||
|
|
* See the Mulan PSL v1 for more details.
|
||
|
|
* Create: 2019-10-29
|
||
|
|
*/
|
||
|
|
|
||
|
|
package utils
|
||
|
|
|
||
|
|
import (
|
||
|
|
PB "atune/api/profile"
|
||
|
|
"bufio"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"math/rand"
|
||
|
|
"net"
|
||
|
|
"os"
|
||
|
|
"os/exec"
|
||
|
|
"path"
|
||
|
|
"path/filepath"
|
||
|
|
"plugin"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
"syscall"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/urfave/cli"
|
||
|
|
)
|
||
|
|
|
||
|
|
// disk filename
|
||
|
|
const (
|
||
|
|
diskFilename = "diskstats"
|
||
|
|
)
|
||
|
|
|
||
|
|
// the number of args
|
||
|
|
const (
|
||
|
|
ConstExactArgs = iota
|
||
|
|
ConstMinArgs
|
||
|
|
)
|
||
|
|
|
||
|
|
// Status of AckCheck
|
||
|
|
const (
|
||
|
|
SUCCESS = "SUCCESS"
|
||
|
|
FAILD = "FAILED"
|
||
|
|
WARNING = "WARNING"
|
||
|
|
REQUEST = "REQUEST"
|
||
|
|
INFO = "INFO"
|
||
|
|
)
|
||
|
|
|
||
|
|
// CheckArgs method check command args num
|
||
|
|
func CheckArgs(context *cli.Context, expected, checkType int) error {
|
||
|
|
var err error
|
||
|
|
cmdName := context.Command.Name
|
||
|
|
switch checkType {
|
||
|
|
case ConstExactArgs:
|
||
|
|
if context.NArg() != expected {
|
||
|
|
err = fmt.Errorf("%s: %q requires exactly %d argument(s)", os.Args[0], cmdName, expected)
|
||
|
|
}
|
||
|
|
case ConstMinArgs:
|
||
|
|
if context.NArg() < expected {
|
||
|
|
err = fmt.Errorf("%s: %q requires a minimum of %d argument(s)", os.Args[0], cmdName, expected)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
fmt.Printf("Incorrect Usage.\n\n")
|
||
|
|
cli.ShowCommandHelp(context, cmdName)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fatal method exit the application
|
||
|
|
func Fatal(err error) {
|
||
|
|
fmt.Fprintln(os.Stderr, err)
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Random method return a random uint value, the source is the timestamp
|
||
|
|
func Random() uint64 {
|
||
|
|
rand.Seed(time.Now().Unix())
|
||
|
|
return rand.Uint64()
|
||
|
|
}
|
||
|
|
|
||
|
|
// LoadPlugins method load the plugin service
|
||
|
|
func LoadPlugins(path string) error {
|
||
|
|
abs, err := filepath.Abs(path)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
pattern := filepath.Join(abs, fmt.Sprintf("*"))
|
||
|
|
libs, err := filepath.Glob(pattern)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, lib := range libs {
|
||
|
|
if _, err := plugin.Open(lib); err != nil {
|
||
|
|
fmt.Printf("load %s failed : err\n", lib, err)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// PathExist method check path if exist or not
|
||
|
|
func PathExist(path string) (bool, error) {
|
||
|
|
_, err := os.Stat(path)
|
||
|
|
if err == nil {
|
||
|
|
return true, nil
|
||
|
|
}
|
||
|
|
if os.IsNotExist(err) {
|
||
|
|
return false, nil
|
||
|
|
}
|
||
|
|
return false, err
|
||
|
|
}
|
||
|
|
|
||
|
|
// PathIsDir method check path is dir or not
|
||
|
|
func PathIsDir(path string) (bool, error) {
|
||
|
|
info, err := os.Stat(path)
|
||
|
|
if err == nil {
|
||
|
|
return info.IsDir(), nil
|
||
|
|
}
|
||
|
|
if os.IsNotExist(err) {
|
||
|
|
return false, fmt.Errorf("path %s doens't exist", path)
|
||
|
|
}
|
||
|
|
|
||
|
|
return false, err
|
||
|
|
}
|
||
|
|
|
||
|
|
// Print method print AckCheck to stdout
|
||
|
|
func Print(ackCheck *PB.AckCheck) {
|
||
|
|
fc := 32
|
||
|
|
if ackCheck.Status == FAILD {
|
||
|
|
fc = 31
|
||
|
|
} else if ackCheck.Status == WARNING {
|
||
|
|
fc = 33
|
||
|
|
} else if ackCheck.Status == REQUEST {
|
||
|
|
fc = 36
|
||
|
|
} else if ackCheck.Status == INFO {
|
||
|
|
fc = 37
|
||
|
|
}
|
||
|
|
if ackCheck.Description == "" {
|
||
|
|
fmt.Printf("%c[1;40;%dm %s %c[0m\n", 0x1B, fc, ackCheck.GetName(), 0x1B)
|
||
|
|
} else {
|
||
|
|
description := strings.Replace(ackCheck.Description, "\n", ",", -1)
|
||
|
|
fmt.Printf(" [%c[1;40;%dm %-7s] %-40s %-50s %c[0m\n", 0x1B, fc, ackCheck.Status, ackCheck.Name, description, 0x1B)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// PrintStr method print string to stdout
|
||
|
|
func PrintStr(description string) {
|
||
|
|
|
||
|
|
fmt.Printf("%c[1;40;%dm %s %c[0m\n", 0x1B, 32, description, 0x1B)
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsHost method check whether it is a physical machine or a virtual machine
|
||
|
|
func IsHost() bool {
|
||
|
|
cmd := exec.Command("virt-what")
|
||
|
|
_, err := cmd.Output()
|
||
|
|
if err != nil {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateNamedPipe method create a named pip to communicatin
|
||
|
|
func CreateNamedPipe() (string, error) {
|
||
|
|
npipe := strconv.FormatInt(time.Now().Unix(), 10)
|
||
|
|
npipe = path.Join("/tmp", npipe)
|
||
|
|
|
||
|
|
exist, err := PathExist(npipe)
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
if exist {
|
||
|
|
os.Remove(npipe)
|
||
|
|
}
|
||
|
|
|
||
|
|
err = syscall.Mkfifo(npipe, 0666)
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
return npipe, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// CopyFile method copy file from srcName to dstname
|
||
|
|
func CopyFile(dstName string, srcName string) error {
|
||
|
|
src, err := os.Open(srcName)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
defer src.Close()
|
||
|
|
|
||
|
|
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
defer dst.Close()
|
||
|
|
|
||
|
|
if _, err := io.Copy(dst, src); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// RemoveDuplicateElement method remove duplicate elem from slice
|
||
|
|
func RemoveDuplicateElement(message []string) []string {
|
||
|
|
result := make([]string, 0, len(message))
|
||
|
|
messageMap := map[string]struct{}{}
|
||
|
|
for _, item := range message {
|
||
|
|
if _, ok := messageMap[item]; !ok {
|
||
|
|
messageMap[item] = struct{}{}
|
||
|
|
result = append(result, item)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// WaitForPyservice method waiting for pyEngine service start success
|
||
|
|
func WaitForPyservice() error {
|
||
|
|
ticker := time.NewTicker(time.Second * 2)
|
||
|
|
timeout := time.After(time.Second * 120)
|
||
|
|
for {
|
||
|
|
select {
|
||
|
|
case <-ticker.C:
|
||
|
|
_, err := net.Dial("tcp", "localhost:8383")
|
||
|
|
if err != nil {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
case <-timeout:
|
||
|
|
return fmt.Errorf("waiting for pyservice timeout")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// InterfaceByName method check the interface state, up or down
|
||
|
|
// if interface is not exist or down return err, otherwise return nil
|
||
|
|
func InterfaceByName(name string) error {
|
||
|
|
netIntface, err := net.InterfaceByName(name)
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("interface %s is not exist", name)
|
||
|
|
}
|
||
|
|
if netIntface.Flags&net.FlagUp == 0 {
|
||
|
|
return fmt.Errorf("interface %s may be down", name)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// DiskByName method check wether the disk is exist
|
||
|
|
// if disk is exist return nil, otherwise return error
|
||
|
|
func DiskByName(disk string) error {
|
||
|
|
diskFile := path.Join("/proc", diskFilename)
|
||
|
|
file, err := os.Open(diskFile)
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("open file %s error: %v", diskFile, err)
|
||
|
|
}
|
||
|
|
defer file.Close()
|
||
|
|
|
||
|
|
scanner := bufio.NewScanner(file)
|
||
|
|
for scanner.Scan() {
|
||
|
|
parts := strings.Fields(scanner.Text())
|
||
|
|
if len(parts) < 4 {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if parts[2] == disk {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return fmt.Errorf("disk %s is not exist", disk)
|
||
|
|
}
|