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