github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/nomad/util.go (about) 1 package nomad 2 3 import ( 4 "fmt" 5 "math" 6 "math/big" 7 "math/rand" 8 "net" 9 "os" 10 "path/filepath" 11 "runtime" 12 "strconv" 13 "time" 14 15 crand "crypto/rand" 16 17 "github.com/hashicorp/serf/serf" 18 ) 19 20 // ensurePath is used to make sure a path exists 21 func ensurePath(path string, dir bool) error { 22 if !dir { 23 path = filepath.Dir(path) 24 } 25 return os.MkdirAll(path, 0755) 26 } 27 28 // RuntimeStats is used to return various runtime information 29 func RuntimeStats() map[string]string { 30 return map[string]string{ 31 "kernel.name": runtime.GOOS, 32 "arch": runtime.GOARCH, 33 "version": runtime.Version(), 34 "max_procs": strconv.FormatInt(int64(runtime.GOMAXPROCS(0)), 10), 35 "goroutines": strconv.FormatInt(int64(runtime.NumGoroutine()), 10), 36 "cpu_count": strconv.FormatInt(int64(runtime.NumCPU()), 10), 37 } 38 } 39 40 // serverParts is used to return the parts of a server role 41 type serverParts struct { 42 Name string 43 Region string 44 Datacenter string 45 Port int 46 Bootstrap bool 47 Expect int 48 Version int 49 Addr net.Addr 50 } 51 52 func (s *serverParts) String() string { 53 return fmt.Sprintf("%s (Addr: %s) (DC: %s)", 54 s.Name, s.Addr, s.Datacenter) 55 } 56 57 // Returns if a member is a Nomad server. Returns a boolean, 58 // and a struct with the various important components 59 func isNomadServer(m serf.Member) (bool, *serverParts) { 60 if m.Tags["role"] != "nomad" { 61 return false, nil 62 } 63 64 region := m.Tags["region"] 65 datacenter := m.Tags["dc"] 66 _, bootstrap := m.Tags["bootstrap"] 67 68 expect := 0 69 expect_str, ok := m.Tags["expect"] 70 var err error 71 if ok { 72 expect, err = strconv.Atoi(expect_str) 73 if err != nil { 74 return false, nil 75 } 76 } 77 78 port_str := m.Tags["port"] 79 port, err := strconv.Atoi(port_str) 80 if err != nil { 81 return false, nil 82 } 83 84 vsn_str := m.Tags["vsn"] 85 vsn, err := strconv.Atoi(vsn_str) 86 if err != nil { 87 return false, nil 88 } 89 90 addr := &net.TCPAddr{IP: m.Addr, Port: port} 91 parts := &serverParts{ 92 Name: m.Name, 93 Region: region, 94 Datacenter: datacenter, 95 Port: port, 96 Bootstrap: bootstrap, 97 Expect: expect, 98 Addr: addr, 99 Version: vsn, 100 } 101 return true, parts 102 } 103 104 // Returns a random stagger interval between 0 and the duration 105 func randomStagger(intv time.Duration) time.Duration { 106 return time.Duration(uint64(rand.Int63()) % uint64(intv)) 107 } 108 109 // shuffleStrings randomly shuffles the list of strings 110 func shuffleStrings(list []string) { 111 for i := range list { 112 j := rand.Intn(i + 1) 113 list[i], list[j] = list[j], list[i] 114 } 115 } 116 117 // maxUint64 returns the maximum value 118 func maxUint64(a, b uint64) uint64 { 119 if a >= b { 120 return a 121 } 122 return b 123 } 124 125 // rateScaledInterval is used to choose an interval to perform an action in order 126 // to target an aggregate number of actions per second across the whole cluster. 127 func rateScaledInterval(rate float64, min time.Duration, n int) time.Duration { 128 interval := time.Duration(float64(time.Second) * float64(n) / rate) 129 if interval < min { 130 return min 131 } 132 return interval 133 } 134 135 // seedRandom seeds the global random variable using a cryptographically random 136 // seed. It returns an error if determing the random seed fails. 137 func seedRandom() error { 138 n, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) 139 if err != nil { 140 return err 141 } 142 rand.Seed(n.Int64()) 143 return nil 144 }