1{
2 lib,
3 mkNode,
4 package,
5 testScriptSetup,
6 ...
7}:
8let
9 extraSettings =
10 if (lib.versionAtLeast package.version "2") then
11 {
12 replication_factor = 3;
13 consistency_mode = "consistent";
14 }
15 else
16 {
17 replication_mode = "3";
18 };
19in
20{
21 name = "garage-3node-replication";
22
23 nodes = {
24 node1 = mkNode {
25 inherit extraSettings;
26 publicV6Address = "fc00:1::1";
27 };
28 node2 = mkNode {
29 inherit extraSettings;
30 publicV6Address = "fc00:1::2";
31 };
32 node3 = mkNode {
33 inherit extraSettings;
34 publicV6Address = "fc00:1::3";
35 };
36 node4 = mkNode {
37 inherit extraSettings;
38 publicV6Address = "fc00:1::4";
39 };
40 };
41
42 testScript = # python
43 ''
44 ${testScriptSetup}
45
46 with subtest("Garage works as a multi-node S3 storage"):
47 nodes = ('node1', 'node2', 'node3', 'node4')
48 rev_machines = {m.name: m for m in machines}
49 def get_machine(key): return rev_machines[key]
50 for key in nodes:
51 node = get_machine(key)
52 node.wait_for_unit("garage.service")
53 node.wait_for_open_port(3900)
54
55 # Garage is initialized on all nodes.
56 node_ids = {key: get_node_fqn(get_machine(key)) for key in nodes}
57
58 for key in nodes:
59 for other_key in nodes:
60 if other_key != key:
61 other_id = node_ids[other_key]
62 get_machine(key).succeed(f"garage node connect {other_id.node_id}@{other_id.host}")
63
64 # Provide multiple zones for the nodes.
65 zones = ["nixcon", "nixcon", "paris_meetup", "fosdem"]
66 apply_garage_layout(node1,
67 [
68 f'{ndata.node_id} -z {zones[index]} -c 1G'
69 for index, ndata in enumerate(node_ids.values())
70 ])
71 # Now Garage is operational.
72 test_bucket_writes(node1)
73 for node in nodes:
74 test_bucket_over_http(get_machine(node))
75 '';
76}