Merge ~cgrabowski/maas:rpc_client_server into maas:rack_region_exploration

Proposed by Christian Grabowski
Status: Merged
Approved by: Christian Grabowski
Approved revision: e4105e0c6bf7c8b11fa71629d67385c20b5a2cad
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:rpc_client_server
Merge into: maas:rack_region_exploration
Diff against target: 3110 lines (+2887/-3)
21 files modified
src/rackd_spike/Makefile (+21/-1)
src/rackd_spike/cmd/rackd.go (+21/-0)
src/rackd_spike/go.mod (+4/-0)
src/rackd_spike/go.sum (+15/-2)
src/rackd_spike/internal/machine_helpers/env.go (+67/-0)
src/rackd_spike/internal/machine_helpers/info.go (+24/-0)
src/rackd_spike/internal/machine_helpers/interfaces.go (+498/-0)
src/rackd_spike/internal/machine_helpers/interfaces_capnp.go (+65/-0)
src/rackd_spike/internal/machine_helpers/interfaces_test.go (+81/-0)
src/rackd_spike/internal/machine_helpers/ps.go (+81/-0)
src/rackd_spike/internal/machine_helpers/refresh.go (+29/-0)
src/rackd_spike/internal/machine_helpers/snap.go (+30/-0)
src/rackd_spike/internal/transport/rpc.go (+127/-0)
src/rackd_spike/pkg/authenticate/authenticator.go (+93/-0)
src/rackd_spike/pkg/region/handshake.go (+91/-0)
src/rackd_spike/pkg/register/registerer.go (+125/-0)
src/rackd_spike/pkg/rpc/handshake.capnp.go (+933/-0)
src/rackd_spike/pkg/rpc/network.capnp.go (+489/-0)
src/rpc/go.capnp (+27/-0)
src/rpc/handshake.capnp (+36/-0)
src/rpc/network.capnp (+30/-0)
Reviewer Review Type Date Requested Status
Alexsander de Souza Approve
MAAS Lander Approve
Review via email: mp+405247@code.launchpad.net

Commit message

add rpc handshake

add machine helper functions

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: b8a28beb8353fa66ac5a4d5130940e457ccd5ed9

review: Approve
Revision history for this message
Alexsander de Souza (alexsander-souza) :
Revision history for this message
Christian Grabowski (cgrabowski) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 55db9bddb0a716d1a24be429bdd4750027740736

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/10399/console
COMMIT: 6b7bb3239a1fa1687c37b5a93587fddb06a009a9

review: Needs Fixing
Revision history for this message
Alexsander de Souza (alexsander-souza) :
Revision history for this message
Christian Grabowski (cgrabowski) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: efa4abdd774328b4e09c27e4404f5981eeff08cf

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: bd874202dee2eeed333cc3c647b3b8c4873608c2

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/10417/console
COMMIT: a350ebb73dc98f908746aa767362b4525ad8b712

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: e4105e0c6bf7c8b11fa71629d67385c20b5a2cad

review: Approve
Revision history for this message
Alexsander de Souza (alexsander-souza) wrote :

LGTM

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

