more vault
[arvados.git] / services / boot / nomad.go
1 package main
2
3 import (
4         "context"
5         "fmt"
6         "io/ioutil"
7         "os"
8         "path"
9         "sync"
10         "time"
11
12         "github.com/hashicorp/nomad/api"
13 )
14
15 var nomad = &nomadBooter{}
16
17 type nomadBooter struct {
18         sync.Mutex
19 }
20
21 func (nb *nomadBooter) Boot(ctx context.Context) error {
22         nb.Lock()
23         defer nb.Unlock()
24
25         if nb.check(ctx) == nil {
26                 return nil
27         }
28         cfg := cfg(ctx)
29         bin := cfg.UsrDir + "/bin/nomad"
30         err := (&download{
31                 URL:  "https://releases.hashicorp.com/nomad/0.5.4/nomad_0.5.4_linux_amd64.zip",
32                 Dest: bin,
33                 Size: 34150464,
34                 Mode: 0755,
35         }).Boot(ctx)
36         if err != nil {
37                 return err
38         }
39
40         masterToken, err := ioutil.ReadFile(cfg.masterTokenFile())
41         if err != nil {
42                 return err
43         }
44
45         dataDir := path.Join(cfg.DataDir, "nomad")
46         if err := os.MkdirAll(dataDir, 0700); err != nil {
47                 return err
48         }
49
50         cf := path.Join(cfg.DataDir, "nomad.json")
51         err = atomicWriteJSON(cf, map[string]interface{}{
52                 "client": map[string]interface{}{
53                         "enabled": true,
54                         "options": map[string]interface{}{
55                                 "driver.raw_exec.enable": true,
56                         },
57                 },
58                 "consul": map[string]interface{}{
59                         "address": fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP),
60                         "token":   string(masterToken),
61                 },
62                 "data_dir":   dataDir,
63                 "datacenter": cfg.SiteID,
64                 "ports": map[string]int{
65                         "http": cfg.Ports.NomadHTTP,
66                         "rpc":  cfg.Ports.NomadRPC,
67                         "serf": cfg.Ports.NomadSerf,
68                 },
69                 "server": map[string]interface{}{
70                         "enabled":          true,
71                         "bootstrap_expect": len(cfg.ControlHosts),
72                 },
73         }, 0644)
74         if err != nil {
75                 return err
76         }
77
78         supervisor := newSupervisor(ctx, "arvados-nomad", bin, "agent", "-config="+cf)
79         running, err := supervisor.Running(ctx)
80         if err != nil {
81                 return err
82         }
83         if !running {
84                 defer feedbackf(ctx, "starting nomad service")()
85                 err = supervisor.Start(ctx)
86                 if err != nil {
87                         return fmt.Errorf("starting nomad: %s", err)
88                 }
89         }
90         return waitCheck(ctx, 30*time.Second, nb.check)
91 }
92
93 var nomadCfg = api.DefaultConfig()
94
95 func (nb *nomadBooter) check(ctx context.Context) error {
96         cfg := cfg(ctx)
97         nomadCfg.Address = fmt.Sprintf("http://127.0.0.1:%d", cfg.Ports.NomadHTTP)
98         nomad, err := api.NewClient(nomadCfg)
99         if err != nil {
100                 return err
101         }
102         _, err = nomad.Agent().Datacenter()
103         if err != nil {
104                 return err
105         }
106         return nil
107 }