carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "context"
7 "log"
8 "reflect"
9
10 "github.com/carlosframework/platform/internal/hostbox"
11)
12
13func (p *servingParkRoot) commitServingReboot(ctx context.Context, id string) error {
14 return p.prepareOrCommitServingReboot(ctx, id, true)
15}
16
17// The namespace binding is durable first. An unbound record still carries its
18// old boot and every filesystem effect refuses it, including reused mount IDs.
19// A lost reply at either write is replayed against fresh independent evidence.
20func (l *servingParkLedger) commitRebootLocked(ctx context.Context, saved servingParkRecord, active *servingParkRebootAuthority) error {
21 fresh, err := l.observeRebootPreparation(ctx, saved, active)
22 if err != nil {
23 return err
24 }
25 body, err := l.state.Read(servingNamespacePreparationName(saved.Authorization.ID, fresh.Observation.Topology))
26 if err != nil {
27 return err
28 }
29 var prepared servingParkRebootPreparation
30 if servingParkDecode(body, &prepared) != nil || !reflect.DeepEqual(prepared, fresh) {
31 return hostbox.ErrChanged
32 }
33 t := fresh.Observation.Topology
34 namespace := servingParkBootBinding{Version: 1, ID: "namespace", BeforeBoot: t.Previous.BootID, BootID: t.BootID, BeforeParent: t.Previous.Parent, Parent: t.CurrentParent}
35 if err := ctx.Err(); err != nil {
36 return err
37 }
38 if err := l.write("current-namespace.json", namespace); err != nil {
39 return err
40 }
41 again, err := l.observeRebootPreparation(ctx, saved, active)
42 if err != nil {
43 return err
44 }
45 if !reflect.DeepEqual(fresh, again) {
46 return hostbox.ErrChanged
47 }
48 record := servingParkBootBinding{Version: 1, ID: "retirement-" + saved.Authorization.ID, BeforeBoot: saved.Source.BootID, BootID: t.BootID, BeforeParent: saved.Source.Parent, Parent: t.CurrentParent}
49 if err := ctx.Err(); err != nil {
50 return err
51 }
52 prior, err := servingParkReadBinding(l.state, record.ID)
53 if err != nil {
54 return err
55 }
56 if saved.Source.Volume != "" && saved.Source.Volume == t.Volume && (prior == nil || prior.Volume != "") {
57 record.Volume = t.Volume
58 } else {
59 log.Printf("Host %q: serving database retirement %q retained: %s.", saved.Authorization.Successor.Host, saved.Authorization.ID, hostbox.ErrChanged)
60 }
61 return l.write("current-"+record.ID+".json", record)
62}
63
64func (f *servingParkFS) readNamespace() (servingParkNamespace, error) {
65 var n servingParkNamespace
66 body, err := f.state.Read("namespace.json")
67 if err != nil {
68 return n, err
69 }
70 if servingParkDecode(body, &n) != nil {
71 return n, hostbox.ErrChanged
72 }
73 b, err := servingParkReadBinding(f.state, "namespace")
74 if err != nil || b == nil {
75 return n, err
76 }
77 if n.BootID != b.BeforeBoot || n.Parent != b.BeforeParent {
78 return n, hostbox.ErrChanged
79 }
80 n.BootID = b.BootID
81 if err = b.directory(&n.Parent, false); err != nil {
82 return n, err
83 }
84 err = b.directory(&n.Root, false)
85 return n, err
86}
87