Skip to content
This repository was archived by the owner on Jul 7, 2024. It is now read-only.

Commit 41e8ed7

Browse files
committed
backport for node
1 parent 0f522b4 commit 41e8ed7

File tree

6 files changed

+99
-2
lines changed

6 files changed

+99
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Flakes are recommended. See `flake.nix` for options.
4242

4343
## TODO
4444

45-
- node: wg config persistent over reboot, etc (change only when cs requests so, or when wg conn fails?)
45+
- node: test node backport (in test.nix)
4646
- confine qrystal-node and qrystal-cs (using systemd's options)
4747
- configure existing interfaces without disrupting connections (as much as possible)
4848
- support multiple hosts

cmd/runner-node/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"log"
77
"os"
8+
"path/filepath"
89
"regexp"
910

1011
"crypto/tls"
@@ -128,6 +129,7 @@ func main() {
128129
HokutoDNSParent: c.Hokuto.Parent,
129130
HokutoExtraParents: c.Hokuto.ExtraParents,
130131
EndpointOverride: c.EndpointOverride,
132+
BackportPath: filepath.Join(os.Getenv("STATE_DIRECTORY"), "node-backport.json"),
131133
}
132134
if os.Getenv("HOKUTO_ADDR") != "" {
133135
nc.HokutoAddr = os.Getenv("HOKUTO_ADDR")
@@ -141,5 +143,9 @@ func main() {
141143
panic(err)
142144
}
143145

146+
err = n.LoadBackport()
147+
if err != nil {
148+
util.S.Errorf("load backport: %s", err)
149+
}
144150
n.ListenCS()
145151
}

node/api.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,15 @@ func (n *Node) setupClient(cl *rpc2.Client) {
7474
return fmt.Errorf("updateHokutoCC: %w", err)
7575
}
7676
cns := new(strings.Builder)
77-
for cnn, cn := range n.cc.Networks {
77+
for cnn := range n.cc.Networks {
7878
fmt.Fprintf(cns, " %s", cnn)
7979
}
8080
util.Notify(fmt.Sprintf("STATUS=Synced. CNs:%s", cns))
8181
util.Notify("READY=1")
82+
err = n.saveBackport()
83+
if err != nil {
84+
util.S.Errorf("save backport: %s", err)
85+
}
8286
n.traceCheck()
8387
return nil
8488
})

node/backport.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package node
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
7+
"github.com/nyiyui/qrystal/central"
8+
)
9+
10+
type Backport struct {
11+
CC *central.Config `json:"cc"`
12+
}
13+
14+
// LoadBackport reads a backport from the path and applies it if CC exists in the backport.
15+
// This must not be called after Node.ListenCS.
16+
func (n *Node) LoadBackport() error {
17+
encoded, err := os.ReadFile(n.backportPath)
18+
if err != nil {
19+
return err
20+
}
21+
var b Backport
22+
err = json.Unmarshal(encoded, &b)
23+
if err != nil {
24+
return err
25+
}
26+
if b.CC != nil {
27+
func() {
28+
n.ccLock.Lock()
29+
defer n.ccLock.Unlock()
30+
n.cc = *b.CC
31+
}()
32+
}
33+
return nil
34+
}
35+
36+
// saveBackport saves a backport from the current CC.
37+
// Note: Node.ccLock must be read-locked (i.e. RLock was called).
38+
func (n *Node) saveBackport() error {
39+
encoded, err := json.Marshal(Backport{
40+
CC: &n.cc,
41+
})
42+
if err != nil {
43+
return err
44+
}
45+
err = os.WriteFile(n.backportPath, encoded, 0o0600)
46+
if err != nil {
47+
return err
48+
}
49+
return nil
50+
}

node/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type NodeConfig struct {
2222
HokutoExtraParents []hokuto.ExtraParent
2323
CS CSConfig
2424
EndpointOverride string
25+
BackportPath string
2526
}
2627

2728
// There must be only one Node instance as a Node can trigger a trace to stop.
@@ -46,6 +47,7 @@ func NewNode(cfg NodeConfig) (*Node, error) {
4647
mio: mh,
4748
hokuto: hh,
4849
endpointOverridePath: cfg.EndpointOverride,
50+
backportPath: cfg.BackportPath,
4951
}
5052
if cfg.HokutoDNSAddr != "" {
5153
addr, err := net.ResolveUDPAddr("udp", cfg.HokutoDNSAddr)
@@ -80,4 +82,6 @@ type Node struct {
8082
endpointOverridePath string
8183
eoState *eoState
8284
eoStateLock sync.Mutex
85+
86+
backportPath string
8387
}

runner/node.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log"
88
"os"
99
"os/exec"
10+
"path/filepath"
1011

1112
"github.com/nyiyui/qrystal/runner/config"
1213
)
@@ -17,6 +18,38 @@ type nodeHandle struct {
1718
}
1819

1920
func newNode(cfg *config.Node, mh, hh *mioHandle) (*nodeHandle, error) {
21+
backportPath := filepath.Join(os.Getenv("STATE_DIRECTORY"), "node-backport.json")
22+
_, err := os.Stat(backportPath)
23+
if os.IsNotExist(err) {
24+
f, err := os.Create(backportPath)
25+
if err != nil {
26+
return nil, fmt.Errorf("create backport file: %w", err)
27+
}
28+
err = f.Close()
29+
if err != nil {
30+
return nil, fmt.Errorf("close created backport file: %w", err)
31+
}
32+
} else if err != nil {
33+
return nil, fmt.Errorf("stat backport file: %w", err)
34+
}
35+
err = os.Chmod(backportPath, 0o0600)
36+
if err != nil {
37+
return nil, fmt.Errorf("chmod created backport file: %w", err)
38+
}
39+
cred, err := cfg.Subprocess.Credential.ToCredential()
40+
if err != nil {
41+
return nil, fmt.Errorf("backport file: load credential: %w", err)
42+
}
43+
err = os.Chown(backportPath, int(cred.Uid), int(cred.Gid))
44+
if err != nil {
45+
return nil, fmt.Errorf("chown created backport file: %w", err)
46+
}
47+
48+
err = os.Chown(os.Getenv("STATE_DIRECTORY"), int(cred.Uid), int(cred.Gid))
49+
if err != nil {
50+
return nil, fmt.Errorf("chown STATE_DIRECTORY: %w", err)
51+
}
52+
2053
cmd, err := newSubprocess(cfg.Subprocess)
2154
if err != nil {
2255
return nil, fmt.Errorf("subprocess: %w", err)

0 commit comments

Comments
 (0)