at master 5.4 kB view raw
1{ 2 name = "zrepl"; 3 4 nodes = { 5 source = 6 { nodes, pkgs, ... }: 7 { 8 config = { 9 # Prerequisites for ZFS and tests. 10 virtualisation.emptyDiskImages = [ 11 2048 12 ]; 13 14 boot.supportedFilesystems = [ "zfs" ]; 15 environment.systemPackages = [ 16 pkgs.parted 17 pkgs.zrepl 18 ]; 19 networking.firewall.allowedTCPPorts = [ 8888 ]; 20 networking.hostId = "deadbeef"; 21 services.zrepl = { 22 enable = true; 23 settings = { 24 # Enable Prometheus output for status assertions. 25 global.monitoring = [ 26 { 27 type = "prometheus"; 28 listen = ":9811"; 29 } 30 ]; 31 # Create a periodic snapshot job for an ephemeral zpool. 32 jobs = [ 33 { 34 name = "snapshots"; 35 type = "snap"; 36 37 filesystems."tank/data" = true; 38 snapshotting = { 39 type = "periodic"; 40 prefix = "zrepl_"; 41 interval = "10s"; 42 }; 43 44 pruning.keep = [ 45 { 46 type = "last_n"; 47 count = 8; 48 } 49 ]; 50 } 51 { 52 name = "backup-target"; 53 type = "source"; 54 55 serve = { 56 type = "tcp"; 57 listen = ":8888"; 58 59 clients = { 60 "${nodes.target.networking.primaryIPAddress}" = "${nodes.target.networking.hostName}"; 61 "${nodes.target.networking.primaryIPv6Address}" = "${nodes.target.networking.hostName}"; 62 }; 63 }; 64 filesystems."tank/data" = true; 65 # Snapshots are handled by the separate snap job 66 snapshotting = { 67 type = "manual"; 68 }; 69 } 70 ]; 71 }; 72 }; 73 }; 74 }; 75 76 target = 77 { pkgs, ... }: 78 { 79 config = { 80 # Prerequisites for ZFS and tests. 81 virtualisation.emptyDiskImages = [ 82 2048 83 ]; 84 85 boot.supportedFilesystems = [ "zfs" ]; 86 environment.systemPackages = [ 87 pkgs.parted 88 pkgs.zrepl 89 ]; 90 networking.hostId = "deadd0d0"; 91 services.zrepl = { 92 enable = true; 93 settings = { 94 # Enable Prometheus output for status assertions. 95 global.monitoring = [ 96 { 97 type = "prometheus"; 98 listen = ":9811"; 99 } 100 ]; 101 jobs = [ 102 { 103 name = "source-pull"; 104 type = "pull"; 105 106 connect = { 107 type = "tcp"; 108 address = "source:8888"; 109 }; 110 root_fs = "tank/zrepl/source"; 111 interval = "15s"; 112 recv = { 113 placeholder = { 114 encryption = "off"; 115 }; 116 }; 117 pruning = { 118 keep_sender = [ 119 { 120 type = "regex"; 121 regex = ".*"; 122 } 123 ]; 124 keep_receiver = [ 125 { 126 type = "grid"; 127 grid = "1x1h(keep=all) | 24x1h"; 128 regex = "^zrepl_"; 129 } 130 ]; 131 }; 132 } 133 ]; 134 }; 135 }; 136 }; 137 }; 138 }; 139 140 testScript = '' 141 start_all() 142 143 with subtest("Wait for zrepl and network ready"): 144 for machine in source, target: 145 machine.systemctl("start network-online.target") 146 machine.wait_for_unit("network-online.target") 147 machine.wait_for_unit("zrepl.service") 148 149 with subtest("Create tank zpool"): 150 for machine in source, target: 151 machine.succeed( 152 "parted --script /dev/vdb mklabel gpt", 153 "zpool create tank /dev/vdb", 154 ) 155 156 # Create ZFS datasets 157 source.succeed("zfs create tank/data") 158 target.succeed("zfs create -p tank/zrepl/source") 159 160 with subtest("Check for completed zrepl snapshot on target"): 161 # zrepl periodic snapshot job creates a snapshot with this prefix. 162 target.wait_until_succeeds("zfs list -t snapshot | grep -q tank/zrepl/source/tank/data@zrepl_") 163 164 with subtest("Check for completed zrepl bookmark on source"): 165 source.wait_until_succeeds("zfs list -t bookmark | grep -q tank/data#zrepl_") 166 167 with subtest("Verify HTTP monitoring server is configured"): 168 out = source.succeed("curl -f localhost:9811/metrics") 169 170 assert ( 171 "zrepl_start_time" in out 172 ), "zrepl start time metric was not found in Prometheus output" 173 174 assert ( 175 "zrepl_zfs_snapshot_duration_count{filesystem=\"tank/data\"}" in out 176 ), "zrepl snapshot counter for tank/data was not found in Prometheus output" 177 ''; 178}