carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5 "github.com/carlosframework/platform/internal/awsinv"
6 "github.com/carlosframework/platform/internal/hostactors"
7 "github.com/carlosframework/platform/internal/hostfence"
8 "github.com/carlosframework/platform/internal/hostfloor"
9 "github.com/carlosframework/platform/internal/release"
10 "log"
11 "os"
12 "strings"
13 "time"
14)
15
16func runHostFencePass(ctx context.Context) {
17 if strings.TrimSpace(os.Getenv("CARLOS_HOST_CLAIM")) == "" || os.Getenv("CARLOS_FLEET") != "" {
18 return
19 }
20 runHostFenceLoop(ctx, 10*time.Minute, hostFenceOnce)
21}
22func runHostFenceLoop(ctx context.Context, interval time.Duration, once func(context.Context) error) {
23 ticker := time.NewTicker(interval)
24 defer ticker.Stop()
25 for {
26 if ctx.Err() != nil {
27 return
28 }
29 pass, cancel := context.WithTimeout(ctx, 2*time.Minute)
30 err := once(pass)
31 cancel()
32 if err != nil {
33 log.Printf("host fence pass: %v", err)
34 }
35 select {
36 case <-ctx.Done():
37 return
38 case <-ticker.C:
39 }
40 }
41}
42func hostFenceOnce(ctx context.Context) error {
43 fences, err := hostfence.OpenRootFenceStore(ctx, os.Getenv("CARLOS_DEPLOYMENT_BUCKET"))
44 if err != nil {
45 return err
46 }
47 store, pub, err := openSystemStore(ctx)
48 if err != nil {
49 return err
50 }
51 enrollment, err := hostfloor.ReadEnrollment("/etc/carlos/host-actor.json")
52 if err != nil {
53 return err
54 }
55 d := hostactors.Directory{Store: store, PublicKey: pub, Bucket: os.Getenv("CARLOS_DEPLOYMENT_BUCKET")}
56 worker := hostfence.TerminationWorker{Fences: fences, Enabled: true, Directory: d, Self: hostfence.Worker{Box: enrollment.Box, Enrollment: enrollment.Enrollment}, Reader: awsinv.NewEC2Reader, Now: time.Now}
57 floor, err := hostfloor.Read(ctx, store, pub, d.Bucket)
58 if err == nil {
59 local, loadErr := floorDisk(release.OptDir())
60 if loadErr != nil {
61 err = loadErr
62 } else {
63 _, armed, e := local.Load()
64 if e != nil {
65 err = e
66 } else if armed.Digest != floor.Digest {
67 err = hostfloor.ErrFloor
68 }
69 }
70 }
71 if err == nil {
72 roster, e := d.Read(ctx)
73 err = e
74 if e == nil {
75 self := roster.Roster.Boxes[enrollment.Box]
76 for ref, box := range roster.Roster.Boxes {
77 if ref == enrollment.Box || box.Region != self.Region || box.State == "retired" {
78 continue
79 }
80 if _, fenceErr := worker.Describe(ctx, ref); fenceErr != nil {
81 log.Printf("host fence %s: awaiting verified termination: %v", ref, fenceErr)
82 }
83 }
84 }
85 }
86 return err
87}
88