1import ./make-test-python.nix (
2 { pkgs, lib, ... }:
3
4 let
5 addrShared = "192.168.0.1";
6 addrHostA = "192.168.0.10";
7 addrHostB = "192.168.0.11";
8
9 mkUcarpHost =
10 addr:
11 {
12 config,
13 pkgs,
14 lib,
15 ...
16 }:
17 {
18 networking.interfaces.eth1.ipv4.addresses = lib.mkForce [
19 {
20 address = addr;
21 prefixLength = 24;
22 }
23 ];
24
25 networking.ucarp = {
26 enable = true;
27 interface = "eth1";
28 srcIp = addr;
29 vhId = 1;
30 passwordFile = "${pkgs.writeText "ucarp-pass" "secure"}";
31 addr = addrShared;
32 upscript = pkgs.writeScript "upscript" ''
33 #!/bin/sh
34 ${pkgs.iproute2}/bin/ip addr add "$2"/24 dev "$1"
35 '';
36 downscript = pkgs.writeScript "downscript" ''
37 #!/bin/sh
38 ${pkgs.iproute2}/bin/ip addr del "$2"/24 dev "$1"
39 '';
40 };
41 };
42 in
43 {
44 name = "ucarp";
45 meta.maintainers = with lib.maintainers; [ oxzi ];
46
47 nodes = {
48 hostA = mkUcarpHost addrHostA;
49 hostB = mkUcarpHost addrHostB;
50 };
51
52 testScript = ''
53 def is_master(host):
54 ipOutput = host.succeed("ip addr show dev eth1")
55 return "inet ${addrShared}/24" in ipOutput
56
57
58 start_all()
59
60 # First, let both hosts start and let a master node be selected
61 for host, peer in [(hostA, "${addrHostB}"), (hostB, "${addrHostA}")]:
62 host.wait_for_unit("ucarp.service")
63 host.succeed(f"ping -c 1 {peer}")
64
65 hostA.sleep(5)
66
67 hostA_master, hostB_master = is_master(hostA), is_master(hostB)
68 assert hostA_master != hostB_master, "only one master node is allowed"
69
70 master_host = hostA if hostA_master else hostB
71 backup_host = hostB if hostA_master else hostA
72
73 # Let's crash the master host and let the backup take over
74 master_host.crash()
75
76 backup_host.sleep(5)
77 assert is_master(backup_host), "backup did not take over"
78 '';
79 }
80)