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  }