github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/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  	"time"
    12  
    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  	Version    int
    45  	Addr       net.Addr
    46  }
    47  
    48  func (s *serverParts) String() string {
    49  	return fmt.Sprintf("%s (Addr: %s) (DC: %s)",
    50  		s.Name, s.Addr, s.Datacenter)
    51  }
    52  
    53  // Returns if a member is a Nomad server. Returns a boolean,
    54  // and a struct with the various important components
    55  func isNomadServer(m serf.Member) (bool, *serverParts) {
    56  	if m.Tags["role"] != "nomad" {
    57  		return false, nil
    58  	}
    59  
    60  	region := m.Tags["region"]
    61  	datacenter := m.Tags["dc"]
    62  	_, bootstrap := m.Tags["bootstrap"]
    63  
    64  	expect := 0
    65  	expect_str, ok := m.Tags["expect"]
    66  	var err error
    67  	if ok {
    68  		expect, err = strconv.Atoi(expect_str)
    69  		if err != nil {
    70  			return false, nil
    71  		}
    72  	}
    73  
    74  	port_str := m.Tags["port"]
    75  	port, err := strconv.Atoi(port_str)
    76  	if err != nil {
    77  		return false, nil
    78  	}
    79  
    80  	vsn_str := m.Tags["vsn"]
    81  	vsn, err := strconv.Atoi(vsn_str)
    82  	if err != nil {
    83  		return false, nil
    84  	}
    85  
    86  	addr := &net.TCPAddr{IP: m.Addr, Port: port}
    87  	parts := &serverParts{
    88  		Name:       m.Name,
    89  		Region:     region,
    90  		Datacenter: datacenter,
    91  		Port:       port,
    92  		Bootstrap:  bootstrap,
    93  		Expect:     expect,
    94  		Addr:       addr,
    95  		Version:    vsn,
    96  	}
    97  	return true, parts
    98  }
    99  
   100  // Returns a random stagger interval between 0 and the duration
   101  func randomStagger(intv time.Duration) time.Duration {
   102  	return time.Duration(uint64(rand.Int63()) % uint64(intv))
   103  }
   104  
   105  // shuffleStrings randomly shuffles the list of strings
   106  func shuffleStrings(list []string) {
   107  	for i := range list {
   108  		j := rand.Intn(i + 1)
   109  		list[i], list[j] = list[j], list[i]
   110  	}
   111  }
   112  
   113  // maxUint64 returns the maximum value
   114  func maxUint64(a, b uint64) uint64 {
   115  	if a >= b {
   116  		return a
   117  	}
   118  	return b
   119  }
   120  
   121  // rateScaledInterval is used to choose an interval to perform an action in order
   122  // to target an aggregate number of actions per second across the whole cluster.
   123  func rateScaledInterval(rate float64, min time.Duration, n int) time.Duration {
   124  	interval := time.Duration(float64(time.Second) * float64(n) / rate)
   125  	if interval < min {
   126  		return min
   127  	}
   128  	return interval
   129  }