at 25.11-pre 10 kB view raw
1import ./make-test-python.nix ( 2 { pkgs, lib, ... }: 3 4 let 5 cfg = { 6 clusterId = "066ae264-2a5d-4729-8001-6ad265f50b03"; 7 monA = { 8 name = "a"; 9 ip = "192.168.1.1"; 10 }; 11 osd0 = { 12 name = "0"; 13 ip = "192.168.1.2"; 14 key = "AQBCEJNa3s8nHRAANvdsr93KqzBznuIWm2gOGg=="; 15 uuid = "55ba2294-3e24-478f-bee0-9dca4c231dd9"; 16 }; 17 osd1 = { 18 name = "1"; 19 ip = "192.168.1.3"; 20 key = "AQBEEJNac00kExAAXEgy943BGyOpVH1LLlHafQ=="; 21 uuid = "5e97a838-85b6-43b0-8950-cb56d554d1e5"; 22 }; 23 osd2 = { 24 name = "2"; 25 ip = "192.168.1.4"; 26 key = "AQAdyhZeIaUlARAAGRoidDAmS6Vkp546UFEf5w=="; 27 uuid = "ea999274-13d0-4dd5-9af9-ad25a324f72f"; 28 }; 29 }; 30 generateCephConfig = 31 { daemonConfig }: 32 { 33 enable = true; 34 global = { 35 fsid = cfg.clusterId; 36 monHost = cfg.monA.ip; 37 monInitialMembers = cfg.monA.name; 38 }; 39 } 40 // daemonConfig; 41 42 generateHost = 43 { 44 pkgs, 45 cephConfig, 46 networkConfig, 47 ... 48 }: 49 { 50 virtualisation = { 51 emptyDiskImages = [ 20480 ]; 52 vlans = [ 1 ]; 53 }; 54 55 networking = networkConfig; 56 57 environment.systemPackages = with pkgs; [ 58 bash 59 sudo 60 ceph 61 xfsprogs 62 libressl.nc 63 ]; 64 65 boot.kernelModules = [ "xfs" ]; 66 67 services.ceph = cephConfig; 68 }; 69 70 networkMonA = { 71 dhcpcd.enable = false; 72 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [ 73 { 74 address = cfg.monA.ip; 75 prefixLength = 24; 76 } 77 ]; 78 firewall = { 79 allowedTCPPorts = [ 80 6789 81 3300 82 ]; 83 allowedTCPPortRanges = [ 84 { 85 from = 6800; 86 to = 7300; 87 } 88 ]; 89 }; 90 }; 91 cephConfigMonA = generateCephConfig { 92 daemonConfig = { 93 mon = { 94 enable = true; 95 daemons = [ cfg.monA.name ]; 96 }; 97 mgr = { 98 enable = true; 99 daemons = [ cfg.monA.name ]; 100 }; 101 }; 102 }; 103 104 networkOsd = osd: { 105 dhcpcd.enable = false; 106 interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [ 107 { 108 address = osd.ip; 109 prefixLength = 24; 110 } 111 ]; 112 firewall = { 113 allowedTCPPortRanges = [ 114 { 115 from = 6800; 116 to = 7300; 117 } 118 ]; 119 }; 120 }; 121 122 cephConfigOsd = 123 osd: 124 generateCephConfig { 125 daemonConfig = { 126 osd = { 127 enable = true; 128 daemons = [ osd.name ]; 129 }; 130 }; 131 }; 132 133 # Following deployment is based on the manual deployment described here: 134 # https://docs.ceph.com/docs/master/install/manual-deployment/ 135 # For other ways to deploy a ceph cluster, look at the documentation at 136 # https://docs.ceph.com/docs/master/ 137 testscript = 138 { ... }: 139 '' 140 start_all() 141 142 monA.wait_for_unit("network.target") 143 osd0.wait_for_unit("network.target") 144 osd1.wait_for_unit("network.target") 145 osd2.wait_for_unit("network.target") 146 147 # Bootstrap ceph-mon daemon 148 monA.succeed( 149 "sudo -u ceph ceph-authtool --create-keyring /tmp/ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'", 150 "sudo -u ceph ceph-authtool --create-keyring /etc/ceph/ceph.client.admin.keyring --gen-key -n client.admin --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'", 151 "sudo -u ceph ceph-authtool /tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring", 152 "monmaptool --create --add ${cfg.monA.name} ${cfg.monA.ip} --fsid ${cfg.clusterId} /tmp/monmap", 153 "sudo -u ceph ceph-mon --mkfs -i ${cfg.monA.name} --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring", 154 "sudo -u ceph mkdir -p /var/lib/ceph/mgr/ceph-${cfg.monA.name}/", 155 "sudo -u ceph touch /var/lib/ceph/mon/ceph-${cfg.monA.name}/done", 156 "systemctl start ceph-mon-${cfg.monA.name}", 157 ) 158 monA.wait_for_unit("ceph-mon-${cfg.monA.name}") 159 monA.succeed("ceph mon enable-msgr2") 160 monA.succeed("ceph config set mon auth_allow_insecure_global_id_reclaim false") 161 162 # Can't check ceph status until a mon is up 163 monA.succeed("ceph -s | grep 'mon: 1 daemons'") 164 165 # Start the ceph-mgr daemon, it has no deps and hardly any setup 166 monA.succeed( 167 "ceph auth get-or-create mgr.${cfg.monA.name} mon 'allow profile mgr' osd 'allow *' mds 'allow *' > /var/lib/ceph/mgr/ceph-${cfg.monA.name}/keyring", 168 "systemctl start ceph-mgr-${cfg.monA.name}", 169 ) 170 monA.wait_for_unit("ceph-mgr-a") 171 monA.wait_until_succeeds("ceph -s | grep 'quorum ${cfg.monA.name}'") 172 monA.wait_until_succeeds("ceph -s | grep 'mgr: ${cfg.monA.name}(active,'") 173 174 # Send the admin keyring to the OSD machines 175 monA.succeed("cp /etc/ceph/ceph.client.admin.keyring /tmp/shared") 176 osd0.succeed("cp /tmp/shared/ceph.client.admin.keyring /etc/ceph") 177 osd1.succeed("cp /tmp/shared/ceph.client.admin.keyring /etc/ceph") 178 osd2.succeed("cp /tmp/shared/ceph.client.admin.keyring /etc/ceph") 179 180 # Bootstrap OSDs 181 osd0.succeed( 182 "mkfs.xfs /dev/vdb", 183 "mkdir -p /var/lib/ceph/osd/ceph-${cfg.osd0.name}", 184 "mount /dev/vdb /var/lib/ceph/osd/ceph-${cfg.osd0.name}", 185 "ceph-authtool --create-keyring /var/lib/ceph/osd/ceph-${cfg.osd0.name}/keyring --name osd.${cfg.osd0.name} --add-key ${cfg.osd0.key}", 186 'echo \'{"cephx_secret": "${cfg.osd0.key}"}\' | ceph osd new ${cfg.osd0.uuid} -i -', 187 ) 188 osd1.succeed( 189 "mkfs.xfs /dev/vdb", 190 "mkdir -p /var/lib/ceph/osd/ceph-${cfg.osd1.name}", 191 "mount /dev/vdb /var/lib/ceph/osd/ceph-${cfg.osd1.name}", 192 "ceph-authtool --create-keyring /var/lib/ceph/osd/ceph-${cfg.osd1.name}/keyring --name osd.${cfg.osd1.name} --add-key ${cfg.osd1.key}", 193 'echo \'{"cephx_secret": "${cfg.osd1.key}"}\' | ceph osd new ${cfg.osd1.uuid} -i -', 194 ) 195 osd2.succeed( 196 "mkfs.xfs /dev/vdb", 197 "mkdir -p /var/lib/ceph/osd/ceph-${cfg.osd2.name}", 198 "mount /dev/vdb /var/lib/ceph/osd/ceph-${cfg.osd2.name}", 199 "ceph-authtool --create-keyring /var/lib/ceph/osd/ceph-${cfg.osd2.name}/keyring --name osd.${cfg.osd2.name} --add-key ${cfg.osd2.key}", 200 'echo \'{"cephx_secret": "${cfg.osd2.key}"}\' | ceph osd new ${cfg.osd2.uuid} -i -', 201 ) 202 203 # Initialize the OSDs with regular filestore 204 osd0.succeed( 205 "ceph-osd -i ${cfg.osd0.name} --mkfs --osd-uuid ${cfg.osd0.uuid}", 206 "chown -R ceph:ceph /var/lib/ceph/osd", 207 "systemctl start ceph-osd-${cfg.osd0.name}", 208 ) 209 osd1.succeed( 210 "ceph-osd -i ${cfg.osd1.name} --mkfs --osd-uuid ${cfg.osd1.uuid}", 211 "chown -R ceph:ceph /var/lib/ceph/osd", 212 "systemctl start ceph-osd-${cfg.osd1.name}", 213 ) 214 osd2.succeed( 215 "ceph-osd -i ${cfg.osd2.name} --mkfs --osd-uuid ${cfg.osd2.uuid}", 216 "chown -R ceph:ceph /var/lib/ceph/osd", 217 "systemctl start ceph-osd-${cfg.osd2.name}", 218 ) 219 monA.wait_until_succeeds("ceph osd stat | grep -e '3 osds: 3 up[^,]*, 3 in'") 220 monA.wait_until_succeeds("ceph -s | grep 'mgr: ${cfg.monA.name}(active,'") 221 monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'") 222 223 monA.succeed( 224 "ceph osd pool create multi-node-test 32 32", 225 "ceph osd pool ls | grep 'multi-node-test'", 226 227 # We need to enable an application on the pool, otherwise it will 228 # stay unhealthy in state POOL_APP_NOT_ENABLED. 229 # Creating a CephFS would do this automatically, but we haven't done that here. 230 # See: https://docs.ceph.com/en/reef/rados/operations/pools/#associating-a-pool-with-an-application 231 # We use the custom application name "nixos-test" for this. 232 "ceph osd pool application enable multi-node-test nixos-test", 233 234 "ceph osd pool rename multi-node-test multi-node-other-test", 235 "ceph osd pool ls | grep 'multi-node-other-test'", 236 ) 237 monA.wait_until_succeeds("ceph -s | grep '2 pools, 33 pgs'") 238 monA.succeed("ceph osd pool set multi-node-other-test size 2") 239 monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'") 240 monA.wait_until_succeeds("ceph -s | grep '33 active+clean'") 241 monA.fail( 242 "ceph osd pool ls | grep 'multi-node-test'", 243 "ceph osd pool delete multi-node-other-test multi-node-other-test --yes-i-really-really-mean-it", 244 ) 245 246 # Shut down ceph on all machines in a very unpolite way 247 monA.crash() 248 osd0.crash() 249 osd1.crash() 250 osd2.crash() 251 252 # Start it up 253 osd0.start() 254 osd1.start() 255 osd2.start() 256 monA.start() 257 258 # Ensure the cluster comes back up again 259 monA.succeed("ceph -s | grep 'mon: 1 daemons'") 260 monA.wait_until_succeeds("ceph -s | grep 'quorum ${cfg.monA.name}'") 261 monA.wait_until_succeeds("ceph osd stat | grep -e '3 osds: 3 up[^,]*, 3 in'") 262 monA.wait_until_succeeds("ceph -s | grep 'mgr: ${cfg.monA.name}(active,'") 263 monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'") 264 ''; 265 in 266 { 267 name = "basic-multi-node-ceph-cluster"; 268 meta = with pkgs.lib.maintainers; { 269 maintainers = [ lejonet ]; 270 }; 271 272 nodes = { 273 monA = generateHost { 274 pkgs = pkgs; 275 cephConfig = cephConfigMonA; 276 networkConfig = networkMonA; 277 }; 278 osd0 = generateHost { 279 pkgs = pkgs; 280 cephConfig = cephConfigOsd cfg.osd0; 281 networkConfig = networkOsd cfg.osd0; 282 }; 283 osd1 = generateHost { 284 pkgs = pkgs; 285 cephConfig = cephConfigOsd cfg.osd1; 286 networkConfig = networkOsd cfg.osd1; 287 }; 288 osd2 = generateHost { 289 pkgs = pkgs; 290 cephConfig = cephConfigOsd cfg.osd2; 291 networkConfig = networkOsd cfg.osd2; 292 }; 293 }; 294 295 testScript = testscript; 296 } 297)