github.com/blixtra/nomad@v0.7.2-0.20171221000451-da9a1d7bb050/nomad/util.go (about)

     1  package nomad
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"net"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strconv"
    11  
    12  	version "github.com/hashicorp/go-version"
    13  	"github.com/hashicorp/serf/serf"
    14  )
    15  
    16  // ensurePath is used to make sure a path exists
    17  func ensurePath(path string, dir bool) error {
    18  	if !dir {
    19  		path = filepath.Dir(path)
    20  	}
    21  	return os.MkdirAll(path, 0755)
    22  }
    23  
    24  // RuntimeStats is used to return various runtime information
    25  func RuntimeStats() map[string]string {
    26  	return map[string]string{
    27  		"kernel.name": runtime.GOOS,
    28  		"arch":        runtime.GOARCH,
    29  		"version":     runtime.Version(),
    30  		"max_procs":   strconv.FormatInt(int64(runtime.GOMAXPROCS(0)), 10),
    31  		"goroutines":  strconv.FormatInt(int64(runtime.NumGoroutine()), 10),
    32  		"cpu_count":   strconv.FormatInt(int64(runtime.NumCPU()), 10),
    33  	}
    34  }
    35  
    36  // serverParts is used to return the parts of a server role
    37  type serverParts struct {
    38  	Name         string
    39  	Region       string
    40  	Datacenter   string
    41  	Port         int
    42  	Bootstrap    bool
    43  	Expect       int
    44  	MajorVersion int
    45  	MinorVersion int
    46  	Build        version.Version
    47  	Addr         net.Addr
    48  	Status       serf.MemberStatus
    49  }
    50  
    51  func (s *serverParts) String() string {
    52  	return fmt.Sprintf("%s (Addr: %s) (DC: %s)",
    53  		s.Name, s.Addr, s.Datacenter)
    54  }
    55  
    56  // Returns if a member is a Nomad server. Returns a boolean,
    57  // and a struct with the various important components
    58  func isNomadServer(m serf.Member) (bool, *serverParts) {
    59  	if m.Tags["role"] != "nomad" {
    60  		return false, nil
    61  	}
    62  
    63  	region := m.Tags["region"]
    64  	datacenter := m.Tags["dc"]
    65  	_, bootstrap := m.Tags["bootstrap"]
    66  
    67  	expect := 0
    68  	expect_str, ok := m.Tags["expect"]
    69  	var err error
    70  	if ok {
    71  		expect, err = strconv.Atoi(expect_str)
    72  		if err != nil {
    73  			return false, nil
    74  		}
    75  	}
    76  
    77  	port_str := m.Tags["port"]
    78  	port, err := strconv.Atoi(port_str)
    79  	if err != nil {
    80  		return false, nil
    81  	}
    82  
    83  	build_version, err := version.NewVersion(m.Tags["build"])
    84  	if err != nil {
    85  		return false, nil
    86  	}
    87  
    88  	// The "vsn" tag was Version, which is now the MajorVersion number.
    89  	majorVersionStr := m.Tags["vsn"]
    90  	majorVersion, err := strconv.Atoi(majorVersionStr)
    91  	if err != nil {
    92  		return false, nil
    93  	}
    94  
    95  	// To keep some semblance of convention, "mvn" is now the "Minor
    96  	// Version Number."
    97  	minorVersionStr := m.Tags["mvn"]
    98  	minorVersion, err := strconv.Atoi(minorVersionStr)
    99  	if err != nil {
   100  		minorVersion = 0
   101  	}
   102  
   103  	addr := &net.TCPAddr{IP: m.Addr, Port: port}
   104  	parts := &serverParts{
   105  		Name:         m.Name,
   106  		Region:       region,
   107  		Datacenter:   datacenter,
   108  		Port:         port,
   109  		Bootstrap:    bootstrap,
   110  		Expect:       expect,
   111  		Addr:         addr,
   112  		MajorVersion: majorVersion,
   113  		MinorVersion: minorVersion,
   114  		Build:        *build_version,
   115  		Status:       m.Status,
   116  	}
   117  	return true, parts
   118  }
   119  
   120  // ServersMeetMinimumVersion returns whether the given alive servers are at least on the
   121  // given Nomad version
   122  func ServersMeetMinimumVersion(members []serf.Member, minVersion *version.Version) bool {
   123  	for _, member := range members {
   124  		if valid, parts := isNomadServer(member); valid && parts.Status == serf.StatusAlive {
   125  			if parts.Build.LessThan(minVersion) {
   126  				return false
   127  			}
   128  		}
   129  	}
   130  
   131  	return true
   132  }
   133  
   134  // shuffleStrings randomly shuffles the list of strings
   135  func shuffleStrings(list []string) {
   136  	for i := range list {
   137  		j := rand.Intn(i + 1)
   138  		list[i], list[j] = list[j], list[i]
   139  	}
   140  }
   141  
   142  // maxUint64 returns the maximum value
   143  func maxUint64(inputs ...uint64) uint64 {
   144  	l := len(inputs)
   145  	if l == 0 {
   146  		return 0
   147  	} else if l == 1 {
   148  		return inputs[0]
   149  	}
   150  
   151  	max := inputs[0]
   152  	for i := 1; i < l; i++ {
   153  		cur := inputs[i]
   154  		if cur > max {
   155  			max = cur
   156  		}
   157  	}
   158  	return max
   159  }