github.com/yasker/longhorn-engine@v0.0.0-20160621014712-6ed6cfca0729/integration/core/test_cli.py (about) 1 import time 2 import random 3 from os import path 4 import os 5 import subprocess 6 import json 7 8 import pytest 9 import cattle 10 11 12 REPLICA = 'tcp://localhost:9502' 13 REPLICA2 = 'tcp://localhost:9505' 14 15 BACKUP_DEST = '/tmp/longhorn-backup' 16 17 VOLUME_NAME = 'test-volume' 18 VOLUME_SIZE = str(4 * 1024 * 1024) # 4M 19 20 21 @pytest.fixture 22 def controller_client(request): 23 url = 'http://localhost:9501/v1/schemas' 24 c = cattle.from_env(url=url) 25 request.addfinalizer(lambda: cleanup_controller(c)) 26 c = cleanup_controller(c) 27 assert c.list_volume()[0].replicaCount == 0 28 return c 29 30 31 def cleanup_controller(client): 32 for r in client.list_replica(): 33 client.delete(r) 34 return client 35 36 37 @pytest.fixture 38 def replica_client(request): 39 url = 'http://localhost:9502/v1/schemas' 40 c = cattle.from_env(url=url) 41 request.addfinalizer(lambda: cleanup_replica(c)) 42 return cleanup_replica(c) 43 44 45 @pytest.fixture 46 def replica_client2(request): 47 url = 'http://localhost:9505/v1/schemas' 48 c = cattle.from_env(url=url) 49 request.addfinalizer(lambda: cleanup_replica(c)) 50 return cleanup_replica(c) 51 52 53 def cleanup_replica(client): 54 r = client.list_replica()[0] 55 if r.state == 'initial': 56 return client 57 if 'open' in r: 58 r = r.open() 59 client.delete(r) 60 r = client.reload(r) 61 assert r.state == 'initial' 62 return client 63 64 65 @pytest.fixture 66 def random_str(): 67 return 'random-{0}-{1}'.format(random_num(), int(time.time())) 68 69 70 def random_num(): 71 return random.randint(0, 1000000) 72 73 74 def _file(f): 75 return path.join(_base(), '../../{}'.format(f)) 76 77 78 def _base(): 79 return path.dirname(__file__) 80 81 82 @pytest.fixture(scope='session') 83 def bin(): 84 c = _file('bin/longhorn') 85 assert path.exists(c) 86 return c 87 88 89 def setup_module(): 90 if os.path.exists(BACKUP_DEST): 91 subprocess.check_call(["rm", "-rf", BACKUP_DEST]) 92 93 os.makedirs(BACKUP_DEST) 94 assert os.path.exists(BACKUP_DEST) 95 96 97 def open_replica(client): 98 replicas = client.list_replica() 99 assert len(replicas) == 1 100 101 r = replicas[0] 102 assert r.state == 'initial' 103 assert r.size == '0' 104 assert r.sectorSize == 0 105 assert r.parent == '' 106 assert r.head == '' 107 108 r = r.create(size=str(1024 * 4096)) 109 110 assert r.state == 'closed' 111 assert r.size == str(1024 * 4096) 112 assert r.sectorSize == 512 113 assert r.parent == '' 114 assert r.head == 'volume-head-000.img' 115 116 return r 117 118 119 def test_replica_add_start(bin, controller_client, replica_client): 120 open_replica(replica_client) 121 122 cmd = [bin, '--debug', 'add-replica', REPLICA] 123 subprocess.check_call(cmd) 124 125 volume = controller_client.list_volume()[0] 126 assert volume.replicaCount == 1 127 128 129 def test_replica_add_rebuild(bin, controller_client, replica_client, 130 replica_client2): 131 open_replica(replica_client) 132 open_replica(replica_client2) 133 134 r = replica_client.list_replica()[0] 135 r = r.open() 136 r = r.snapshot(name='000') 137 r = r.snapshot(name='001') 138 139 l = replica_client2.list_replica()[0] 140 141 assert r.chain == ['volume-head-002.img', 142 'volume-snap-001.img', 143 'volume-snap-000.img'] 144 145 assert l.chain != ['volume-head-002.img', 146 'volume-snap-001.img', 147 'volume-snap-000.img'] 148 149 r = r.close() 150 cmd = [bin, '--debug', 'add-replica', REPLICA] 151 subprocess.check_call(cmd) 152 153 volume = controller_client.list_volume()[0] 154 assert volume.replicaCount == 1 155 156 cmd = [bin, '--debug', 'add-replica', REPLICA2] 157 subprocess.check_call(cmd) 158 159 volume = controller_client.list_volume()[0] 160 assert volume.replicaCount == 2 161 162 replicas = controller_client.list_replica() 163 assert len(replicas) == 2 164 165 for r in replicas: 166 assert r.mode == 'RW' 167 168 169 def test_replica_add_after_rebuild_failed(bin, controller_client, 170 replica_client, replica_client2): 171 open_replica(replica_client) 172 open_replica(replica_client2) 173 174 r = replica_client.list_replica()[0] 175 r = r.open() 176 r = r.snapshot(name='000') 177 r.close() 178 179 cmd = [bin, '--debug', 'add-replica', REPLICA] 180 subprocess.check_call(cmd) 181 182 volume = controller_client.list_volume()[0] 183 assert volume.replicaCount == 1 184 185 l = replica_client2.list_replica()[0] 186 l = l.open() 187 l = l.setrebuilding(rebuilding=True) 188 l.close() 189 190 cmd = [bin, '--debug', 'add-replica', REPLICA2] 191 subprocess.check_call(cmd) 192 193 volume = controller_client.list_volume()[0] 194 assert volume.replicaCount == 2 195 196 replicas = controller_client.list_replica() 197 assert len(replicas) == 2 198 199 for r in replicas: 200 assert r.mode == 'RW' 201 202 203 def test_revert(bin, controller_client, replica_client, replica_client2): 204 open_replica(replica_client) 205 open_replica(replica_client2) 206 207 v = controller_client.list_volume()[0] 208 v = v.start(replicas=[ 209 REPLICA, 210 REPLICA2, 211 ]) 212 assert v.replicaCount == 2 213 214 snap = v.snapshot(name='foo1') 215 assert snap.id == 'foo1' 216 217 snap2 = v.snapshot(name='foo2') 218 assert snap2.id == 'foo2' 219 220 r1 = replica_client.list_replica()[0] 221 r2 = replica_client2.list_replica()[0] 222 223 assert r1.chain == ['volume-head-002.img', 'volume-snap-foo2.img', 224 'volume-snap-foo1.img'] 225 assert r1.chain == r2.chain 226 227 v.revert(name='foo1') 228 229 r1 = replica_client.list_replica()[0] 230 r2 = replica_client2.list_replica()[0] 231 assert r1.chain == ['volume-head-003.img', 'volume-snap-foo1.img'] 232 assert r1.chain == r2.chain 233 234 235 def test_snapshot(bin, controller_client, replica_client, replica_client2): 236 open_replica(replica_client) 237 open_replica(replica_client2) 238 239 v = controller_client.list_volume()[0] 240 v = v.start(replicas=[ 241 REPLICA, 242 REPLICA2, 243 ]) 244 assert v.replicaCount == 2 245 246 snap = v.snapshot(name='foo1') 247 assert snap.id == 'foo1' 248 249 snap2 = v.snapshot(name='foo2') 250 assert snap2.id == 'foo2' 251 252 cmd = [bin, '--debug', 'snapshot'] 253 output = subprocess.check_output(cmd) 254 255 assert output == '''ID 256 {} 257 {} 258 '''.format(snap2.id, snap.id) 259 260 261 def test_snapshot_ls(bin, controller_client, replica_client, replica_client2): 262 open_replica(replica_client) 263 open_replica(replica_client2) 264 265 v = controller_client.list_volume()[0] 266 v = v.start(replicas=[ 267 REPLICA, 268 REPLICA2, 269 ]) 270 assert v.replicaCount == 2 271 272 snap = v.snapshot() 273 assert snap.id != '' 274 275 snap2 = v.snapshot() 276 assert snap2.id != '' 277 278 cmd = [bin, '--debug', 'snapshot', 'ls'] 279 output = subprocess.check_output(cmd) 280 281 assert output == '''ID 282 {} 283 {} 284 '''.format(snap2.id, snap.id) 285 286 287 def test_snapshot_create(bin, controller_client, replica_client, 288 replica_client2): 289 open_replica(replica_client) 290 open_replica(replica_client2) 291 292 v = controller_client.list_volume()[0] 293 v = v.start(replicas=[ 294 REPLICA, 295 REPLICA2, 296 ]) 297 assert v.replicaCount == 2 298 299 cmd = [bin, 'snapshot', 'create'] 300 output = subprocess.check_output(cmd).strip() 301 expected = replica_client.list_replica()[0].chain[1] 302 303 assert expected == 'volume-snap-{}.img'.format(output) 304 305 cmd = [bin, '--debug', 'snapshot', 'ls'] 306 ls_output = subprocess.check_output(cmd) 307 308 assert ls_output == '''ID 309 {} 310 '''.format(output) 311 312 313 def test_snapshot_rm(bin, controller_client, replica_client, replica_client2): 314 open_replica(replica_client) 315 open_replica(replica_client2) 316 317 v = controller_client.list_volume()[0] 318 v = v.start(replicas=[ 319 REPLICA, 320 REPLICA2, 321 ]) 322 assert v.replicaCount == 2 323 324 cmd = [bin, 'snapshot', 'create'] 325 subprocess.check_call(cmd) 326 output = subprocess.check_output(cmd).strip() 327 328 chain = replica_client.list_replica()[0].chain 329 assert len(chain) == 3 330 assert chain[0] == 'volume-head-002.img' 331 assert chain[1] == 'volume-snap-{}.img'.format(output) 332 333 cmd = [bin, 'snapshot', 'rm', output] 334 subprocess.check_call(cmd) 335 336 new_chain = replica_client.list_replica()[0].chain 337 assert len(new_chain) == 2 338 assert chain[0] == new_chain[0] 339 assert chain[2] == new_chain[1] 340 341 342 def test_snapshot_last(bin, controller_client, replica_client, 343 replica_client2): 344 open_replica(replica_client) 345 open_replica(replica_client2) 346 347 v = controller_client.list_volume()[0] 348 v = v.start(replicas=[ 349 REPLICA, 350 ]) 351 assert v.replicaCount == 1 352 353 cmd = [bin, 'add', REPLICA2] 354 subprocess.check_output(cmd) 355 output = subprocess.check_output([bin, 'snapshot', 'ls']) 356 output = output.splitlines()[1] 357 358 chain = replica_client.list_replica()[0].chain 359 assert len(chain) == 2 360 assert chain[0] == 'volume-head-001.img' 361 assert chain[1] == 'volume-snap-{}.img'.format(output) 362 363 chain = replica_client2.list_replica()[0].chain 364 assert len(chain) == 2 365 assert chain[0] == 'volume-head-001.img' 366 assert chain[1] == 'volume-snap-{}.img'.format(output) 367 368 # it will be marked as removed 369 cmd = [bin, 'snapshot', 'rm', output] 370 subprocess.check_call(cmd) 371 372 373 def test_backup_core(bin, controller_client, replica_client, 374 replica_client2): 375 open_replica(replica_client) 376 open_replica(replica_client2) 377 378 v = controller_client.list_volume()[0] 379 v = v.start(replicas=[ 380 REPLICA, 381 REPLICA2, 382 ]) 383 assert v.replicaCount == 2 384 385 cmd = [bin, 'snapshot', 'create'] 386 output = subprocess.check_output(cmd).strip() 387 snapshot1 = replica_client.list_replica()[0].chain[1] 388 389 assert snapshot1 == 'volume-snap-{}.img'.format(output) 390 391 cmd = [bin, 'backup', 'create', snapshot1, 392 '--dest', "vfs://" + BACKUP_DEST] 393 backup1 = subprocess.check_output(cmd).strip() 394 395 cmd = [bin, 'snapshot', 'create'] 396 output = subprocess.check_output(cmd).strip() 397 snapshot2 = replica_client.list_replica()[0].chain[1] 398 399 assert snapshot2 == 'volume-snap-{}.img'.format(output) 400 401 cmd = [bin, 'backup', 'create', snapshot2, 402 '--dest', "vfs://" + BACKUP_DEST] 403 backup2 = subprocess.check_output(cmd).strip() 404 405 cmd = [bin, 'backup', 'inspect', backup1] 406 data = subprocess.check_output(cmd) 407 backup1_info = json.loads(data) 408 assert backup1_info["BackupURL"] == backup1 409 assert backup1_info["VolumeName"] == VOLUME_NAME 410 assert backup1_info["VolumeSize"] == VOLUME_SIZE 411 assert backup1_info["SnapshotName"] == snapshot1 412 413 cmd = [bin, 'backup', 'inspect', backup2] 414 data = subprocess.check_output(cmd) 415 backup2_info = json.loads(data) 416 assert backup2_info["BackupURL"] == backup2 417 assert backup2_info["VolumeName"] == VOLUME_NAME 418 assert backup2_info["VolumeSize"] == VOLUME_SIZE 419 assert backup2_info["SnapshotName"] == snapshot2 420 421 cmd = [bin, 'backup', 'inspect', 422 "vfs:///tmp/longhorn-backup?backup=backup-1234&volume=test-volume"] 423 with pytest.raises(subprocess.CalledProcessError) as e: 424 subprocess.check_call(cmd) 425 assert 'cannot find' in str(e.value) 426 427 cmd = [bin, 'backup', 'restore', backup1] 428 subprocess.check_call(cmd) 429 430 cmd = [bin, 'backup', 'restore', backup2] 431 subprocess.check_call(cmd) 432 433 cmd = [bin, 'backup', 'rm', backup1] 434 subprocess.check_call(cmd) 435 cmd = [bin, 'backup', 'rm', backup2] 436 subprocess.check_call(cmd) 437 438 assert os.path.exists(BACKUP_DEST) 439 440 cmd = [bin, 'backup', 'inspect', 441 "vfs:///tmp/longhorn-backup?backup=backup-1234&volume=test-volume"] 442 with pytest.raises(subprocess.CalledProcessError) as e: 443 subprocess.check_call(cmd) 444 assert 'cannot find' in str(e.value) 445 446 cmd = [bin, 'backup', 'inspect', "xxx"] 447 with pytest.raises(subprocess.CalledProcessError) as e: 448 subprocess.check_call(cmd) 449 assert 'not supported' in str(e.value)