LANDING
-b rpc_client_server lp:~cgrabowski/maas/+git/maas into -b rack_region_exploration lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/10425/consoleText

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/rackd_spike/Makefile b/src/rackd_spike/Makefile
2index 81278c8..df50bdd 100644
3--- a/src/rackd_spike/Makefile
4+++ b/src/rackd_spike/Makefile
5@@ -1,3 +1,6 @@
6+PWD:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
7+ROOT_DIR:=$(shell dirname $(PWD))
8+RPC_DIR:=$(PWD)/pkg/rpc
9 VERSION:=develop-$(shell git rev-list -1 HEAD)
10
11 PATH:=$(shell go env GOPATH)/bin:${PATH}
12@@ -5,24 +8,41 @@ export PATH
13
14 LDFLAGS="-X main.Version=$(VERSION) -s -w"
15
16+.PHONY: all
17 all: version test build
18
19 version:
20 @go version
21
22+.PHONY: build
23 build: rackd
24
25+.PHONY: build-dir
26 build-dir:
27 mkdir -p ./build
28
29-rackd: build-dir
30+.PHONY: rackd
31+rackd: build-dir gen-capnp
32 go build -ldflags $(LDFLAGS) -o ./build/rackd ./cmd/rackd.go
33
34+.PHONY: test
35 test:
36 go test ./...
37
38+.PHONY: lint
39 lint:
40 go vet ./...
41
42+.PHONY: format
43 format:
44 gofmt -s -d ./cmd ./internal ./pkg
45+
46+.PHONY: capnp-dir
47+capnp-dir:
48+ mkdir -p ./pkg/rpc
49+
50+%.capnp: capnp-dir
51+ capnp compile -ogo:$(PWD)/pkg/rpc $(ROOT_DIR)/rpc/$@ --src-prefix $(ROOT_DIR)/rpc
52+
53+.PHONY: gen-capnp
54+gen-capnp: handshake.capnp network.capnp
55diff --git a/src/rackd_spike/cmd/rackd.go b/src/rackd_spike/cmd/rackd.go
56index fd7dac5..8ca5188 100644
57--- a/src/rackd_spike/cmd/rackd.go
58+++ b/src/rackd_spike/cmd/rackd.go
59@@ -14,6 +14,10 @@ import (
60 "rackd/cmd/subcommands"
61 "rackd/internal/config"
62 "rackd/internal/metrics"
63+ "rackd/internal/transport"
64+ "rackd/pkg/authenticate"
65+ "rackd/pkg/region"
66+ "rackd/pkg/register"
67 )
68
69 type opts struct {
70@@ -76,6 +80,23 @@ var (
71 }
72 defer metricsSrvr.Close()
73
74+ initRegion := os.Getenv("REGION_URL")
75+ rpcMgr := transport.NewRPCManager(initRegion, true) // TODO use the register command to provide info to connect instead and make TLS skip verify configurable
76+ err = rpcMgr.Init(ctx)
77+ if err != nil {
78+ return err
79+ }
80+ rpcMgr.AddClient(ctx, authenticate.NewCapnpAuthenticator())
81+ rpcMgr.AddClient(ctx, register.NewCapnpRegisterer())
82+ err = rpcMgr.Init(ctx)
83+ if err != nil {
84+ return err
85+ }
86+ err = region.Handshake(ctx, initRegion, Version, rpcMgr)
87+ if err != nil {
88+ return err
89+ }
90+
91 log.Info().Msgf("rackd %v started successfully", Version)
92
93 sigChan := make(chan os.Signal, 4)
94diff --git a/src/rackd_spike/go.mod b/src/rackd_spike/go.mod
95index 3339fb7..73edbc6 100644
96--- a/src/rackd_spike/go.mod
97+++ b/src/rackd_spike/go.mod
98@@ -3,11 +3,15 @@ module rackd
99 go 1.16
100
101 require (
102+ capnproto.org/go/capnp/v3 v3.0.0-alpha.1
103 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
104 github.com/coreos/go-systemd/v22 v22.3.2
105 github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b
106+ github.com/lxc/lxd v0.0.0-20210705204343-3596a3bcba59
107+ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
108 github.com/prometheus/client_golang v0.9.3
109 github.com/rs/zerolog v1.23.0
110 github.com/spf13/cobra v1.1.3
111+ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
112 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
113 )
114diff --git a/src/rackd_spike/go.sum b/src/rackd_spike/go.sum
115index 4c08b8b..b61ac4f 100644
116--- a/src/rackd_spike/go.sum
117+++ b/src/rackd_spike/go.sum
118@@ -1,3 +1,5 @@
119+capnproto.org/go/capnp/v3 v3.0.0-alpha.1 h1:lA/zWC1XgaFez/UdqcWi5Bz1grsqPQDY5Ki4lgYrQ1o=
120+capnproto.org/go/capnp/v3 v3.0.0-alpha.1/go.mod h1:izbWjXlvObqHwvhxwDBFLpY9lXSXIxDKRtnuktKHVsU=
121 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
122 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
123 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
124@@ -110,11 +112,13 @@ github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b h1:iNjcivnc6lhbvJA3LD6
125 github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
126 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
127 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
128-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
129 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
130 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
131 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
132 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
133+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
134+github.com/lxc/lxd v0.0.0-20210705204343-3596a3bcba59 h1:FvuAx1MSuzz2gC5fqGG1tL99SNm1JacG3kDWqL3vILo=
135+github.com/lxc/lxd v0.0.0-20210705204343-3596a3bcba59/go.mod h1:2BaZflfwsv8a3uy3/Vw+de4Avn4DSrAiqaHJjCIXMV4=
136 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
137 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
138 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
139@@ -132,9 +136,13 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
140 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
141 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
142 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
143+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
144+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
145 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
146 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
147 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
148+github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
149+github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
150 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
151 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
152 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
153@@ -181,7 +189,10 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
154 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
155 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
156 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
157+github.com/tinylib/msgp v1.1.5 h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0=
158+github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
159 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
160+github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
161 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
162 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
163 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
164@@ -280,6 +291,7 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
165 golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
166 golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
167 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
168+golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
169 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
170 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
171 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
172@@ -307,8 +319,9 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq
173 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
174 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
175 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
176-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
177 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
178+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
179+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
180 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
181 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
182 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
183diff --git a/src/rackd_spike/internal/machine_helpers/env.go b/src/rackd_spike/internal/machine_helpers/env.go
184new file mode 100644
185index 0000000..351d53c
186--- /dev/null
187+++ b/src/rackd_spike/internal/machine_helpers/env.go
188@@ -0,0 +1,67 @@
189+package machinehelpers
190+
191+import (
192+ "fmt"
193+ "io"
194+ "os"
195+ "path/filepath"
196+ "strings"
197+ "sync"
198+)
199+
200+var (
201+ maasId string
202+)
203+
204+var (
205+ maasIdLock = &sync.RWMutex{}
206+)
207+
208+func GetMAASDataPath(path string) string {
209+ basePath, ok := os.LookupEnv(path)
210+ if !ok {
211+ basePath = "/var/lib/maas"
212+ }
213+ return filepath.Join(basePath, path)
214+}
215+
216+func GetMAASID() (string, error) {
217+ maasIdLock.RLock()
218+ defer maasIdLock.RUnlock()
219+
220+ if len(maasId) == 0 {
221+ path := GetMAASDataPath("maas_id")
222+ f, err := os.Open(path)
223+ if err != nil {
224+ if os.IsNotExist(err) {
225+ return "", nil
226+ }
227+ return "", err
228+ }
229+ contents, err := io.ReadAll(f)
230+ if err != nil {
231+ return "", err
232+ }
233+ maasIdLock.Lock()
234+ defer maasIdLock.Unlock()
235+ maasId = strings.TrimSpace(string(contents))
236+ }
237+ return maasId, nil
238+}
239+
240+func SetMAASId(id string) error {
241+ path := GetMAASDataPath("maas_id")
242+ maasIdLock.Lock()
243+ defer maasIdLock.Unlock()
244+ maasId = id
245+ f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644)
246+ if err != nil {
247+ return err
248+ }
249+ defer f.Close()
250+ _, err = fmt.Fprint(f, id)
251+ if err != nil {
252+ return err
253+ }
254+ return nil
255+}
256diff --git a/src/rackd_spike/internal/machine_helpers/info.go b/src/rackd_spike/internal/machine_helpers/info.go
257new file mode 100644
258index 0000000..1517fc6
259--- /dev/null
260+++ b/src/rackd_spike/internal/machine_helpers/info.go
261@@ -0,0 +1,24 @@
262+package machinehelpers
263+
264+import (
265+ lxdresources "github.com/lxc/lxd/shared/api"
266+)
267+
268+type EnvInfo struct {
269+ Kernel string `json:"kernel"`
270+ KernelArchitecture string `json:"kernel_architecture"`
271+ KernelVersion string `json:"kernel_version"`
272+ OSName string `json:"os_name"`
273+ OSVersion string `json:"os_version"`
274+ Server string `json:"server"`
275+ ServerName string `json:"server_name"`
276+ ServerVersion string `json:"server_version"`
277+}
278+
279+type MachineInfo struct {
280+ APIExtensions []string `json:"api_extension"`
281+ APIVersion string `json:"api_version"`
282+ Environment EnvInfo `json:"environment"`
283+ Resources lxdresources.Resources `json:"resources"`
284+ Networks map[string]lxdresources.NetworkState `json:"networks"`
285+}
286diff --git a/src/rackd_spike/internal/machine_helpers/interfaces.go b/src/rackd_spike/internal/machine_helpers/interfaces.go
287new file mode 100644
288index 0000000..cbf58e6
289--- /dev/null
290+++ b/src/rackd_spike/internal/machine_helpers/interfaces.go
291@@ -0,0 +1,498 @@
292+package machinehelpers
293+
294+import (
295+ "bufio"
296+ "context"
297+ "encoding/json"
298+ "fmt"
299+ "io"
300+ "net"
301+ "os"
302+ "os/exec"
303+ "path/filepath"
304+ "regexp"
305+ "sort"
306+ "strconv"
307+ "strings"
308+
309+ lxdresources "github.com/lxc/lxd/shared/api"
310+)
311+
312+var (
313+ excludedInterfaceTypes = map[string]struct{}{
314+ "loopback": {},
315+ "ipip": {},
316+ "tunnel": {},
317+ }
318+
319+ leaseRx = regexp.MustCompile(`(?m)(^\s*lease\s+{([^}]+)})`)
320+)
321+
322+func isExcludedType(ctx context.Context, t string) (bool, error) {
323+ if _, ok := excludedInterfaceTypes[t]; ok {
324+ return true, nil
325+ }
326+ runningContainer, err := RunningInContainer(ctx)
327+ if err != nil {
328+ return false, err
329+ }
330+ if runningContainer && t == "ethernet" {
331+ return true, nil
332+ }
333+ if strings.HasPrefix("unknown-", t) {
334+ return true, nil
335+ }
336+ return false, nil
337+}
338+
339+func GetIPAddr(ctx context.Context) (map[string]lxdresources.NetworkState, error) {
340+ cmdPath, err := GetResourcesBinPath()
341+ if err != nil {
342+ return nil, err
343+ }
344+ var args []string
345+ if IsRunningInSnap() {
346+ args = append(args, cmdPath)
347+ cmdPath = "/usr/bin/sudo"
348+ }
349+ cmd := exec.CommandContext(ctx, cmdPath, args...)
350+ out, err := cmd.Output()
351+ if err != nil {
352+ return nil, err
353+ }
354+ var info MachineInfo
355+ err = json.Unmarshal(out, &info)
356+ if err != nil {
357+ return nil, err
358+ }
359+ return info.Networks, nil
360+}
361+
362+func splitDhclientCmdlineFile(data []byte, atEOF bool) (advance int, token []byte, err error) {
363+ for i := 0; i < len(data); i++ {
364+ if data[i] == '\x00' {
365+ return i + 1, data[:i], nil
366+ }
367+ if !atEOF {
368+ return 0, nil, nil
369+ }
370+ }
371+ return 0, data, bufio.ErrFinalToken
372+}
373+
374+func GetLatestFixedAddress(leasePath string) (string, error) {
375+ f, err := os.Open(leasePath)
376+ if err != nil {
377+ return "", err
378+ }
379+ defer f.Close()
380+ return getLatestFixedAddress(f)
381+}
382+
383+func getLatestFixedAddress(leaseFile io.Reader) (string, error) {
384+ leaseBytes, err := io.ReadAll(leaseFile)
385+ if err != nil {
386+ return "", err
387+ }
388+ submatches := leaseRx.FindAllSubmatch(leaseBytes, -1)
389+ if len(submatches) > 0 {
390+ matches := submatches[len(submatches)-1]
391+ if len(matches) > 0 {
392+ lastLease := matches[len(matches)-1]
393+ for _, line := range strings.Split(string(lastLease), "\n") {
394+ line = strings.TrimSpace(line)
395+ if len(line) > 0 {
396+ lineList := strings.SplitN(line, " ", 2)
397+ if len(lineList) < 2 {
398+ continue
399+ }
400+ statement, value := lineList[0], lineList[1]
401+ if statement == "fixed-address" || statement == "fixed-address6" {
402+ return strings.TrimSpace(strings.SplitN(value, ";", 2)[0]), nil
403+ }
404+ }
405+ }
406+ }
407+ }
408+ return "", nil
409+}
410+
411+func GetDhclientInfo(ctx context.Context, procPath string) (map[string]string, error) {
412+ if len(procPath) == 0 {
413+ procPath = "/proc"
414+ }
415+ pids, err := GetRunningPIDsWithCMD(ctx, "dhclient", "", false)
416+ if err != nil {
417+ return nil, err
418+ }
419+ info := make(map[string]string)
420+ for _, pid := range pids {
421+ cmdlinePath := filepath.Join(procPath, strconv.Itoa(pid), "cmdline")
422+ err = func() error {
423+ f, err := os.Open(cmdlinePath)
424+ if err != nil {
425+ return err
426+ }
427+ defer f.Close()
428+ scanner := bufio.NewScanner(f)
429+ scanner.Split(splitDhclientCmdlineFile)
430+ var (
431+ cmd []string
432+ leasePath string
433+ )
434+ lfIdx := -1
435+ for scanner.Scan() {
436+ cmd = append(cmd, scanner.Text())
437+ if cmd[len(cmd)-1] == "-lf" {
438+ lfIdx = len(cmd) - 1
439+ }
440+ if lfIdx > -1 && len(cmd)-2 == lfIdx {
441+ leasePath = cmd[len(cmd)-1]
442+ }
443+ }
444+ ifaceName := cmd[len(cmd)-1]
445+ ipAddr, err := GetLatestFixedAddress(leasePath)
446+ if err != nil {
447+ return err
448+ }
449+ if len(ipAddr) > 0 && ipAddr != " " {
450+ info[ifaceName] = ipAddr
451+ }
452+ return nil
453+ }()
454+ if err != nil {
455+ return nil, err
456+ }
457+ }
458+ return info, nil
459+}
460+
461+type IPLink struct {
462+ Netmask int
463+ Mode string
464+ Address string
465+ Gateway string
466+}
467+
468+type Vlan struct {
469+ LowerDev string
470+ Vid uint64
471+}
472+
473+type Interface struct {
474+ Type string
475+ Mac string
476+ Links []IPLink
477+ Enabled bool
478+ Vlan *Vlan
479+ Source string
480+ Parents []string
481+ Monitored bool
482+}
483+
484+type sortableSubnets []*net.IPNet
485+
486+func (s sortableSubnets) Len() int {
487+ return len(s)
488+}
489+
490+func (s sortableSubnets) Less(i, j int) bool {
491+ iPrefixlen, _ := s[i].Mask.Size()
492+ jPrefixlen, _ := s[j].Mask.Size()
493+ return iPrefixlen < jPrefixlen
494+}
495+
496+func (s sortableSubnets) Swap(i, j int) {
497+ tmp := s[j]
498+ s[j] = s[i]
499+ s[i] = tmp
500+}
501+
502+func fixLinkAddresses(links []IPLink) ([]IPLink, error) {
503+ var (
504+ subnetsV4 []*net.IPNet
505+ linksV4 []struct {
506+ Link IPLink
507+ Idx int
508+ }
509+ subnetsV6 []*net.IPNet
510+ linksV6 []struct {
511+ Link IPLink
512+ Idx int
513+ }
514+ )
515+ for i, link := range links {
516+ var (
517+ ipAddr net.IP
518+ ipNet *net.IPNet
519+ err error
520+ )
521+ if link.Netmask != 0 {
522+ ipAddr, ipNet, err = net.ParseCIDR(fmt.Sprintf("%s/%d", link.Address, link.Netmask))
523+ if err != nil {
524+ return nil, err
525+ }
526+ } else {
527+ ipAddr, ipNet, err = net.ParseCIDR(link.Address)
528+ if err != nil {
529+ return nil, err
530+ }
531+ }
532+ prefixLen, _ := ipNet.Mask.Size()
533+ if ipAddr.To4() != nil {
534+ if prefixLen == 32 {
535+ linksV4 = append(linksV4, struct {
536+ Link IPLink
537+ Idx int
538+ }{
539+ Link: link,
540+ Idx: i,
541+ })
542+ } else {
543+ subnetsV4 = append(subnetsV4, ipNet)
544+ }
545+ } else {
546+ if prefixLen == 128 {
547+ linksV6 = append(linksV6, struct {
548+ Link IPLink
549+ Idx int
550+ }{
551+ Link: link,
552+ Idx: i,
553+ })
554+ } else {
555+ subnetsV6 = append(subnetsV6, ipNet)
556+ }
557+ }
558+ }
559+ newLinks := [][]struct {
560+ Link IPLink
561+ Idx int
562+ }{linksV4, linksV6}
563+ newSubnets := [][]*net.IPNet{subnetsV4, subnetsV6}
564+ for i, currLinks := range newLinks {
565+ currSubnets := sortableSubnets(newSubnets[i])
566+ var ok bool
567+ currSubnets, ok = sort.Reverse(currSubnets).(sortableSubnets)
568+ if !ok {
569+ return nil, fmt.Errorf("sort.Reverse() returned a type other than sortableSubnets, %T", currSubnets)
570+ }
571+ for _, link := range currLinks {
572+ var (
573+ ip net.IP
574+ err error
575+ )
576+ if link.Link.Netmask != 0 {
577+ ip, _, err = net.ParseCIDR(
578+ fmt.Sprintf("%s:%d", link.Link.Address, link.Link.Netmask),
579+ )
580+ } else {
581+ ip, _, err = net.ParseCIDR(link.Link.Address)
582+ }
583+ if err != nil {
584+ return nil, err
585+ }
586+ for _, subnet := range currSubnets {
587+ if subnet.Contains(ip) {
588+ prefixlen, _ := subnet.Mask.Size()
589+ if link.Link.Netmask != 0 {
590+ link.Link.Netmask = prefixlen
591+ } else {
592+ link.Link.Address = fmt.Sprintf("%s/%d", ip, prefixlen)
593+ }
594+ }
595+ }
596+ links[link.Idx] = link.Link
597+ }
598+ }
599+ return links, nil
600+}
601+
602+type IPRoute struct {
603+ Gateway string `json:"gateway"`
604+ GatewayIP net.IP `json:"-"`
605+ Dev string `json:"dev"`
606+ Protocol string `json:"protocol"`
607+ Metric int `json:"metric"`
608+ Flags []int `json:"flags"`
609+}
610+
611+func GetIPRoute(ctx context.Context) (map[string]IPRoute, error) {
612+ cmd := exec.CommandContext(ctx, "ip", "-json", "route", "list", "scope", "global")
613+ routes := make(map[string]IPRoute)
614+ var routeList []struct {
615+ Name string `json:"dst"`
616+ IPRoute
617+ }
618+ out, err := cmd.Output()
619+ if err != nil {
620+ return nil, err
621+ }
622+ err = json.Unmarshal(out, &routeList)
623+ if err != nil {
624+ return nil, err
625+ }
626+ for _, route := range routeList {
627+ route.IPRoute.GatewayIP = net.ParseIP(route.Gateway)
628+ routes[route.Name] = route.IPRoute
629+ }
630+ return routes, nil
631+}
632+
633+func fixGateways(links []IPLink, ipRouteInfo map[string]IPRoute) ([]IPLink, error) {
634+ for i, link := range links {
635+ _, subnet, err := net.ParseCIDR(link.Address)
636+ if err != nil {
637+ return nil, err
638+ }
639+ if routeInfo, ok := ipRouteInfo[subnet.String()]; ok {
640+ link.Gateway = routeInfo.Gateway
641+ } else if defaultInfo, ok := ipRouteInfo["default"]; ok && subnet.Contains(defaultInfo.GatewayIP) {
642+ link.Gateway = defaultInfo.Gateway
643+ }
644+ links[i] = link
645+ }
646+ return links, nil
647+}
648+
649+func GetInterfaceChildren(interfaces map[string]Interface) map[string][]string {
650+ children := make(map[string][]string)
651+ for name, iface := range interfaces {
652+ for _, parent := range iface.Parents {
653+ if node, ok := children[parent]; ok {
654+ node = append(node, name)
655+ } else {
656+ children[parent] = []string{name}
657+ }
658+ }
659+ }
660+ return children
661+}
662+
663+type InterfaceChild struct {
664+ Name string
665+ Iface Interface
666+}
667+
668+func InterfaceChildren(ifname string, interfaces map[string]Interface, children map[string][]string) (res []InterfaceChild) {
669+ if node, ok := children[ifname]; ok {
670+ for _, child := range node {
671+ res = append(res, InterfaceChild{Name: child, Iface: interfaces[child]})
672+ }
673+ }
674+ return res
675+}
676+
677+func GetDefaultMonitoredInterfaces(interfaces map[string]Interface) (res map[string]struct{}) {
678+ res = make(map[string]struct{})
679+ childrenMap := GetInterfaceChildren(interfaces)
680+ for name, iface := range interfaces {
681+ if !iface.Enabled {
682+ continue
683+ }
684+ switch iface.Type {
685+ case "physical":
686+ shouldMonitor := true
687+ for _, child := range InterfaceChildren(name, interfaces, childrenMap) {
688+ if child.Iface.Type == "bond" {
689+ shouldMonitor = false
690+ break
691+ }
692+ }
693+ if shouldMonitor {
694+ res[name] = struct{}{}
695+ }
696+ case "bond":
697+ res[name] = struct{}{}
698+ case "bridge":
699+ if len(iface.Parents) == 0 {
700+ res[name] = struct{}{}
701+ }
702+ }
703+ }
704+ return res
705+}
706+
707+func GetAllInterfacesDefinition(ctx context.Context, annotateWithMonitored bool) (map[string]Interface, error) {
708+ dhclientInfo, err := GetDhclientInfo(ctx, "")
709+ if err != nil {
710+ return nil, err
711+ }
712+ netIfaces, err := GetIPAddr(ctx)
713+ if err != nil {
714+ return nil, err
715+ }
716+ iprouteInfo, err := GetIPRoute(ctx)
717+ if err != nil {
718+ return nil, err
719+ }
720+ res := make(map[string]Interface)
721+ for name, iface := range netIfaces {
722+ excludeType, err := isExcludedType(ctx, iface.Type)
723+ if err != nil {
724+ return nil, err
725+ }
726+ if excludeType {
727+ continue
728+ }
729+ i := Interface{
730+ Mac: iface.Hwaddr,
731+ Enabled: iface.State == "up",
732+ }
733+ if !(iface.Type == "vlan" || iface.Type == "bridge" || iface.Type == "bond") {
734+ i.Type = "physical"
735+ } else {
736+ i.Type = iface.Type
737+ if iface.Bond != nil && len(iface.Bond.LowerDevices) > 0 {
738+ i.Parents = append(i.Parents, iface.Bond.LowerDevices...)
739+ }
740+ if iface.Bridge != nil && len(iface.Bridge.UpperDevices) > 0 {
741+ i.Parents = append(i.Parents, iface.Bridge.UpperDevices...)
742+ }
743+ }
744+ if iface.VLAN != nil {
745+ i.Vlan = &Vlan{
746+ LowerDev: iface.VLAN.LowerDevice,
747+ Vid: iface.VLAN.VID,
748+ }
749+ i.Parents = append(i.Parents, iface.VLAN.LowerDevice)
750+ }
751+ dhcpAddr := dhclientInfo[name]
752+ for _, addr := range iface.Addresses {
753+ mode := "static"
754+ if net.ParseIP(addr.Address).String() == dhcpAddr {
755+ mode = "dhcp"
756+ }
757+
758+ link := IPLink{Mode: mode, Address: addr.Address}
759+ if len(addr.Netmask) > 0 {
760+ link.Netmask, err = strconv.Atoi(addr.Netmask)
761+ if err != nil {
762+ return nil, err
763+ }
764+ }
765+ i.Links = append(i.Links, link)
766+ }
767+ i.Links, err = fixLinkAddresses(i.Links)
768+ if err != nil {
769+ return nil, err
770+ }
771+ i.Links, err = fixGateways(i.Links, iprouteInfo)
772+ if err != nil {
773+ return nil, err
774+ }
775+ res[name] = i
776+ }
777+ if annotateWithMonitored {
778+ monitoredIfaces := GetDefaultMonitoredInterfaces(res)
779+ for name, iface := range res {
780+ if _, ok := monitoredIfaces[name]; ok {
781+ iface.Monitored = true
782+ } else {
783+ iface.Monitored = false
784+ }
785+ res[name] = iface
786+ }
787+ }
788+ return res, nil
789+}
790diff --git a/src/rackd_spike/internal/machine_helpers/interfaces_capnp.go b/src/rackd_spike/internal/machine_helpers/interfaces_capnp.go
791new file mode 100644
792index 0000000..777f0b4
793--- /dev/null
794+++ b/src/rackd_spike/internal/machine_helpers/interfaces_capnp.go
795@@ -0,0 +1,65 @@
796+package machinehelpers
797+
798+import (
799+ "rackd/pkg/rpc"
800+)
801+
802+type CapnpInterfaces map[string]Interface
803+
804+func (c CapnpInterfaces) SetProto(ifacePayload rpc.Interfaces) error {
805+ ifaces, err := ifacePayload.NewIfaces(int32(len(c)))
806+ if err != nil {
807+ return err
808+ }
809+ var idx int
810+ for name, iface := range c {
811+ protoIface := ifaces.At(idx)
812+ err = protoIface.SetName(name)
813+ if err != nil {
814+ return err
815+ }
816+ details, err := protoIface.NewIface()
817+ if err != nil {
818+ return err
819+ }
820+ details.SetMacAddress(iface.Mac)
821+ details.SetType(iface.Type)
822+ protoLinks, err := details.NewLinks(int32(len(iface.Links)))
823+ if err != nil {
824+ return err
825+ }
826+ for i, link := range iface.Links {
827+ protoLink := protoLinks.At(i)
828+ err = protoLink.SetMode(link.Mode)
829+ if err != nil {
830+ return err
831+ }
832+ err = protoLink.SetAddress(link.Address)
833+ if err != nil {
834+ return err
835+ }
836+ err = protoLink.SetGateway(link.Gateway)
837+ if err != nil {
838+ return err
839+ }
840+ protoLink.SetNetmask(int32(link.Netmask))
841+ }
842+ if iface.Vlan != nil {
843+ details.SetVid(iface.Vlan.Vid)
844+ }
845+ if len(iface.Parents) > 0 {
846+ protoParents, err := details.NewParents(int32(len(iface.Parents)))
847+ if err != nil {
848+ return err
849+ }
850+ for i, parent := range iface.Parents {
851+ err = protoParents.Set(i, parent)
852+ if err != nil {
853+ return err
854+ }
855+ }
856+ }
857+ idx++
858+ }
859+ return nil
860+}
861diff --git a/src/rackd_spike/internal/machine_helpers/interfaces_test.go b/src/rackd_spike/internal/machine_helpers/interfaces_test.go
862new file mode 100644
863index 0000000..a7d2b3c
864--- /dev/null
865+++ b/src/rackd_spike/internal/machine_helpers/interfaces_test.go
866@@ -0,0 +1,81 @@
867+package machinehelpers
868+
869+import (
870+ "errors"
871+ "io"
872+ "testing"
873+)
874+
875+type mockLeaseFile struct {
876+ Data []byte
877+}
878+
879+func (m mockLeaseFile) Read(b []byte) (n int, err error) {
880+ n = copy(b, m.Data)
881+ if n > 0 {
882+ m.Data = m.Data[n:]
883+ }
884+ if len(m.Data) == 0 {
885+ return n, io.EOF
886+ }
887+ return n, nil
888+}
889+
890+func TestGetLatestFixedAddress(t *testing.T) {
891+ table := []struct {
892+ Name string
893+ In mockLeaseFile
894+ Out string
895+ Err error
896+ }{
897+ {
898+ Name: "basic-v4-lease-file",
899+ In: mockLeaseFile{
900+ Data: []byte(`
901+ lease {
902+ fixed-address 10.0.0.2;
903+ }
904+ `),
905+ },
906+ Out: "10.0.0.2",
907+ }, {
908+ Name: "basic-v6-lease-file",
909+ In: mockLeaseFile{
910+ Data: []byte(`
911+ lease {
912+ fixed-address6 fe80::ca56:eed8:1344:1aa2;
913+ }
914+ `),
915+ },
916+ Out: "fe80::ca56:eed8:1344:1aa2",
917+ }, {
918+ Name: "no-data-lease-file",
919+ In: mockLeaseFile{},
920+ }, {
921+ Name: "multi-lease-lease-file",
922+ In: mockLeaseFile{
923+ Data: []byte(`
924+ lease {
925+ fixed-address 10.0.0.9;
926+ }
927+
928+ lease {
929+ fixed-address 10.0.0.2;
930+ }
931+ `),
932+ },
933+ Out: "10.0.0.2",
934+ },
935+ }
936+ for _, tcase := range table {
937+ t.Run(tcase.Name, func(tt *testing.T) {
938+ out, err := getLatestFixedAddress(tcase.In)
939+ if !errors.Is(err, tcase.Err) {
940+ tt.Fatalf("expected %v to equal %v", err, tcase.Err)
941+ }
942+ if out != tcase.Out {
943+ tt.Fatalf("expected '%s' to equal '%s'", out, tcase.Out)
944+ }
945+ })
946+ }
947+}
948diff --git a/src/rackd_spike/internal/machine_helpers/ps.go b/src/rackd_spike/internal/machine_helpers/ps.go
949new file mode 100644
950index 0000000..016564b
951--- /dev/null
952+++ b/src/rackd_spike/internal/machine_helpers/ps.go
953@@ -0,0 +1,81 @@
954+package machinehelpers
955+
956+import (
957+ "bufio"
958+ "context"
959+ "os"
960+ "os/exec"
961+ "path/filepath"
962+ "strconv"
963+ "strings"
964+)
965+
966+const (
967+ vertCheckExec = "systemd-detect-virt"
968+)
969+
970+var (
971+ vertCheckArgs = []string{"-c"}
972+)
973+
974+func RunningInContainer(ctx context.Context) (bool, error) {
975+ cmd := exec.CommandContext(ctx, vertCheckExec, vertCheckArgs...)
976+ if err := cmd.Run(); err != nil {
977+ if cmd.ProcessState.ExitCode() == 1 {
978+ return false, nil
979+ }
980+ return false, err
981+ }
982+ return true, nil
983+}
984+
985+func PIDInContainer(pid int, procPath string) (bool, error) {
986+ if len(procPath) == 0 {
987+ procPath = "/proc"
988+ }
989+ cgroupPath := filepath.Join(procPath, strconv.Itoa(pid), "cgroup")
990+ f, err := os.Open(cgroupPath)
991+ if err != nil {
992+ return false, err
993+ }
994+ defer f.Close()
995+ scanner := bufio.NewScanner(f)
996+ for scanner.Scan() {
997+ line := scanner.Text()
998+ cgroup := strings.SplitN(line, ":", 2)
999+ // cgroup[2] will be the cgroup heirarchy
1000+ if strings.HasPrefix(cgroup[2], "/lxc") || strings.Contains(cgroup[2], "docker") {
1001+ return true, nil
1002+ }
1003+ }
1004+ return false, nil
1005+}
1006+
1007+func GetRunningPIDsWithCMD(ctx context.Context, command, procPath string, excludeContainerProcesses bool) ([]int, error) {
1008+ if len(procPath) == 0 {
1009+ procPath = "/proc"
1010+ }
1011+ dirs, err := os.ReadDir(procPath)
1012+ if err != nil {
1013+ return nil, err
1014+ }
1015+ var runningPIDs []int
1016+ runningInContainer, err := RunningInContainer(ctx)
1017+ if err != nil {
1018+ return nil, err
1019+ }
1020+ for _, dir := range dirs {
1021+ pid, parseErr := strconv.Atoi(dir.Name())
1022+ if parseErr == nil {
1023+ pidInContainer, err := PIDInContainer(pid, procPath)
1024+ if err != nil {
1025+ return nil, err
1026+ }
1027+ if excludeContainerProcesses && !runningInContainer && pidInContainer {
1028+ continue
1029+ }
1030+ runningPIDs = append(runningPIDs, pid)
1031+ }
1032+ }
1033+ return runningPIDs, nil
1034+}
1035diff --git a/src/rackd_spike/internal/machine_helpers/refresh.go b/src/rackd_spike/internal/machine_helpers/refresh.go
1036new file mode 100644
1037index 0000000..685460b
1038--- /dev/null
1039+++ b/src/rackd_spike/internal/machine_helpers/refresh.go
1040@@ -0,0 +1,29 @@
1041+package machinehelpers
1042+
1043+import (
1044+ "path/filepath"
1045+ "runtime"
1046+)
1047+
1048+func isDevEnv() bool {
1049+ // TODO grab this value from config
1050+ return true
1051+}
1052+
1053+func GetResourcesBinPath() (string, error) {
1054+ var path string
1055+ if isDevEnv() {
1056+ path = "src/machine-resources/bin"
1057+ } else {
1058+ prefix, ok := SnapPaths{}.FromEnv()["snap"]
1059+ path = "/usr/share/maas/machine-resources"
1060+ if ok {
1061+ path = prefix + path
1062+ }
1063+ }
1064+ absPath, err := filepath.Abs(path)
1065+ if err != nil {
1066+ return "", err
1067+ }
1068+ return filepath.Join(absPath, runtime.GOARCH), nil
1069+}
1070diff --git a/src/rackd_spike/internal/machine_helpers/snap.go b/src/rackd_spike/internal/machine_helpers/snap.go
1071new file mode 100644
1072index 0000000..0956377
1073--- /dev/null
1074+++ b/src/rackd_spike/internal/machine_helpers/snap.go
1075@@ -0,0 +1,30 @@
1076+package machinehelpers
1077+
1078+import (
1079+ "os"
1080+)
1081+
1082+var (
1083+ pathVars = map[string]string{
1084+ "snap": "SNAP",
1085+ "common": "SNAP_COMMON",
1086+ "data": "SNAP_DATA",
1087+ }
1088+)
1089+
1090+func IsRunningInSnap() bool {
1091+ _, ok := os.LookupEnv("SNAP")
1092+ return ok
1093+}
1094+
1095+type SnapPaths map[string]string
1096+
1097+func (s SnapPaths) FromEnv() SnapPaths {
1098+ for k, v := range pathVars {
1099+ path, ok := os.LookupEnv(v)
1100+ if ok {
1101+ s[k] = path
1102+ }
1103+ }
1104+ return s
1105+}
1106diff --git a/src/rackd_spike/internal/transport/rpc.go b/src/rackd_spike/internal/transport/rpc.go
1107new file mode 100644
1108index 0000000..c0764d0
1109--- /dev/null
1110+++ b/src/rackd_spike/internal/transport/rpc.go
1111@@ -0,0 +1,127 @@
1112+package transport
1113+
1114+import (
1115+ "context"
1116+ "crypto/tls"
1117+ "errors"
1118+ "net"
1119+ "net/url"
1120+
1121+ capnprpc "capnproto.org/go/capnp/v3/rpc"
1122+ "github.com/rs/zerolog"
1123+
1124+ "rackd/internal/metrics"
1125+)
1126+
1127+var (
1128+ ErrRPCClientNotFound = errors.New("error client not found")
1129+)
1130+
1131+type RPCHandler interface {
1132+ Name() string
1133+ RegisterMetrics(*metrics.Registry) error
1134+ SetupServer(context.Context, *ConnWrapper)
1135+}
1136+
1137+type RPCClient interface {
1138+ Name() string
1139+ RegisterMetrics(*metrics.Registry) error
1140+ SetupClient(context.Context, *ConnWrapper)
1141+}
1142+
1143+type CapnpRPCClient interface {
1144+ RPCClient
1145+ Release()
1146+}
1147+
1148+type ConnWrapper struct {
1149+ Conn net.Conn
1150+ capnpConn *capnprpc.Conn
1151+}
1152+
1153+func NewConnWrapper(conn net.Conn) *ConnWrapper {
1154+ return &ConnWrapper{
1155+ Conn: conn,
1156+ capnpConn: capnprpc.NewConn(capnprpc.NewStreamTransport(conn), nil),
1157+ }
1158+}
1159+
1160+func (c *ConnWrapper) Capnp() *capnprpc.Conn {
1161+ return c.capnpConn
1162+}
1163+
1164+type RPCManager struct {
1165+ conns map[string]*ConnWrapper
1166+ handlers map[string]RPCHandler
1167+ clients map[string]RPCClient
1168+ initURL string
1169+ skipHostVerify bool
1170+}
1171+
1172+func NewRPCManager(rpcServerURL string, skipHostVerify bool) *RPCManager {
1173+ return &RPCManager{
1174+ conns: make(map[string]*ConnWrapper),
1175+ handlers: make(map[string]RPCHandler),
1176+ clients: make(map[string]RPCClient),
1177+ initURL: rpcServerURL,
1178+ skipHostVerify: skipHostVerify,
1179+ }
1180+}
1181+
1182+// Init initiates the initial region connection
1183+func (r *RPCManager) Init(ctx context.Context) error {
1184+ parsedURL, err := url.Parse(r.initURL)
1185+ if err != nil {
1186+ return err
1187+ }
1188+ var conn net.Conn
1189+ if parsedURL.Scheme == "https" {
1190+ conn, err = tls.Dial(
1191+ "tcp",
1192+ net.JoinHostPort(parsedURL.Hostname(), parsedURL.Port()),
1193+ &tls.Config{InsecureSkipVerify: r.skipHostVerify},
1194+ )
1195+ } else {
1196+ conn, err = net.Dial("tcp", net.JoinHostPort(parsedURL.Hostname(), parsedURL.Port()))
1197+ }
1198+ if err != nil {
1199+ return err
1200+ }
1201+ r.AddConn(ctx, conn)
1202+ log := zerolog.Ctx(ctx)
1203+ log.Debug().Msg("connected to region server")
1204+ return nil
1205+}
1206+
1207+func (r *RPCManager) AddHandler(ctx context.Context, handler RPCHandler) {
1208+ r.handlers[handler.Name()] = handler
1209+ for _, conn := range r.conns {
1210+ handler.SetupServer(ctx, conn)
1211+ }
1212+}
1213+
1214+func (r *RPCManager) AddClient(ctx context.Context, client RPCClient) {
1215+ r.clients[client.Name()] = client
1216+ for _, conn := range r.conns {
1217+ client.SetupClient(ctx, conn)
1218+ }
1219+}
1220+
1221+func (r *RPCManager) AddConn(ctx context.Context, conn net.Conn) {
1222+ newConn := NewConnWrapper(conn)
1223+ r.conns[conn.RemoteAddr().String()] = newConn
1224+ for _, handler := range r.handlers {
1225+ handler.SetupServer(ctx, newConn)
1226+ }
1227+ for _, client := range r.clients {
1228+ client.SetupClient(ctx, newConn)
1229+ }
1230+}
1231+
1232+func (r *RPCManager) GetClient(clientName string) (RPCClient, error) {
1233+ c, ok := r.clients[clientName]
1234+ if !ok {
1235+ return nil, ErrRPCClientNotFound
1236+ }
1237+ return c, nil
1238+}
1239diff --git a/src/rackd_spike/pkg/authenticate/authenticator.go b/src/rackd_spike/pkg/authenticate/authenticator.go
1240new file mode 100644
1241index 0000000..6a60a86
1242--- /dev/null
1243+++ b/src/rackd_spike/pkg/authenticate/authenticator.go
1244@@ -0,0 +1,93 @@
1245+package authenticate
1246+
1247+import (
1248+ "bytes"
1249+ "context"
1250+ "fmt"
1251+
1252+ "rackd/internal/metrics"
1253+ "rackd/internal/transport"
1254+ "rackd/pkg/rpc"
1255+)
1256+
1257+type AuthCreds struct {
1258+ Salt []byte
1259+ Digest []byte
1260+}
1261+
1262+func (c *AuthCreds) localDigest(secret, message []byte) []byte {
1263+ // TODO
1264+ return nil
1265+}
1266+
1267+func (c *AuthCreds) Verify(secret, message []byte) bool {
1268+ return bytes.Compare(c.Digest, c.localDigest(secret, message)) == 0
1269+}
1270+
1271+type Authenticator interface {
1272+ transport.RPCClient
1273+ Authenticate(context.Context, string, []byte, []byte) (*AuthCreds, error)
1274+}
1275+
1276+type CapnpAuthenticator struct {
1277+ clients map[string]*rpc.Authenticator
1278+}
1279+
1280+func NewCapnpAuthenticator() Authenticator {
1281+ // Perhaps we should initialize this with the shared secret already loaded either
1282+ // from the config manager or load from the FS on instantiation?
1283+ return &CapnpAuthenticator{
1284+ clients: make(map[string]*rpc.Authenticator),
1285+ }
1286+}
1287+
1288+func (c *CapnpAuthenticator) Name() string {
1289+ return "authenticator"
1290+}
1291+
1292+func (c *CapnpAuthenticator) RegisterMetrics(registry *metrics.Registry) error {
1293+ // TODO
1294+ return nil
1295+}
1296+
1297+func (c *CapnpAuthenticator) SetupClient(ctx context.Context, conn *transport.ConnWrapper) {
1298+ c.clients[conn.Conn.RemoteAddr().String()] = &rpc.Authenticator{Client: conn.Capnp().Bootstrap(ctx)}
1299+}
1300+
1301+func (c *CapnpAuthenticator) Authenticate(ctx context.Context, region string, secret, message []byte) (*AuthCreds, error) {
1302+ regionClient, ok := c.clients[region]
1303+ if !ok {
1304+ return nil, fmt.Errorf("%w: %s", transport.ErrRPCClientNotFound, region)
1305+ }
1306+ result, release := regionClient.Authenticate(ctx, func(params rpc.Authenticator_authenticate_Params) error {
1307+ return params.SetMsg(message)
1308+ })
1309+ defer release()
1310+ resp, err := result.Struct()
1311+ if err != nil {
1312+ return nil, err
1313+ }
1314+ creds, err := resp.Resp()
1315+ if err != nil {
1316+ return nil, err
1317+ }
1318+ salt, err := creds.Salt()
1319+ if err != nil {
1320+ return nil, err
1321+ }
1322+ digest, err := creds.Digest()
1323+ if err != nil {
1324+ return nil, err
1325+ }
1326+ return &AuthCreds{
1327+ Salt: salt,
1328+ Digest: digest,
1329+ }, nil
1330+}
1331+
1332+func (c *CapnpAuthenticator) Release() {
1333+ for k, client := range c.clients {
1334+ client.Release()
1335+ delete(c.clients, k)
1336+ }
1337+}
1338diff --git a/src/rackd_spike/pkg/region/handshake.go b/src/rackd_spike/pkg/region/handshake.go
1339new file mode 100644
1340index 0000000..4d1a090
1341--- /dev/null
1342+++ b/src/rackd_spike/pkg/region/handshake.go
1343@@ -0,0 +1,91 @@
1344+package region
1345+
1346+import (
1347+ "context"
1348+ "crypto/rand"
1349+ "errors"
1350+ "fmt"
1351+ "os"
1352+
1353+ machinehelpers "rackd/internal/machine_helpers"
1354+ "rackd/internal/transport"
1355+ auth "rackd/pkg/authenticate"
1356+ reg "rackd/pkg/register"
1357+)
1358+
1359+var (
1360+ ErrNoAuthenticatorProvided = errors.New("error no authenticator was provided")
1361+ ErrNoRegistererProvided = errors.New("error no registerer was provided")
1362+ ErrRegionNotAuthed = errors.New("error unable to authenticate with region")
1363+)
1364+
1365+func authenticate(ctx context.Context, region string, rpcMgr *transport.RPCManager) error {
1366+ authenticatorIface, err := rpcMgr.GetClient("authenticator")
1367+ if err != nil {
1368+ return err
1369+ }
1370+ authenticator, ok := authenticatorIface.(auth.Authenticator)
1371+ if !ok {
1372+ return ErrNoAuthenticatorProvided
1373+ }
1374+ secret := []byte{} // TODO get this from filesystem
1375+ message := make([]byte, 16)
1376+ _, err = rand.Read(message)
1377+ if err != nil {
1378+ return err
1379+ }
1380+ creds, err := authenticator.Authenticate(ctx, region, secret, message)
1381+ if err != nil {
1382+ return err
1383+ }
1384+ if !creds.Verify(secret, message) {
1385+ return fmt.Errorf("%w: credential verification failed", ErrRegionNotAuthed)
1386+ }
1387+ return nil
1388+}
1389+
1390+func register(ctx context.Context, region, localVersion string, rpcMgr *transport.RPCManager) error {
1391+ registererIface, err := rpcMgr.GetClient("registerer")
1392+ if err != nil {
1393+ return err
1394+ }
1395+ registerer, ok := registererIface.(reg.Registerer)
1396+ if !ok {
1397+ return ErrNoRegistererProvided
1398+ }
1399+ // TODO get cluster UUID from config
1400+ clusterUUID := "123456"
1401+ systemId, err := machinehelpers.GetMAASID()
1402+ if err != nil {
1403+ return err
1404+ }
1405+ interfaces, err := machinehelpers.GetAllInterfacesDefinition(ctx, false)
1406+ if err != nil {
1407+ return err
1408+ }
1409+ hostname, err := os.Hostname()
1410+ if err != nil {
1411+ return err
1412+ }
1413+ err = registerer.Register(
1414+ ctx,
1415+ region,
1416+ clusterUUID,
1417+ systemId,
1418+ hostname,
1419+ localVersion,
1420+ interfaces,
1421+ )
1422+ if err != nil {
1423+ return err
1424+ }
1425+ return nil
1426+}
1427+
1428+func Handshake(ctx context.Context, region, localVersion string, rpcMgr *transport.RPCManager) error {
1429+ err := authenticate(ctx, region, rpcMgr)
1430+ if err != nil {
1431+ return err
1432+ }
1433+ return register(ctx, region, localVersion, rpcMgr)
1434+}
1435diff --git a/src/rackd_spike/pkg/register/registerer.go b/src/rackd_spike/pkg/register/registerer.go
1436new file mode 100644
1437index 0000000..b6562e7
1438--- /dev/null
1439+++ b/src/rackd_spike/pkg/register/registerer.go
1440@@ -0,0 +1,125 @@
1441+package register
1442+
1443+import (
1444+ "context"
1445+
1446+ "github.com/rs/zerolog"
1447+
1448+ machinehelpers "rackd/internal/machine_helpers"
1449+ "rackd/internal/metrics"
1450+ "rackd/internal/transport"
1451+ "rackd/pkg/rpc"
1452+)
1453+
1454+type Registerer interface {
1455+ transport.RPCClient
1456+ Register(
1457+ ctx context.Context,
1458+ region, clusterUUID, systemId, hostname, version string,
1459+ interfaces map[string]machinehelpers.Interface,
1460+ ) error
1461+}
1462+
1463+type CapnpRegisterer struct {
1464+ clients map[string]*rpc.Registerer
1465+}
1466+
1467+func NewCapnpRegisterer() Registerer {
1468+ return &CapnpRegisterer{}
1469+}
1470+
1471+func (c *CapnpRegisterer) Name() string {
1472+ return "Registerer"
1473+}
1474+
1475+func (c *CapnpRegisterer) RegisterMetrics(registry *metrics.Registry) error {
1476+ // TODO
1477+ return nil
1478+}
1479+
1480+func (c *CapnpRegisterer) SetupClient(ctx context.Context, client *transport.ConnWrapper) {
1481+ c.clients[client.Conn.RemoteAddr().String()] = &rpc.Registerer{Client: client.Capnp().Bootstrap(ctx)}
1482+}
1483+
1484+func (c *CapnpRegisterer) Register(
1485+ ctx context.Context,
1486+ region, clusterUUID, systemId, hostname, version string,
1487+ interfaces map[string]machinehelpers.Interface,
1488+) error {
1489+ client, ok := c.clients[region]
1490+ if !ok {
1491+ return transport.ErrRPCClientNotFound
1492+ }
1493+ result, release := client.Register(ctx, func(params rpc.Registerer_register_Params) error {
1494+ req, err := params.NewReq()
1495+ if err != nil {
1496+ return err
1497+ }
1498+ err = req.SetSystemId(systemId)
1499+ if err != nil {
1500+ return err
1501+ }
1502+ err = req.SetHostname(hostname)
1503+ if err != nil {
1504+ return err
1505+ }
1506+ ifaces, err := req.NewInterfaces()
1507+ if err != nil {
1508+ return err
1509+ }
1510+ capnpIfaces := machinehelpers.CapnpInterfaces(interfaces)
1511+ err = capnpIfaces.SetProto(ifaces)
1512+ if err != nil {
1513+ return err
1514+ }
1515+ err = req.SetUrl(region)
1516+ if err != nil {
1517+ return err
1518+ }
1519+ err = req.SetNodegroup(clusterUUID)
1520+ if err != nil {
1521+ return err
1522+ }
1523+ req.SetBeaconSupport(true)
1524+ err = req.SetVersion(version)
1525+ if err != nil {
1526+ return err
1527+ }
1528+ return nil
1529+ })
1530+ defer release()
1531+ resp, err := result.Struct()
1532+ if err != nil {
1533+ return err
1534+ }
1535+ res, err := resp.Resp()
1536+ if err != nil {
1537+ return err
1538+ }
1539+ localId, err := res.SystemId()
1540+ if err != nil {
1541+ return err
1542+ }
1543+ // TODO set global metrics labels
1544+ err = machinehelpers.SetMAASId(localId)
1545+ if err != nil {
1546+ return err
1547+ }
1548+ respVersion, err := res.Version()
1549+ if err != nil {
1550+ return err
1551+ }
1552+ if len(respVersion) == 0 {
1553+ respVersion = "unknown MAAS version"
1554+ }
1555+ log := zerolog.Ctx(ctx)
1556+ log.Log().Msgf("Rack controller '%s' registered (via %s) with %s.", localId, region, respVersion)
1557+ return nil
1558+}
1559+
1560+func (c *CapnpRegisterer) Release() {
1561+ for k, client := range c.clients {
1562+ client.Release()
1563+ delete(c.clients, k)
1564+ }
1565+}
1566diff --git a/src/rackd_spike/pkg/rpc/handshake.capnp.go b/src/rackd_spike/pkg/rpc/handshake.capnp.go
1567new file mode 100644
1568index 0000000..94955c9
1569--- /dev/null
1570+++ b/src/rackd_spike/pkg/rpc/handshake.capnp.go
1571@@ -0,0 +1,933 @@
1572+// Code generated by capnpc-go. DO NOT EDIT.
1573+
1574+package rpc
1575+
1576+import (
1577+ capnp "capnproto.org/go/capnp/v3"
1578+ text "capnproto.org/go/capnp/v3/encoding/text"
1579+ schemas "capnproto.org/go/capnp/v3/schemas"
1580+ server "capnproto.org/go/capnp/v3/server"
1581+ context "context"
1582+)
1583+
1584+type AuthResponse struct{ capnp.Struct }
1585+
1586+// AuthResponse_TypeID is the unique identifier for the type AuthResponse.
1587+const AuthResponse_TypeID = 0x98b03f82d720e4e1
1588+
1589+func NewAuthResponse(s *capnp.Segment) (AuthResponse, error) {
1590+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2})
1591+ return AuthResponse{st}, err
1592+}
1593+
1594+func NewRootAuthResponse(s *capnp.Segment) (AuthResponse, error) {
1595+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2})
1596+ return AuthResponse{st}, err
1597+}
1598+
1599+func ReadRootAuthResponse(msg *capnp.Message) (AuthResponse, error) {
1600+ root, err := msg.Root()
1601+ return AuthResponse{root.Struct()}, err
1602+}
1603+
1604+func (s AuthResponse) String() string {
1605+ str, _ := text.Marshal(0x98b03f82d720e4e1, s.Struct)
1606+ return str
1607+}
1608+
1609+func (s AuthResponse) Salt() ([]byte, error) {
1610+ p, err := s.Struct.Ptr(0)
1611+ return []byte(p.Data()), err
1612+}
1613+
1614+func (s AuthResponse) HasSalt() bool {
1615+ return s.Struct.HasPtr(0)
1616+}
1617+
1618+func (s AuthResponse) SetSalt(v []byte) error {
1619+ return s.Struct.SetData(0, v)
1620+}
1621+
1622+func (s AuthResponse) Digest() ([]byte, error) {
1623+ p, err := s.Struct.Ptr(1)
1624+ return []byte(p.Data()), err
1625+}
1626+
1627+func (s AuthResponse) HasDigest() bool {
1628+ return s.Struct.HasPtr(1)
1629+}
1630+
1631+func (s AuthResponse) SetDigest(v []byte) error {
1632+ return s.Struct.SetData(1, v)
1633+}
1634+
1635+// AuthResponse_List is a list of AuthResponse.
1636+type AuthResponse_List struct{ capnp.List }
1637+
1638+// NewAuthResponse creates a new list of AuthResponse.
1639+func NewAuthResponse_List(s *capnp.Segment, sz int32) (AuthResponse_List, error) {
1640+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz)
1641+ return AuthResponse_List{l}, err
1642+}
1643+
1644+func (s AuthResponse_List) At(i int) AuthResponse { return AuthResponse{s.List.Struct(i)} }
1645+
1646+func (s AuthResponse_List) Set(i int, v AuthResponse) error { return s.List.SetStruct(i, v.Struct) }
1647+
1648+func (s AuthResponse_List) String() string {
1649+ str, _ := text.MarshalList(0x98b03f82d720e4e1, s.List)
1650+ return str
1651+}
1652+
1653+// AuthResponse_Future is a wrapper for a AuthResponse promised by a client call.
1654+type AuthResponse_Future struct{ *capnp.Future }
1655+
1656+func (p AuthResponse_Future) Struct() (AuthResponse, error) {
1657+ s, err := p.Future.Struct()
1658+ return AuthResponse{s}, err
1659+}
1660+
1661+type Authenticator struct{ Client *capnp.Client }
1662+
1663+// Authenticator_TypeID is the unique identifier for the type Authenticator.
1664+const Authenticator_TypeID = 0x800ae3a77a7bc18e
1665+
1666+func (c Authenticator) Authenticate(ctx context.Context, params func(Authenticator_authenticate_Params) error) (Authenticator_authenticate_Results_Future, capnp.ReleaseFunc) {
1667+ s := capnp.Send{
1668+ Method: capnp.Method{
1669+ InterfaceID: 0x800ae3a77a7bc18e,
1670+ MethodID: 0,
1671+ InterfaceName: "handshake.capnp:Authenticator",
1672+ MethodName: "authenticate",
1673+ },
1674+ }
1675+ if params != nil {
1676+ s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1}
1677+ s.PlaceArgs = func(s capnp.Struct) error { return params(Authenticator_authenticate_Params{Struct: s}) }
1678+ }
1679+ ans, release := c.Client.SendCall(ctx, s)
1680+ return Authenticator_authenticate_Results_Future{Future: ans.Future()}, release
1681+}
1682+
1683+func (c Authenticator) AddRef() Authenticator {
1684+ return Authenticator{
1685+ Client: c.Client.AddRef(),
1686+ }
1687+}
1688+
1689+func (c Authenticator) Release() {
1690+ c.Client.Release()
1691+}
1692+
1693+// A Authenticator_Server is a Authenticator with a local implementation.
1694+type Authenticator_Server interface {
1695+ Authenticate(context.Context, Authenticator_authenticate) error
1696+}
1697+
1698+// Authenticator_NewServer creates a new Server from an implementation of Authenticator_Server.
1699+func Authenticator_NewServer(s Authenticator_Server, policy *server.Policy) *server.Server {
1700+ c, _ := s.(server.Shutdowner)
1701+ return server.New(Authenticator_Methods(nil, s), s, c, policy)
1702+}
1703+
1704+// Authenticator_ServerToClient creates a new Client from an implementation of Authenticator_Server.
1705+// The caller is responsible for calling Release on the returned Client.
1706+func Authenticator_ServerToClient(s Authenticator_Server, policy *server.Policy) Authenticator {
1707+ return Authenticator{Client: capnp.NewClient(Authenticator_NewServer(s, policy))}
1708+}
1709+
1710+// Authenticator_Methods appends Methods to a slice that invoke the methods on s.
1711+// This can be used to create a more complicated Server.
1712+func Authenticator_Methods(methods []server.Method, s Authenticator_Server) []server.Method {
1713+ if cap(methods) == 0 {
1714+ methods = make([]server.Method, 0, 1)
1715+ }
1716+
1717+ methods = append(methods, server.Method{
1718+ Method: capnp.Method{
1719+ InterfaceID: 0x800ae3a77a7bc18e,
1720+ MethodID: 0,
1721+ InterfaceName: "handshake.capnp:Authenticator",
1722+ MethodName: "authenticate",
1723+ },
1724+ Impl: func(ctx context.Context, call *server.Call) error {
1725+ return s.Authenticate(ctx, Authenticator_authenticate{call})
1726+ },
1727+ })
1728+
1729+ return methods
1730+}
1731+
1732+// Authenticator_authenticate holds the state for a server call to Authenticator.authenticate.
1733+// See server.Call for documentation.
1734+type Authenticator_authenticate struct {
1735+ *server.Call
1736+}
1737+
1738+// Args returns the call's arguments.
1739+func (c Authenticator_authenticate) Args() Authenticator_authenticate_Params {
1740+ return Authenticator_authenticate_Params{Struct: c.Call.Args()}
1741+}
1742+
1743+// AllocResults allocates the results struct.
1744+func (c Authenticator_authenticate) AllocResults() (Authenticator_authenticate_Results, error) {
1745+ r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 0, PointerCount: 1})
1746+ return Authenticator_authenticate_Results{Struct: r}, err
1747+}
1748+
1749+type Authenticator_authenticate_Params struct{ capnp.Struct }
1750+
1751+// Authenticator_authenticate_Params_TypeID is the unique identifier for the type Authenticator_authenticate_Params.
1752+const Authenticator_authenticate_Params_TypeID = 0xdbaca3bedaffa653
1753+
1754+func NewAuthenticator_authenticate_Params(s *capnp.Segment) (Authenticator_authenticate_Params, error) {
1755+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
1756+ return Authenticator_authenticate_Params{st}, err
1757+}
1758+
1759+func NewRootAuthenticator_authenticate_Params(s *capnp.Segment) (Authenticator_authenticate_Params, error) {
1760+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
1761+ return Authenticator_authenticate_Params{st}, err
1762+}
1763+
1764+func ReadRootAuthenticator_authenticate_Params(msg *capnp.Message) (Authenticator_authenticate_Params, error) {
1765+ root, err := msg.Root()
1766+ return Authenticator_authenticate_Params{root.Struct()}, err
1767+}
1768+
1769+func (s Authenticator_authenticate_Params) String() string {
1770+ str, _ := text.Marshal(0xdbaca3bedaffa653, s.Struct)
1771+ return str
1772+}
1773+
1774+func (s Authenticator_authenticate_Params) Msg() ([]byte, error) {
1775+ p, err := s.Struct.Ptr(0)
1776+ return []byte(p.Data()), err
1777+}
1778+
1779+func (s Authenticator_authenticate_Params) HasMsg() bool {
1780+ return s.Struct.HasPtr(0)
1781+}
1782+
1783+func (s Authenticator_authenticate_Params) SetMsg(v []byte) error {
1784+ return s.Struct.SetData(0, v)
1785+}
1786+
1787+// Authenticator_authenticate_Params_List is a list of Authenticator_authenticate_Params.
1788+type Authenticator_authenticate_Params_List struct{ capnp.List }
1789+
1790+// NewAuthenticator_authenticate_Params creates a new list of Authenticator_authenticate_Params.
1791+func NewAuthenticator_authenticate_Params_List(s *capnp.Segment, sz int32) (Authenticator_authenticate_Params_List, error) {
1792+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
1793+ return Authenticator_authenticate_Params_List{l}, err
1794+}
1795+
1796+func (s Authenticator_authenticate_Params_List) At(i int) Authenticator_authenticate_Params {
1797+ return Authenticator_authenticate_Params{s.List.Struct(i)}
1798+}
1799+
1800+func (s Authenticator_authenticate_Params_List) Set(i int, v Authenticator_authenticate_Params) error {
1801+ return s.List.SetStruct(i, v.Struct)
1802+}
1803+
1804+func (s Authenticator_authenticate_Params_List) String() string {
1805+ str, _ := text.MarshalList(0xdbaca3bedaffa653, s.List)
1806+ return str
1807+}
1808+
1809+// Authenticator_authenticate_Params_Future is a wrapper for a Authenticator_authenticate_Params promised by a client call.
1810+type Authenticator_authenticate_Params_Future struct{ *capnp.Future }
1811+
1812+func (p Authenticator_authenticate_Params_Future) Struct() (Authenticator_authenticate_Params, error) {
1813+ s, err := p.Future.Struct()
1814+ return Authenticator_authenticate_Params{s}, err
1815+}
1816+
1817+type Authenticator_authenticate_Results struct{ capnp.Struct }
1818+
1819+// Authenticator_authenticate_Results_TypeID is the unique identifier for the type Authenticator_authenticate_Results.
1820+const Authenticator_authenticate_Results_TypeID = 0x96c07ce683897942
1821+
1822+func NewAuthenticator_authenticate_Results(s *capnp.Segment) (Authenticator_authenticate_Results, error) {
1823+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
1824+ return Authenticator_authenticate_Results{st}, err
1825+}
1826+
1827+func NewRootAuthenticator_authenticate_Results(s *capnp.Segment) (Authenticator_authenticate_Results, error) {
1828+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
1829+ return Authenticator_authenticate_Results{st}, err
1830+}
1831+
1832+func ReadRootAuthenticator_authenticate_Results(msg *capnp.Message) (Authenticator_authenticate_Results, error) {
1833+ root, err := msg.Root()
1834+ return Authenticator_authenticate_Results{root.Struct()}, err
1835+}
1836+
1837+func (s Authenticator_authenticate_Results) String() string {
1838+ str, _ := text.Marshal(0x96c07ce683897942, s.Struct)
1839+ return str
1840+}
1841+
1842+func (s Authenticator_authenticate_Results) Resp() (AuthResponse, error) {
1843+ p, err := s.Struct.Ptr(0)
1844+ return AuthResponse{Struct: p.Struct()}, err
1845+}
1846+
1847+func (s Authenticator_authenticate_Results) HasResp() bool {
1848+ return s.Struct.HasPtr(0)
1849+}
1850+
1851+func (s Authenticator_authenticate_Results) SetResp(v AuthResponse) error {
1852+ return s.Struct.SetPtr(0, v.Struct.ToPtr())
1853+}
1854+
1855+// NewResp sets the resp field to a newly
1856+// allocated AuthResponse struct, preferring placement in s's segment.
1857+func (s Authenticator_authenticate_Results) NewResp() (AuthResponse, error) {
1858+ ss, err := NewAuthResponse(s.Struct.Segment())
1859+ if err != nil {
1860+ return AuthResponse{}, err
1861+ }
1862+ err = s.Struct.SetPtr(0, ss.Struct.ToPtr())
1863+ return ss, err
1864+}
1865+
1866+// Authenticator_authenticate_Results_List is a list of Authenticator_authenticate_Results.
1867+type Authenticator_authenticate_Results_List struct{ capnp.List }
1868+
1869+// NewAuthenticator_authenticate_Results creates a new list of Authenticator_authenticate_Results.
1870+func NewAuthenticator_authenticate_Results_List(s *capnp.Segment, sz int32) (Authenticator_authenticate_Results_List, error) {
1871+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
1872+ return Authenticator_authenticate_Results_List{l}, err
1873+}
1874+
1875+func (s Authenticator_authenticate_Results_List) At(i int) Authenticator_authenticate_Results {
1876+ return Authenticator_authenticate_Results{s.List.Struct(i)}
1877+}
1878+
1879+func (s Authenticator_authenticate_Results_List) Set(i int, v Authenticator_authenticate_Results) error {
1880+ return s.List.SetStruct(i, v.Struct)
1881+}
1882+
1883+func (s Authenticator_authenticate_Results_List) String() string {
1884+ str, _ := text.MarshalList(0x96c07ce683897942, s.List)
1885+ return str
1886+}
1887+
1888+// Authenticator_authenticate_Results_Future is a wrapper for a Authenticator_authenticate_Results promised by a client call.
1889+type Authenticator_authenticate_Results_Future struct{ *capnp.Future }
1890+
1891+func (p Authenticator_authenticate_Results_Future) Struct() (Authenticator_authenticate_Results, error) {
1892+ s, err := p.Future.Struct()
1893+ return Authenticator_authenticate_Results{s}, err
1894+}
1895+
1896+func (p Authenticator_authenticate_Results_Future) Resp() AuthResponse_Future {
1897+ return AuthResponse_Future{Future: p.Future.Field(0, nil)}
1898+}
1899+
1900+type RegisterRequest struct{ capnp.Struct }
1901+
1902+// RegisterRequest_TypeID is the unique identifier for the type RegisterRequest.
1903+const RegisterRequest_TypeID = 0x8a21a43d866e69f4
1904+
1905+func NewRegisterRequest(s *capnp.Segment) (RegisterRequest, error) {
1906+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 6})
1907+ return RegisterRequest{st}, err
1908+}
1909+
1910+func NewRootRegisterRequest(s *capnp.Segment) (RegisterRequest, error) {
1911+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 6})
1912+ return RegisterRequest{st}, err
1913+}
1914+
1915+func ReadRootRegisterRequest(msg *capnp.Message) (RegisterRequest, error) {
1916+ root, err := msg.Root()
1917+ return RegisterRequest{root.Struct()}, err
1918+}
1919+
1920+func (s RegisterRequest) String() string {
1921+ str, _ := text.Marshal(0x8a21a43d866e69f4, s.Struct)
1922+ return str
1923+}
1924+
1925+func (s RegisterRequest) SystemId() (string, error) {
1926+ p, err := s.Struct.Ptr(0)
1927+ return p.Text(), err
1928+}
1929+
1930+func (s RegisterRequest) HasSystemId() bool {
1931+ return s.Struct.HasPtr(0)
1932+}
1933+
1934+func (s RegisterRequest) SystemIdBytes() ([]byte, error) {
1935+ p, err := s.Struct.Ptr(0)
1936+ return p.TextBytes(), err
1937+}
1938+
1939+func (s RegisterRequest) SetSystemId(v string) error {
1940+ return s.Struct.SetText(0, v)
1941+}
1942+
1943+func (s RegisterRequest) Hostname() (string, error) {
1944+ p, err := s.Struct.Ptr(1)
1945+ return p.Text(), err
1946+}
1947+
1948+func (s RegisterRequest) HasHostname() bool {
1949+ return s.Struct.HasPtr(1)
1950+}
1951+
1952+func (s RegisterRequest) HostnameBytes() ([]byte, error) {
1953+ p, err := s.Struct.Ptr(1)
1954+ return p.TextBytes(), err
1955+}
1956+
1957+func (s RegisterRequest) SetHostname(v string) error {
1958+ return s.Struct.SetText(1, v)
1959+}
1960+
1961+func (s RegisterRequest) Interfaces() (Interfaces, error) {
1962+ p, err := s.Struct.Ptr(2)
1963+ return Interfaces{Struct: p.Struct()}, err
1964+}
1965+
1966+func (s RegisterRequest) HasInterfaces() bool {
1967+ return s.Struct.HasPtr(2)
1968+}
1969+
1970+func (s RegisterRequest) SetInterfaces(v Interfaces) error {
1971+ return s.Struct.SetPtr(2, v.Struct.ToPtr())
1972+}
1973+
1974+// NewInterfaces sets the interfaces field to a newly
1975+// allocated Interfaces struct, preferring placement in s's segment.
1976+func (s RegisterRequest) NewInterfaces() (Interfaces, error) {
1977+ ss, err := NewInterfaces(s.Struct.Segment())
1978+ if err != nil {
1979+ return Interfaces{}, err
1980+ }
1981+ err = s.Struct.SetPtr(2, ss.Struct.ToPtr())
1982+ return ss, err
1983+}
1984+
1985+func (s RegisterRequest) Url() (string, error) {
1986+ p, err := s.Struct.Ptr(3)
1987+ return p.Text(), err
1988+}
1989+
1990+func (s RegisterRequest) HasUrl() bool {
1991+ return s.Struct.HasPtr(3)
1992+}
1993+
1994+func (s RegisterRequest) UrlBytes() ([]byte, error) {
1995+ p, err := s.Struct.Ptr(3)
1996+ return p.TextBytes(), err
1997+}
1998+
1999+func (s RegisterRequest) SetUrl(v string) error {
2000+ return s.Struct.SetText(3, v)
2001+}
2002+
2003+func (s RegisterRequest) Nodegroup() (string, error) {
2004+ p, err := s.Struct.Ptr(4)
2005+ return p.Text(), err
2006+}
2007+
2008+func (s RegisterRequest) HasNodegroup() bool {
2009+ return s.Struct.HasPtr(4)
2010+}
2011+
2012+func (s RegisterRequest) NodegroupBytes() ([]byte, error) {
2013+ p, err := s.Struct.Ptr(4)
2014+ return p.TextBytes(), err
2015+}
2016+
2017+func (s RegisterRequest) SetNodegroup(v string) error {
2018+ return s.Struct.SetText(4, v)
2019+}
2020+
2021+func (s RegisterRequest) BeaconSupport() bool {
2022+ return s.Struct.Bit(0)
2023+}
2024+
2025+func (s RegisterRequest) SetBeaconSupport(v bool) {
2026+ s.Struct.SetBit(0, v)
2027+}
2028+
2029+func (s RegisterRequest) Version() (string, error) {
2030+ p, err := s.Struct.Ptr(5)
2031+ return p.Text(), err
2032+}
2033+
2034+func (s RegisterRequest) HasVersion() bool {
2035+ return s.Struct.HasPtr(5)
2036+}
2037+
2038+func (s RegisterRequest) VersionBytes() ([]byte, error) {
2039+ p, err := s.Struct.Ptr(5)
2040+ return p.TextBytes(), err
2041+}
2042+
2043+func (s RegisterRequest) SetVersion(v string) error {
2044+ return s.Struct.SetText(5, v)
2045+}
2046+
2047+// RegisterRequest_List is a list of RegisterRequest.
2048+type RegisterRequest_List struct{ capnp.List }
2049+
2050+// NewRegisterRequest creates a new list of RegisterRequest.
2051+func NewRegisterRequest_List(s *capnp.Segment, sz int32) (RegisterRequest_List, error) {
2052+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 6}, sz)
2053+ return RegisterRequest_List{l}, err
2054+}
2055+
2056+func (s RegisterRequest_List) At(i int) RegisterRequest { return RegisterRequest{s.List.Struct(i)} }
2057+
2058+func (s RegisterRequest_List) Set(i int, v RegisterRequest) error {
2059+ return s.List.SetStruct(i, v.Struct)
2060+}
2061+
2062+func (s RegisterRequest_List) String() string {
2063+ str, _ := text.MarshalList(0x8a21a43d866e69f4, s.List)
2064+ return str
2065+}
2066+
2067+// RegisterRequest_Future is a wrapper for a RegisterRequest promised by a client call.
2068+type RegisterRequest_Future struct{ *capnp.Future }
2069+
2070+func (p RegisterRequest_Future) Struct() (RegisterRequest, error) {
2071+ s, err := p.Future.Struct()
2072+ return RegisterRequest{s}, err
2073+}
2074+
2075+func (p RegisterRequest_Future) Interfaces() Interfaces_Future {
2076+ return Interfaces_Future{Future: p.Future.Field(2, nil)}
2077+}
2078+
2079+type RegisterResponse struct{ capnp.Struct }
2080+
2081+// RegisterResponse_TypeID is the unique identifier for the type RegisterResponse.
2082+const RegisterResponse_TypeID = 0x971fe28893233a11
2083+
2084+func NewRegisterResponse(s *capnp.Segment) (RegisterResponse, error) {
2085+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 3})
2086+ return RegisterResponse{st}, err
2087+}
2088+
2089+func NewRootRegisterResponse(s *capnp.Segment) (RegisterResponse, error) {
2090+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 3})
2091+ return RegisterResponse{st}, err
2092+}
2093+
2094+func ReadRootRegisterResponse(msg *capnp.Message) (RegisterResponse, error) {
2095+ root, err := msg.Root()
2096+ return RegisterResponse{root.Struct()}, err
2097+}
2098+
2099+func (s RegisterResponse) String() string {
2100+ str, _ := text.Marshal(0x971fe28893233a11, s.Struct)
2101+ return str
2102+}
2103+
2104+func (s RegisterResponse) SystemId() (string, error) {
2105+ p, err := s.Struct.Ptr(0)
2106+ return p.Text(), err
2107+}
2108+
2109+func (s RegisterResponse) HasSystemId() bool {
2110+ return s.Struct.HasPtr(0)
2111+}
2112+
2113+func (s RegisterResponse) SystemIdBytes() ([]byte, error) {
2114+ p, err := s.Struct.Ptr(0)
2115+ return p.TextBytes(), err
2116+}
2117+
2118+func (s RegisterResponse) SetSystemId(v string) error {
2119+ return s.Struct.SetText(0, v)
2120+}
2121+
2122+func (s RegisterResponse) Uuid() (string, error) {
2123+ p, err := s.Struct.Ptr(1)
2124+ return p.Text(), err
2125+}
2126+
2127+func (s RegisterResponse) HasUuid() bool {
2128+ return s.Struct.HasPtr(1)
2129+}
2130+
2131+func (s RegisterResponse) UuidBytes() ([]byte, error) {
2132+ p, err := s.Struct.Ptr(1)
2133+ return p.TextBytes(), err
2134+}
2135+
2136+func (s RegisterResponse) SetUuid(v string) error {
2137+ return s.Struct.SetText(1, v)
2138+}
2139+
2140+func (s RegisterResponse) Version() (string, error) {
2141+ p, err := s.Struct.Ptr(2)
2142+ return p.Text(), err
2143+}
2144+
2145+func (s RegisterResponse) HasVersion() bool {
2146+ return s.Struct.HasPtr(2)
2147+}
2148+
2149+func (s RegisterResponse) VersionBytes() ([]byte, error) {
2150+ p, err := s.Struct.Ptr(2)
2151+ return p.TextBytes(), err
2152+}
2153+
2154+func (s RegisterResponse) SetVersion(v string) error {
2155+ return s.Struct.SetText(2, v)
2156+}
2157+
2158+// RegisterResponse_List is a list of RegisterResponse.
2159+type RegisterResponse_List struct{ capnp.List }
2160+
2161+// NewRegisterResponse creates a new list of RegisterResponse.
2162+func NewRegisterResponse_List(s *capnp.Segment, sz int32) (RegisterResponse_List, error) {
2163+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 3}, sz)
2164+ return RegisterResponse_List{l}, err
2165+}
2166+
2167+func (s RegisterResponse_List) At(i int) RegisterResponse { return RegisterResponse{s.List.Struct(i)} }
2168+
2169+func (s RegisterResponse_List) Set(i int, v RegisterResponse) error {
2170+ return s.List.SetStruct(i, v.Struct)
2171+}
2172+
2173+func (s RegisterResponse_List) String() string {
2174+ str, _ := text.MarshalList(0x971fe28893233a11, s.List)
2175+ return str
2176+}
2177+
2178+// RegisterResponse_Future is a wrapper for a RegisterResponse promised by a client call.
2179+type RegisterResponse_Future struct{ *capnp.Future }
2180+
2181+func (p RegisterResponse_Future) Struct() (RegisterResponse, error) {
2182+ s, err := p.Future.Struct()
2183+ return RegisterResponse{s}, err
2184+}
2185+
2186+type Registerer struct{ Client *capnp.Client }
2187+
2188+// Registerer_TypeID is the unique identifier for the type Registerer.
2189+const Registerer_TypeID = 0xe75723043cae2d20
2190+
2191+func (c Registerer) Register(ctx context.Context, params func(Registerer_register_Params) error) (Registerer_register_Results_Future, capnp.ReleaseFunc) {
2192+ s := capnp.Send{
2193+ Method: capnp.Method{
2194+ InterfaceID: 0xe75723043cae2d20,
2195+ MethodID: 0,
2196+ InterfaceName: "handshake.capnp:Registerer",
2197+ MethodName: "register",
2198+ },
2199+ }
2200+ if params != nil {
2201+ s.ArgsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1}
2202+ s.PlaceArgs = func(s capnp.Struct) error { return params(Registerer_register_Params{Struct: s}) }
2203+ }
2204+ ans, release := c.Client.SendCall(ctx, s)
2205+ return Registerer_register_Results_Future{Future: ans.Future()}, release
2206+}
2207+
2208+func (c Registerer) AddRef() Registerer {
2209+ return Registerer{
2210+ Client: c.Client.AddRef(),
2211+ }
2212+}
2213+
2214+func (c Registerer) Release() {
2215+ c.Client.Release()
2216+}
2217+
2218+// A Registerer_Server is a Registerer with a local implementation.
2219+type Registerer_Server interface {
2220+ Register(context.Context, Registerer_register) error
2221+}
2222+
2223+// Registerer_NewServer creates a new Server from an implementation of Registerer_Server.
2224+func Registerer_NewServer(s Registerer_Server, policy *server.Policy) *server.Server {
2225+ c, _ := s.(server.Shutdowner)
2226+ return server.New(Registerer_Methods(nil, s), s, c, policy)
2227+}
2228+
2229+// Registerer_ServerToClient creates a new Client from an implementation of Registerer_Server.
2230+// The caller is responsible for calling Release on the returned Client.
2231+func Registerer_ServerToClient(s Registerer_Server, policy *server.Policy) Registerer {
2232+ return Registerer{Client: capnp.NewClient(Registerer_NewServer(s, policy))}
2233+}
2234+
2235+// Registerer_Methods appends Methods to a slice that invoke the methods on s.
2236+// This can be used to create a more complicated Server.
2237+func Registerer_Methods(methods []server.Method, s Registerer_Server) []server.Method {
2238+ if cap(methods) == 0 {
2239+ methods = make([]server.Method, 0, 1)
2240+ }
2241+
2242+ methods = append(methods, server.Method{
2243+ Method: capnp.Method{
2244+ InterfaceID: 0xe75723043cae2d20,
2245+ MethodID: 0,
2246+ InterfaceName: "handshake.capnp:Registerer",
2247+ MethodName: "register",
2248+ },
2249+ Impl: func(ctx context.Context, call *server.Call) error {
2250+ return s.Register(ctx, Registerer_register{call})
2251+ },
2252+ })
2253+
2254+ return methods
2255+}
2256+
2257+// Registerer_register holds the state for a server call to Registerer.register.
2258+// See server.Call for documentation.
2259+type Registerer_register struct {
2260+ *server.Call
2261+}
2262+
2263+// Args returns the call's arguments.
2264+func (c Registerer_register) Args() Registerer_register_Params {
2265+ return Registerer_register_Params{Struct: c.Call.Args()}
2266+}
2267+
2268+// AllocResults allocates the results struct.
2269+func (c Registerer_register) AllocResults() (Registerer_register_Results, error) {
2270+ r, err := c.Call.AllocResults(capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2271+ return Registerer_register_Results{Struct: r}, err
2272+}
2273+
2274+type Registerer_register_Params struct{ capnp.Struct }
2275+
2276+// Registerer_register_Params_TypeID is the unique identifier for the type Registerer_register_Params.
2277+const Registerer_register_Params_TypeID = 0x80a0e6cbaa396ef4
2278+
2279+func NewRegisterer_register_Params(s *capnp.Segment) (Registerer_register_Params, error) {
2280+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2281+ return Registerer_register_Params{st}, err
2282+}
2283+
2284+func NewRootRegisterer_register_Params(s *capnp.Segment) (Registerer_register_Params, error) {
2285+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2286+ return Registerer_register_Params{st}, err
2287+}
2288+
2289+func ReadRootRegisterer_register_Params(msg *capnp.Message) (Registerer_register_Params, error) {
2290+ root, err := msg.Root()
2291+ return Registerer_register_Params{root.Struct()}, err
2292+}
2293+
2294+func (s Registerer_register_Params) String() string {
2295+ str, _ := text.Marshal(0x80a0e6cbaa396ef4, s.Struct)
2296+ return str
2297+}
2298+
2299+func (s Registerer_register_Params) Req() (RegisterRequest, error) {
2300+ p, err := s.Struct.Ptr(0)
2301+ return RegisterRequest{Struct: p.Struct()}, err
2302+}
2303+
2304+func (s Registerer_register_Params) HasReq() bool {
2305+ return s.Struct.HasPtr(0)
2306+}
2307+
2308+func (s Registerer_register_Params) SetReq(v RegisterRequest) error {
2309+ return s.Struct.SetPtr(0, v.Struct.ToPtr())
2310+}
2311+
2312+// NewReq sets the req field to a newly
2313+// allocated RegisterRequest struct, preferring placement in s's segment.
2314+func (s Registerer_register_Params) NewReq() (RegisterRequest, error) {
2315+ ss, err := NewRegisterRequest(s.Struct.Segment())
2316+ if err != nil {
2317+ return RegisterRequest{}, err
2318+ }
2319+ err = s.Struct.SetPtr(0, ss.Struct.ToPtr())
2320+ return ss, err
2321+}
2322+
2323+// Registerer_register_Params_List is a list of Registerer_register_Params.
2324+type Registerer_register_Params_List struct{ capnp.List }
2325+
2326+// NewRegisterer_register_Params creates a new list of Registerer_register_Params.
2327+func NewRegisterer_register_Params_List(s *capnp.Segment, sz int32) (Registerer_register_Params_List, error) {
2328+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
2329+ return Registerer_register_Params_List{l}, err
2330+}
2331+
2332+func (s Registerer_register_Params_List) At(i int) Registerer_register_Params {
2333+ return Registerer_register_Params{s.List.Struct(i)}
2334+}
2335+
2336+func (s Registerer_register_Params_List) Set(i int, v Registerer_register_Params) error {
2337+ return s.List.SetStruct(i, v.Struct)
2338+}
2339+
2340+func (s Registerer_register_Params_List) String() string {
2341+ str, _ := text.MarshalList(0x80a0e6cbaa396ef4, s.List)
2342+ return str
2343+}
2344+
2345+// Registerer_register_Params_Future is a wrapper for a Registerer_register_Params promised by a client call.
2346+type Registerer_register_Params_Future struct{ *capnp.Future }
2347+
2348+func (p Registerer_register_Params_Future) Struct() (Registerer_register_Params, error) {
2349+ s, err := p.Future.Struct()
2350+ return Registerer_register_Params{s}, err
2351+}
2352+
2353+func (p Registerer_register_Params_Future) Req() RegisterRequest_Future {
2354+ return RegisterRequest_Future{Future: p.Future.Field(0, nil)}
2355+}
2356+
2357+type Registerer_register_Results struct{ capnp.Struct }
2358+
2359+// Registerer_register_Results_TypeID is the unique identifier for the type Registerer_register_Results.
2360+const Registerer_register_Results_TypeID = 0xb5c83b347e16691c
2361+
2362+func NewRegisterer_register_Results(s *capnp.Segment) (Registerer_register_Results, error) {
2363+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2364+ return Registerer_register_Results{st}, err
2365+}
2366+
2367+func NewRootRegisterer_register_Results(s *capnp.Segment) (Registerer_register_Results, error) {
2368+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2369+ return Registerer_register_Results{st}, err
2370+}
2371+
2372+func ReadRootRegisterer_register_Results(msg *capnp.Message) (Registerer_register_Results, error) {
2373+ root, err := msg.Root()
2374+ return Registerer_register_Results{root.Struct()}, err
2375+}
2376+
2377+func (s Registerer_register_Results) String() string {
2378+ str, _ := text.Marshal(0xb5c83b347e16691c, s.Struct)
2379+ return str
2380+}
2381+
2382+func (s Registerer_register_Results) Resp() (RegisterResponse, error) {
2383+ p, err := s.Struct.Ptr(0)
2384+ return RegisterResponse{Struct: p.Struct()}, err
2385+}
2386+
2387+func (s Registerer_register_Results) HasResp() bool {
2388+ return s.Struct.HasPtr(0)
2389+}
2390+
2391+func (s Registerer_register_Results) SetResp(v RegisterResponse) error {
2392+ return s.Struct.SetPtr(0, v.Struct.ToPtr())
2393+}
2394+
2395+// NewResp sets the resp field to a newly
2396+// allocated RegisterResponse struct, preferring placement in s's segment.
2397+func (s Registerer_register_Results) NewResp() (RegisterResponse, error) {
2398+ ss, err := NewRegisterResponse(s.Struct.Segment())
2399+ if err != nil {
2400+ return RegisterResponse{}, err
2401+ }
2402+ err = s.Struct.SetPtr(0, ss.Struct.ToPtr())
2403+ return ss, err
2404+}
2405+
2406+// Registerer_register_Results_List is a list of Registerer_register_Results.
2407+type Registerer_register_Results_List struct{ capnp.List }
2408+
2409+// NewRegisterer_register_Results creates a new list of Registerer_register_Results.
2410+func NewRegisterer_register_Results_List(s *capnp.Segment, sz int32) (Registerer_register_Results_List, error) {
2411+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
2412+ return Registerer_register_Results_List{l}, err
2413+}
2414+
2415+func (s Registerer_register_Results_List) At(i int) Registerer_register_Results {
2416+ return Registerer_register_Results{s.List.Struct(i)}
2417+}
2418+
2419+func (s Registerer_register_Results_List) Set(i int, v Registerer_register_Results) error {
2420+ return s.List.SetStruct(i, v.Struct)
2421+}
2422+
2423+func (s Registerer_register_Results_List) String() string {
2424+ str, _ := text.MarshalList(0xb5c83b347e16691c, s.List)
2425+ return str
2426+}
2427+
2428+// Registerer_register_Results_Future is a wrapper for a Registerer_register_Results promised by a client call.
2429+type Registerer_register_Results_Future struct{ *capnp.Future }
2430+
2431+func (p Registerer_register_Results_Future) Struct() (Registerer_register_Results, error) {
2432+ s, err := p.Future.Struct()
2433+ return Registerer_register_Results{s}, err
2434+}
2435+
2436+func (p Registerer_register_Results_Future) Resp() RegisterResponse_Future {
2437+ return RegisterResponse_Future{Future: p.Future.Field(0, nil)}
2438+}
2439+
2440+const schema_dceab81b996ed67b = "x\xda\x8cTM\x88\x1cE\x18}\xaf\xaa\xbb'\x09\xbb" +
2441+ "\xcc\x14=zI\xe2F\xb3\x07W\xd8%\x92\x04qU" +
2442+ "6F%\xc9\xa2\xb8\xb51(\xb9uf\xca\xdd1;" +
2443+ "=\x93\xae\x1e%\xc6\x9f\x10QTPQ\xc1?<\x08" +
2444+ "\x8a\x82\x88z0\xa0\xa0\x12\xc1\xc0\x82\x04\x12\x10\x7f\xe2" +
2445+ "^\xa2!J\xc0\x8b\xe4\xe2AZj\xdc\xe9\xe9L\x0c" +
2446+ "\xd9[\xd7\xc7\xeb\xf7\xbd\xef\xbd\xaao\xd3Ub\x9b\xb8" +
2447+ "\xd1\xbf)\x00\xf4N?\xc8^\xfc\xe6\xd0\xa3\x1f\xfc\xb6" +
2448+ "\xe60TEf\x87~\x88\xdf\\\xfb\xf9\xf9%\x80!" +
2449+ "\xe5_\xe1\xb0,\x01\xe1j\xb9#\xdc\xea\xbe\xb2\x0b\xf1" +
2450+ "\xcd\x1f~w\xee\x9d\xc3Pk\x09\xf8,\x01\x9b\xd7\xcb" +
2451+ "\xbd\x04\xc319\x05f\x17\x1a\xf13\xb7\xbdw\xed\xf3" +
2452+ "\xd0\x15\xb2O\xe7\x07\x0e\xb9K\x0a\x86{\x1c\xd1f-" +
2453+ "_\"\x98m?\xf8\xdcS\xe7\x1e;\xf6\x1a\xd459" +
2454+ "\xdf\x9f\xde[\x8e\xef\x1f\xcf\xf1\xa9\xc9\x8d\xaf>\xfb\xeb" +
2455+ "\xc8\xebP\x95\"]\x97c\xbd\xbf\x86\xe1\xb8\xef\x14\x8e" +
2456+ "\xf9\x9f\x80\xd9\x99\xb3\x1b~<2\xf5\xe9\x1b\x03`\xe1" +
2457+ "\x10\xc7\xfd\xf3\xe1\xa9.\xf6\x84\xff\x08\x98\xadk\\\xfd" +
2458+ "\xc4\x96[\x16\x8f\x16'\x19\x0b\xf6\xb9\xce[\x03\xd7y" +
2459+ "\xf7\xfb\xd9\xe9\xaf\xdf\xfd\xe8\x97\xa2\xb4=\xc1+\x0e`" +
2460+ "\xba\x80\x0d\xe3\x1f\xdf\xeam\xbc\xff\xf7K\x8c{:8" +
2461+ "\x1d\xbe\xec\x06\x0e_\x08v\x84_\x04%\xd4\xb2\xf9(" +
2462+ "\xae\xdb\xf9h\xbf0\x13\xb5\xa8\x1d\xb7'o\xef\xa4\xf3" +
2463+ "&N\x1b#\xb5(m%3\xa4\xf6\xa4\x0f\xe4m\xd9" +
2464+ "\xb3F\xa9\x87 \xd4\xeaR\x16-\xff\x81r-J\xcd" +
2465+ "6\xce\x909\xad\xd7\xa3\x9d5s\x0d\x9b\x9a\xc4$\x13" +
2466+ "\xc9\xf2\xe7\xe8L\x94D\xb2i\xb5'=\xc0#\xa0\x86" +
2467+ "\xaf\x03\xf4*I]\x15,%\xe6\x00+\xfd\xe0@V" +
2468+ "\xd0g\x96\x83\xcc\xb3\xe6@\xc7\xd8\x14N\xf2\xba\x9c\xf1" +
2469+ "\xe84\xa0?\x93\xd4\xc7\x04\x15Y\xa5+~\xe5\x8a_" +
2470+ "J\xeaEA%D\x95\x02P\xc7\xf7\x02\xfa[I}" +
2471+ "RPIY\xa5\x04\xd4\x09'hQR\x7f/\xa8<" +
2472+ "\xafJ\x0fP\xa7f\x01}RR/\x09\xd2\xaf\xd2\x07" +
2473+ "\xd4\xcf\x09\xa0\x7f\x92\xd4g\x05U\xe0W\x19\x00\xea\xcc" +
2474+ "v@/I\xea?\x043{\xd0\xa6\xa6\xb9\xab\x0e\x80" +
2475+ "C\x10\x1cr\xc3\xb4l\x1aGMS\xac5\xe2\xd4$" +
2476+ "\x0fF5HcY\xc9\xee\x98~\xfc\xef{\xdf\xde\x7f" +
2477+ "dy\xfeR'Y\xc8\xa1q\xabn\xe6\x92V\x07l" +
2478+ "\xe7\xb5}&\xaa\xb5\xe2\xdd\x1d\x8c\xb4\xdb\xad$%!" +
2479+ "H\xf0\xc9\x87Mb\x1b\xad\xb8\xdfz\xd9G\x7f0\xf8" +
2480+ "n\xee\x13Q\xffdFg\x8d\xed,\xc8\xf4\xa2\xa4n" +
2481+ "\xe8'UN\x8cm\xb3\xd2\xbf\xe6W\x8e\xca\xb6[\xb1" +
2482+ "5\xe8\x865\x94\x93\xde\xe5r\xb9SR\xcf\x14\xc2\xba" +
2483+ "\xc7u\xda)\xa9\xef+\x84\xa5\x9d\xb3wK\xea\x07\xfe" +
2484+ "\xdf\xd9r\xa7\xd3\xa8\xf7\x0e\x97\x9d\xfd\xa2K\xefD\x95" +
2485+ "\x9d*\xa7iU\xaei\xcc\xb5\x1f\x95\xd4\x9b\x0a\x9a\xc6" +
2486+ "'\x01}\xbd\xa4\xde\"X\xb6\xd1B\xcaa\x08\x0e\x83" +
2487+ "S\xf5\xc6\x9c\xb1\xf9qe\xef\xc0\xd9[Z\xb8\xa2\xbd" +
2488+ "\xf9\xca\x19\xb0w%\x09\xba\xa7\xd6\xe4e\x9fZ\xd3\xce" +
2489+ "]\"Y\x0cJ\x96\xa6\xb0\x0ez\x0b\x97\xbd}\xa5\xd4" +
2490+ "\xf4\x7f\xeb\xa07\x16\x80\xee.\xf87\x00\x00\xff\xff\x86" +
2491+ "\xdc\x84m"
2492+
2493+func init() {
2494+ schemas.Register(schema_dceab81b996ed67b,
2495+ 0x800ae3a77a7bc18e,
2496+ 0x80a0e6cbaa396ef4,
2497+ 0x8a21a43d866e69f4,
2498+ 0x96c07ce683897942,
2499+ 0x971fe28893233a11,
2500+ 0x98b03f82d720e4e1,
2501+ 0xb5c83b347e16691c,
2502+ 0xdbaca3bedaffa653,
2503+ 0xe75723043cae2d20)
2504+}
2505diff --git a/src/rackd_spike/pkg/rpc/network.capnp.go b/src/rackd_spike/pkg/rpc/network.capnp.go
2506new file mode 100644
2507index 0000000..4101c19
2508--- /dev/null
2509+++ b/src/rackd_spike/pkg/rpc/network.capnp.go
2510@@ -0,0 +1,489 @@
2511+// Code generated by capnpc-go. DO NOT EDIT.
2512+
2513+package rpc
2514+
2515+import (
2516+ capnp "capnproto.org/go/capnp/v3"
2517+ text "capnproto.org/go/capnp/v3/encoding/text"
2518+ schemas "capnproto.org/go/capnp/v3/schemas"
2519+)
2520+
2521+type Link struct{ capnp.Struct }
2522+
2523+// Link_TypeID is the unique identifier for the type Link.
2524+const Link_TypeID = 0xc7251b7c2c125e6e
2525+
2526+func NewLink(s *capnp.Segment) (Link, error) {
2527+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 3})
2528+ return Link{st}, err
2529+}
2530+
2531+func NewRootLink(s *capnp.Segment) (Link, error) {
2532+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 3})
2533+ return Link{st}, err
2534+}
2535+
2536+func ReadRootLink(msg *capnp.Message) (Link, error) {
2537+ root, err := msg.Root()
2538+ return Link{root.Struct()}, err
2539+}
2540+
2541+func (s Link) String() string {
2542+ str, _ := text.Marshal(0xc7251b7c2c125e6e, s.Struct)
2543+ return str
2544+}
2545+
2546+func (s Link) Mode() (string, error) {
2547+ p, err := s.Struct.Ptr(0)
2548+ return p.Text(), err
2549+}
2550+
2551+func (s Link) HasMode() bool {
2552+ return s.Struct.HasPtr(0)
2553+}
2554+
2555+func (s Link) ModeBytes() ([]byte, error) {
2556+ p, err := s.Struct.Ptr(0)
2557+ return p.TextBytes(), err
2558+}
2559+
2560+func (s Link) SetMode(v string) error {
2561+ return s.Struct.SetText(0, v)
2562+}
2563+
2564+func (s Link) Address() (string, error) {
2565+ p, err := s.Struct.Ptr(1)
2566+ return p.Text(), err
2567+}
2568+
2569+func (s Link) HasAddress() bool {
2570+ return s.Struct.HasPtr(1)
2571+}
2572+
2573+func (s Link) AddressBytes() ([]byte, error) {
2574+ p, err := s.Struct.Ptr(1)
2575+ return p.TextBytes(), err
2576+}
2577+
2578+func (s Link) SetAddress(v string) error {
2579+ return s.Struct.SetText(1, v)
2580+}
2581+
2582+func (s Link) Gateway() (string, error) {
2583+ p, err := s.Struct.Ptr(2)
2584+ return p.Text(), err
2585+}
2586+
2587+func (s Link) HasGateway() bool {
2588+ return s.Struct.HasPtr(2)
2589+}
2590+
2591+func (s Link) GatewayBytes() ([]byte, error) {
2592+ p, err := s.Struct.Ptr(2)
2593+ return p.TextBytes(), err
2594+}
2595+
2596+func (s Link) SetGateway(v string) error {
2597+ return s.Struct.SetText(2, v)
2598+}
2599+
2600+func (s Link) Netmask() int32 {
2601+ return int32(s.Struct.Uint32(0))
2602+}
2603+
2604+func (s Link) SetNetmask(v int32) {
2605+ s.Struct.SetUint32(0, uint32(v))
2606+}
2607+
2608+// Link_List is a list of Link.
2609+type Link_List struct{ capnp.List }
2610+
2611+// NewLink creates a new list of Link.
2612+func NewLink_List(s *capnp.Segment, sz int32) (Link_List, error) {
2613+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 3}, sz)
2614+ return Link_List{l}, err
2615+}
2616+
2617+func (s Link_List) At(i int) Link { return Link{s.List.Struct(i)} }
2618+
2619+func (s Link_List) Set(i int, v Link) error { return s.List.SetStruct(i, v.Struct) }
2620+
2621+func (s Link_List) String() string {
2622+ str, _ := text.MarshalList(0xc7251b7c2c125e6e, s.List)
2623+ return str
2624+}
2625+
2626+// Link_Future is a wrapper for a Link promised by a client call.
2627+type Link_Future struct{ *capnp.Future }
2628+
2629+func (p Link_Future) Struct() (Link, error) {
2630+ s, err := p.Future.Struct()
2631+ return Link{s}, err
2632+}
2633+
2634+type InterfaceDetails struct{ capnp.Struct }
2635+
2636+// InterfaceDetails_TypeID is the unique identifier for the type InterfaceDetails.
2637+const InterfaceDetails_TypeID = 0xca5e2a006234f169
2638+
2639+func NewInterfaceDetails(s *capnp.Segment) (InterfaceDetails, error) {
2640+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 4})
2641+ return InterfaceDetails{st}, err
2642+}
2643+
2644+func NewRootInterfaceDetails(s *capnp.Segment) (InterfaceDetails, error) {
2645+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 16, PointerCount: 4})
2646+ return InterfaceDetails{st}, err
2647+}
2648+
2649+func ReadRootInterfaceDetails(msg *capnp.Message) (InterfaceDetails, error) {
2650+ root, err := msg.Root()
2651+ return InterfaceDetails{root.Struct()}, err
2652+}
2653+
2654+func (s InterfaceDetails) String() string {
2655+ str, _ := text.Marshal(0xca5e2a006234f169, s.Struct)
2656+ return str
2657+}
2658+
2659+func (s InterfaceDetails) MacAddress() (string, error) {
2660+ p, err := s.Struct.Ptr(0)
2661+ return p.Text(), err
2662+}
2663+
2664+func (s InterfaceDetails) HasMacAddress() bool {
2665+ return s.Struct.HasPtr(0)
2666+}
2667+
2668+func (s InterfaceDetails) MacAddressBytes() ([]byte, error) {
2669+ p, err := s.Struct.Ptr(0)
2670+ return p.TextBytes(), err
2671+}
2672+
2673+func (s InterfaceDetails) SetMacAddress(v string) error {
2674+ return s.Struct.SetText(0, v)
2675+}
2676+
2677+func (s InterfaceDetails) Type() (string, error) {
2678+ p, err := s.Struct.Ptr(1)
2679+ return p.Text(), err
2680+}
2681+
2682+func (s InterfaceDetails) HasType() bool {
2683+ return s.Struct.HasPtr(1)
2684+}
2685+
2686+func (s InterfaceDetails) TypeBytes() ([]byte, error) {
2687+ p, err := s.Struct.Ptr(1)
2688+ return p.TextBytes(), err
2689+}
2690+
2691+func (s InterfaceDetails) SetType(v string) error {
2692+ return s.Struct.SetText(1, v)
2693+}
2694+
2695+func (s InterfaceDetails) Links() (Link_List, error) {
2696+ p, err := s.Struct.Ptr(2)
2697+ return Link_List{List: p.List()}, err
2698+}
2699+
2700+func (s InterfaceDetails) HasLinks() bool {
2701+ return s.Struct.HasPtr(2)
2702+}
2703+
2704+func (s InterfaceDetails) SetLinks(v Link_List) error {
2705+ return s.Struct.SetPtr(2, v.List.ToPtr())
2706+}
2707+
2708+// NewLinks sets the links field to a newly
2709+// allocated Link_List, preferring placement in s's segment.
2710+func (s InterfaceDetails) NewLinks(n int32) (Link_List, error) {
2711+ l, err := NewLink_List(s.Struct.Segment(), n)
2712+ if err != nil {
2713+ return Link_List{}, err
2714+ }
2715+ err = s.Struct.SetPtr(2, l.List.ToPtr())
2716+ return l, err
2717+}
2718+
2719+func (s InterfaceDetails) Vid() uint64 {
2720+ return s.Struct.Uint64(0)
2721+}
2722+
2723+func (s InterfaceDetails) SetVid(v uint64) {
2724+ s.Struct.SetUint64(0, v)
2725+}
2726+
2727+func (s InterfaceDetails) Enabled() bool {
2728+ return s.Struct.Bit(64)
2729+}
2730+
2731+func (s InterfaceDetails) SetEnabled(v bool) {
2732+ s.Struct.SetBit(64, v)
2733+}
2734+
2735+func (s InterfaceDetails) Parents() (capnp.TextList, error) {
2736+ p, err := s.Struct.Ptr(3)
2737+ return capnp.TextList{List: p.List()}, err
2738+}
2739+
2740+func (s InterfaceDetails) HasParents() bool {
2741+ return s.Struct.HasPtr(3)
2742+}
2743+
2744+func (s InterfaceDetails) SetParents(v capnp.TextList) error {
2745+ return s.Struct.SetPtr(3, v.List.ToPtr())
2746+}
2747+
2748+// NewParents sets the parents field to a newly
2749+// allocated capnp.TextList, preferring placement in s's segment.
2750+func (s InterfaceDetails) NewParents(n int32) (capnp.TextList, error) {
2751+ l, err := capnp.NewTextList(s.Struct.Segment(), n)
2752+ if err != nil {
2753+ return capnp.TextList{}, err
2754+ }
2755+ err = s.Struct.SetPtr(3, l.List.ToPtr())
2756+ return l, err
2757+}
2758+
2759+// InterfaceDetails_List is a list of InterfaceDetails.
2760+type InterfaceDetails_List struct{ capnp.List }
2761+
2762+// NewInterfaceDetails creates a new list of InterfaceDetails.
2763+func NewInterfaceDetails_List(s *capnp.Segment, sz int32) (InterfaceDetails_List, error) {
2764+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 16, PointerCount: 4}, sz)
2765+ return InterfaceDetails_List{l}, err
2766+}
2767+
2768+func (s InterfaceDetails_List) At(i int) InterfaceDetails { return InterfaceDetails{s.List.Struct(i)} }
2769+
2770+func (s InterfaceDetails_List) Set(i int, v InterfaceDetails) error {
2771+ return s.List.SetStruct(i, v.Struct)
2772+}
2773+
2774+func (s InterfaceDetails_List) String() string {
2775+ str, _ := text.MarshalList(0xca5e2a006234f169, s.List)
2776+ return str
2777+}
2778+
2779+// InterfaceDetails_Future is a wrapper for a InterfaceDetails promised by a client call.
2780+type InterfaceDetails_Future struct{ *capnp.Future }
2781+
2782+func (p InterfaceDetails_Future) Struct() (InterfaceDetails, error) {
2783+ s, err := p.Future.Struct()
2784+ return InterfaceDetails{s}, err
2785+}
2786+
2787+type Interface struct{ capnp.Struct }
2788+
2789+// Interface_TypeID is the unique identifier for the type Interface.
2790+const Interface_TypeID = 0x929a2663d1c662e2
2791+
2792+func NewInterface(s *capnp.Segment) (Interface, error) {
2793+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2})
2794+ return Interface{st}, err
2795+}
2796+
2797+func NewRootInterface(s *capnp.Segment) (Interface, error) {
2798+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2})
2799+ return Interface{st}, err
2800+}
2801+
2802+func ReadRootInterface(msg *capnp.Message) (Interface, error) {
2803+ root, err := msg.Root()
2804+ return Interface{root.Struct()}, err
2805+}
2806+
2807+func (s Interface) String() string {
2808+ str, _ := text.Marshal(0x929a2663d1c662e2, s.Struct)
2809+ return str
2810+}
2811+
2812+func (s Interface) Name() (string, error) {
2813+ p, err := s.Struct.Ptr(0)
2814+ return p.Text(), err
2815+}
2816+
2817+func (s Interface) HasName() bool {
2818+ return s.Struct.HasPtr(0)
2819+}
2820+
2821+func (s Interface) NameBytes() ([]byte, error) {
2822+ p, err := s.Struct.Ptr(0)
2823+ return p.TextBytes(), err
2824+}
2825+
2826+func (s Interface) SetName(v string) error {
2827+ return s.Struct.SetText(0, v)
2828+}
2829+
2830+func (s Interface) Iface() (InterfaceDetails, error) {
2831+ p, err := s.Struct.Ptr(1)
2832+ return InterfaceDetails{Struct: p.Struct()}, err
2833+}
2834+
2835+func (s Interface) HasIface() bool {
2836+ return s.Struct.HasPtr(1)
2837+}
2838+
2839+func (s Interface) SetIface(v InterfaceDetails) error {
2840+ return s.Struct.SetPtr(1, v.Struct.ToPtr())
2841+}
2842+
2843+// NewIface sets the iface field to a newly
2844+// allocated InterfaceDetails struct, preferring placement in s's segment.
2845+func (s Interface) NewIface() (InterfaceDetails, error) {
2846+ ss, err := NewInterfaceDetails(s.Struct.Segment())
2847+ if err != nil {
2848+ return InterfaceDetails{}, err
2849+ }
2850+ err = s.Struct.SetPtr(1, ss.Struct.ToPtr())
2851+ return ss, err
2852+}
2853+
2854+// Interface_List is a list of Interface.
2855+type Interface_List struct{ capnp.List }
2856+
2857+// NewInterface creates a new list of Interface.
2858+func NewInterface_List(s *capnp.Segment, sz int32) (Interface_List, error) {
2859+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz)
2860+ return Interface_List{l}, err
2861+}
2862+
2863+func (s Interface_List) At(i int) Interface { return Interface{s.List.Struct(i)} }
2864+
2865+func (s Interface_List) Set(i int, v Interface) error { return s.List.SetStruct(i, v.Struct) }
2866+
2867+func (s Interface_List) String() string {
2868+ str, _ := text.MarshalList(0x929a2663d1c662e2, s.List)
2869+ return str
2870+}
2871+
2872+// Interface_Future is a wrapper for a Interface promised by a client call.
2873+type Interface_Future struct{ *capnp.Future }
2874+
2875+func (p Interface_Future) Struct() (Interface, error) {
2876+ s, err := p.Future.Struct()
2877+ return Interface{s}, err
2878+}
2879+
2880+func (p Interface_Future) Iface() InterfaceDetails_Future {
2881+ return InterfaceDetails_Future{Future: p.Future.Field(1, nil)}
2882+}
2883+
2884+type Interfaces struct{ capnp.Struct }
2885+
2886+// Interfaces_TypeID is the unique identifier for the type Interfaces.
2887+const Interfaces_TypeID = 0x826b9c4ff97d4a43
2888+
2889+func NewInterfaces(s *capnp.Segment) (Interfaces, error) {
2890+ st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2891+ return Interfaces{st}, err
2892+}
2893+
2894+func NewRootInterfaces(s *capnp.Segment) (Interfaces, error) {
2895+ st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
2896+ return Interfaces{st}, err
2897+}
2898+
2899+func ReadRootInterfaces(msg *capnp.Message) (Interfaces, error) {
2900+ root, err := msg.Root()
2901+ return Interfaces{root.Struct()}, err
2902+}
2903+
2904+func (s Interfaces) String() string {
2905+ str, _ := text.Marshal(0x826b9c4ff97d4a43, s.Struct)
2906+ return str
2907+}
2908+
2909+func (s Interfaces) Ifaces() (Interface_List, error) {
2910+ p, err := s.Struct.Ptr(0)
2911+ return Interface_List{List: p.List()}, err
2912+}
2913+
2914+func (s Interfaces) HasIfaces() bool {
2915+ return s.Struct.HasPtr(0)
2916+}
2917+
2918+func (s Interfaces) SetIfaces(v Interface_List) error {
2919+ return s.Struct.SetPtr(0, v.List.ToPtr())
2920+}
2921+
2922+// NewIfaces sets the ifaces field to a newly
2923+// allocated Interface_List, preferring placement in s's segment.
2924+func (s Interfaces) NewIfaces(n int32) (Interface_List, error) {
2925+ l, err := NewInterface_List(s.Struct.Segment(), n)
2926+ if err != nil {
2927+ return Interface_List{}, err
2928+ }
2929+ err = s.Struct.SetPtr(0, l.List.ToPtr())
2930+ return l, err
2931+}
2932+
2933+// Interfaces_List is a list of Interfaces.
2934+type Interfaces_List struct{ capnp.List }
2935+
2936+// NewInterfaces creates a new list of Interfaces.
2937+func NewInterfaces_List(s *capnp.Segment, sz int32) (Interfaces_List, error) {
2938+ l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
2939+ return Interfaces_List{l}, err
2940+}
2941+
2942+func (s Interfaces_List) At(i int) Interfaces { return Interfaces{s.List.Struct(i)} }
2943+
2944+func (s Interfaces_List) Set(i int, v Interfaces) error { return s.List.SetStruct(i, v.Struct) }
2945+
2946+func (s Interfaces_List) String() string {
2947+ str, _ := text.MarshalList(0x826b9c4ff97d4a43, s.List)
2948+ return str
2949+}
2950+
2951+// Interfaces_Future is a wrapper for a Interfaces promised by a client call.
2952+type Interfaces_Future struct{ *capnp.Future }
2953+
2954+func (p Interfaces_Future) Struct() (Interfaces, error) {
2955+ s, err := p.Future.Struct()
2956+ return Interfaces{s}, err
2957+}
2958+
2959+const schema_dae346a935a6f239 = "x\xda|\x921h\x14O\x18\xc5\xdf\x9b\xd9\xfb'\x81" +
2960+ "\xfc/\xb7\xde\x15\x82\x85\"Q4\x18\x89\x1a\x0b\xd3$" +
2961+ "F\x11\"\x82\xf9\x0a\x11D\x82\x93\xdb\xd1,w\xb79" +
2962+ "\xee\x16C@9\x14,l\xad4\xa4PP\xd1\xde\xc2" +
2963+ "@\x04#j \x9d\x9d\xd8\xa9\x88X\x89v\xda\xac\xcc" +
2964+ "\x06\xf7\x16A\xbb\x9d\xc7o\xbf\xf7\xde|32\xc9\x09" +
2965+ "u\xa0\xb0\xae\x00\xd9Q\xf8/9v\xf2\xea\x8f\xd3\xcb" +
2966+ "\xb5\xeb\xf0\x8bL\x8e|\x7fx\xf8\xf1\x89\x8f\xefP`" +
2967+ "\x0fP\x9e\xe2F\xf9L\xfa%\x1c\x07\x93\x0f\xb3\xaf\xdf" +
2968+ "Tw/\xdd\xfa\x83U\x8e\xb8\xc6\x17\xe5\x9b){\x83" +
2969+ "\x0b`\x12\xcdl\xd9we\xdb\xaeuH\x91yX;" +
2970+ "\xe4=\x97\xca_R\xf8\x13?\x83_\xc3o\xa3\xb3C" +
2971+ "3\x1bR\xa4\xca\xa1\x9e\x03V\xd4\xcf\xf2+\xe7ph" +
2972+ "M\x9d%\x86\x93\xc8\xc6\x0b\xf3\xad\xda~U5\xcd\xa8" +
2973+ "96\x15\xc5\xb6u\xd1Tm\x1b\x98&\xc5\xd3\x1e\xe0" +
2974+ "\x11\xf0\xff\x1f\x03\xa4WS\x06\x15\xc7\xc3\x14a\x11\x9c" +
2975+ "\xd6d\xa9[\x05t\xe2_\xa7\xa63{\xb3\x99{\x87" +
2976+ "\x00\x19\xd4\x94\x11E\x9f\xac\xd0\x89\xc3\x07\x01\xd9\xa3)" +
2977+ "\xa3\x8a\x03\x91iX\xf6C\xb1\x1f\xdc\x9e\xba\xb2\xf4\xbb" +
2978+ "\x1f\xc8R\xce\x8b\x9b^\xa7B\x1d\xd5\x9cM)\xb31" +
2979+ "\xce\xe6\xbc\xa6\xcc\xe5l\xec$ \x174\xa5\xae\xe8+" +
2980+ "U\xa1\x02\xfc\xd0\x89\x81\xa64\x15\xa9+\xd4\x80\xdfp" +
2981+ "\xda\x9c\xa6\xc4\x8a\x03\x8d\xf9 \xcb\xd31A\xd0\xb2\xed" +
2982+ "vv\xbedb\xbb`\x16\xb3sd\xe3\x86i\xd7\xe8" +
2983+ "A\xd1\xfb\xc7\xad\x1c\x1f\xb7\xb1\x09\xebm\x97zk\x96" +
2984+ "\xfa\xce9@nk\xca\xfd\\\xea{\xae\xca\xb2\xa6<" +
2985+ "\xca\xa5~\xe0n\xec\xae\xa6\xacvS\xaf\xec\x04\xe4\x89" +
2986+ "\xa6<W\xf4\xbd\x89\x0a=\xc0\x7f\xe6\xaa<\xd5\x94\x97" +
2987+ "\x8a~AWX\x00\xfc5'\xaej\xca[\xc5\xa4a" +
2988+ "\xaaG]+\xe8n\xaf\x81x\xb1\xd9]B=\x8cj" +
2989+ "\xb9\xcdg\x0fss\xf3=\x97\xc3\x80}P\xec\x03;" +
2990+ "62\xb3u\x1b\x90P$\xd8i\x9a\x96\x8d\xe2\xecg" +
2991+ "7\xb1\x08\xfe\x0a\x00\x00\xff\xff\x8c{\xba\xe7"
2992+
2993+func init() {
2994+ schemas.Register(schema_dae346a935a6f239,
2995+ 0x826b9c4ff97d4a43,
2996+ 0x929a2663d1c662e2,
2997+ 0xc7251b7c2c125e6e,
2998+ 0xca5e2a006234f169)
2999+}
3000diff --git a/src/rpc/go.capnp b/src/rpc/go.capnp
3001new file mode 100644
3002index 0000000..4072b57
3003--- /dev/null
3004+++ b/src/rpc/go.capnp
3005@@ -0,0 +1,27 @@
3006+@0xd12a1c51fedd6c88;
3007+
3008+annotation package(file) :Text;
3009+# The Go package name for the generated file.
3010+
3011+annotation import(file) :Text;
3012+# The Go import path that the generated file is accessible from.
3013+# Used to generate import statements and check if two types are in the
3014+# same package.
3015+
3016+annotation doc(struct, field, enum) :Text;
3017+# Adds a doc comment to the generated code.
3018+
3019+annotation tag(enumerant) :Text;
3020+# Changes the string representation of the enum in the generated code.
3021+
3022+annotation notag(enumerant) :Void;
3023+# Removes the string representation of the enum in the generated code.
3024+
3025+annotation customtype(field) :Text;
3026+# OBSOLETE, not used by code generator.
3027+
3028+annotation name(struct, field, union, enum, enumerant, interface, method, param, annotation, const, group) :Text;
3029+# Used to rename the element in the generated code.
3030+
3031+$package("gocp");
3032+$import("capnproto.org/go/capnp/v3/std/go");
3033diff --git a/src/rpc/handshake.capnp b/src/rpc/handshake.capnp
3034new file mode 100644
3035index 0000000..dc87b67
3036--- /dev/null
3037+++ b/src/rpc/handshake.capnp
3038@@ -0,0 +1,36 @@
3039+@0xdceab81b996ed67b;
3040+
3041+using Go = import "go.capnp";
3042+$Go.package("rpc");
3043+$Go.import("rpc");
3044+
3045+using Network = import "network.capnp";
3046+
3047+struct AuthResponse {
3048+ salt @0 :Data;
3049+ digest @1 :Data;
3050+}
3051+
3052+interface Authenticator {
3053+ authenticate @0 (msg :Data) -> (resp :AuthResponse);
3054+}
3055+
3056+struct RegisterRequest {
3057+ systemId @0 :Text;
3058+ hostname @1 :Text;
3059+ interfaces @2 :Network.Interfaces;
3060+ url @3 :Text;
3061+ nodegroup @4 :Text;
3062+ beaconSupport @5 :Bool;
3063+ version @6 :Text;
3064+}
3065+
3066+struct RegisterResponse {
3067+ systemId @0 :Text;
3068+ uuid @1 :Text;
3069+ version @2 :Text;
3070+}
3071+
3072+interface Registerer {
3073+ register @0 (req :RegisterRequest) -> (resp :RegisterResponse);
3074+}
3075diff --git a/src/rpc/network.capnp b/src/rpc/network.capnp
3076new file mode 100644
3077index 0000000..5e719c9
3078--- /dev/null
3079+++ b/src/rpc/network.capnp
3080@@ -0,0 +1,30 @@
3081+@0xdae346a935a6f239;
3082+
3083+using Go = import "go.capnp";
3084+$Go.package("rpc");
3085+$Go.import("rpc");
3086+
3087+struct Link {
3088+ mode @0 :Text;
3089+ address @1 :Text;
3090+ gateway @2 :Text;
3091+ netmask @3 :Int32;
3092+}
3093+
3094+struct InterfaceDetails {
3095+ macAddress @0 :Text;
3096+ type @1 :Text;
3097+ links @2 :List(Link);
3098+ vid @3 :UInt64;
3099+ enabled @4 :Bool;
3100+ parents @5 :List(Text);
3101+}
3102+
3103+struct Interface {
3104+ name @0 :Text;
3105+ iface @1 :InterfaceDetails;
3106+}
3107+
3108+struct Interfaces {
3109+ ifaces @0 :List(Interface);
3110+}

Subscribers

People subscribed via source and target branches