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