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 }