def test_snapshot_rm( bin, grpc_controller_client, # NOQA grpc_replica_client, grpc_replica_client2): # NOQA open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, r2_url, ]) assert v.replicaCount == 2 cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'create'] subprocess.check_call(cmd) output = subprocess.check_output(cmd).strip() chain = grpc_replica_client.replica_get().chain assert len(chain) == 3 assert chain[0] == 'volume-head-002.img' assert chain[1] == 'volume-snap-{}.img'.format(output) cmd = [ bin, '--url', grpc_controller_client.address, 'snapshot', 'rm', output ] subprocess.check_call(cmd) new_chain = grpc_replica_client.replica_get().chain assert len(new_chain) == 2 assert chain[0] == new_chain[0] assert chain[2] == new_chain[1]
def test_snapshot_purge_basic( bin, grpc_controller_client, # NOQA grpc_replica_client, # NOQA grpc_replica_client2): # NOQA open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, r2_url, ]) assert v.replicaCount == 2 cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'create'] snap0 = subprocess.check_output(cmd).strip() snap1 = subprocess.check_output(cmd).strip() chain = grpc_replica_client.replica_get().chain assert len(chain) == 3 assert chain[0] == 'volume-head-002.img' assert chain[1] == 'volume-snap-{}.img'.format(snap1) assert chain[2] == 'volume-snap-{}.img'.format(snap0) cmd = [ bin, '--url', grpc_controller_client.address, 'snapshot', 'rm', snap0 ] subprocess.check_call(cmd) new_chain = grpc_replica_client.replica_get().chain assert len(new_chain) == 2 assert chain[0] == new_chain[0] assert chain[1] == new_chain[1] cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'info'] output = subprocess.check_output(cmd) info = json.loads(output) assert len(info) == 3 assert info[snap0]["parent"] == "" assert info[snap0]["removed"] is True assert info[snap1]["parent"] == snap0 assert info[snap1]["removed"] is False assert info[VOLUME_HEAD]["parent"] == snap1 cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'purge'] subprocess.check_call(cmd) cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'info'] output = subprocess.check_output(cmd) info = json.loads(output) assert len(info) == 2 assert snap0 not in info assert info[snap1]["parent"] == ""
def test_open(grpc_client): # NOQA r = grpc_client.replica_get() assert r.state == 'initial' assert r.size == '0' assert r.sectorSize == 0 assert r.parent == '' assert r.head == '' r = grpc_client.replica_create(size=SIZE_STR) assert r.state == 'closed' assert not r.dirty assert not r.rebuilding assert r.size == SIZE_STR assert r.sectorSize == 512 assert r.parent == '' assert r.head == 'volume-head-000.img' r = grpc_client.replica_open() assert r.state == 'open' assert not r.dirty assert not r.rebuilding assert r.size == SIZE_STR assert r.sectorSize == 512 assert r.parent == '' assert r.head == 'volume-head-000.img'
def test_snapshot_rm_empty( bin, grpc_controller_client, # NOQA grpc_replica_client, # NOQA grpc_replica_client2): # NOQA open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, r2_url, ]) assert v.replicaCount == 2 cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'create'] # first snapshot output1 = subprocess.check_output(cmd).strip() chain = grpc_replica_client.replica_get().chain assert len(chain) == 2 assert chain[0] == 'volume-head-001.img' assert chain[1] == 'volume-snap-{}.img'.format(output1) # second snapshot output2 = subprocess.check_output(cmd).strip() chain = grpc_replica_client.replica_get().chain assert len(chain) == 3 assert chain[0] == 'volume-head-002.img' assert chain[1] == 'volume-snap-{}.img'.format(output2) assert chain[2] == 'volume-snap-{}.img'.format(output1) # remove the first snapshot(empty), it will fold second snapshot(empty) # to the first snapshot(empty) and rename it to second snapshot cmd = [ bin, '--url', grpc_controller_client.address, 'snapshot', 'rm', output1 ] subprocess.check_call(cmd) new_chain = grpc_replica_client.replica_get().chain assert len(new_chain) == 2 assert chain[0] == new_chain[0] assert chain[1] == new_chain[1]
def test_snapshot_create( bin, grpc_controller_client, # NOQA grpc_replica_client, # NOQA grpc_replica_client2): # NOQA open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, r2_url, ]) assert v.replicaCount == 2 cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'create'] snap0 = subprocess.check_output(cmd).strip() expected = grpc_replica_client.replica_get().chain[1] assert expected == 'volume-snap-{}.img'.format(snap0) cmd = [ bin, '--url', grpc_controller_client.address, 'snapshot', 'create', '--label', 'name=snap1', '--label', 'key=value' ] snap1 = subprocess.check_output(cmd).strip() cmd = [ bin, '--debug', '--url', grpc_controller_client.address, 'snapshot', 'ls' ] ls_output = subprocess.check_output(cmd) assert ls_output == '''ID {} {} '''.format(snap1, snap0) cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'info'] output = subprocess.check_output(cmd) info = json.loads(output) assert len(info) == 3 assert info[snap0]["parent"] == "" assert info[snap0]["removed"] is False assert len(info[snap0]["labels"]) == 0 assert info[snap1]["parent"] == snap0 assert info[snap1]["removed"] is False assert len(info[snap1]["labels"]) == 2 assert info[snap1]["labels"]["name"] == "snap1" assert info[snap1]["labels"]["key"] == "value" assert info[VOLUME_HEAD]["parent"] == snap1 assert len(info[VOLUME_HEAD]["labels"]) == 0
def test_revert( engine_manager_client, # NOQA grpc_controller_client, # NOQA grpc_replica_client, # NOQA grpc_replica_client2): # NOQA open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, r2_url, ]) assert v.replicaCount == 2 snap = grpc_controller_client.volume_snapshot(name='foo1') assert snap == 'foo1' snap2 = grpc_controller_client.volume_snapshot(name='foo2') assert snap2 == 'foo2' r1 = grpc_replica_client.replica_get() r2 = grpc_replica_client2.replica_get() assert r1.chain == [ 'volume-head-002.img', 'volume-snap-foo2.img', 'volume-snap-foo1.img' ] assert r1.chain == r2.chain engine_manager_client.frontend_shutdown(ENGINE_NAME) grpc_controller_client.volume_revert(name='foo1') engine_manager_client.frontend_start(ENGINE_NAME, FRONTEND_TGT_BLOCKDEV) r1 = grpc_replica_client.replica_get() r2 = grpc_replica_client2.replica_get() assert r1.chain == ['volume-head-003.img', 'volume-snap-foo1.img'] assert r1.chain == r2.chain
def test_reload(grpc_client): # NOQA grpc_client.replica_create(size=SIZE_STR) grpc_client.replica_open() r = grpc_client.replica_get() assert r.chain == ['volume-head-000.img'] r = grpc_client.replica_snapshot( name='000', created=datetime.datetime.utcnow().isoformat()) assert r.chain == ['volume-head-001.img', 'volume-snap-000.img'] r = grpc_client.replica_snapshot( name='001', created=datetime.datetime.utcnow().isoformat()) assert r.chain == [ 'volume-head-002.img', 'volume-snap-001.img', 'volume-snap-000.img' ] r = grpc_client.disk_remove(name='volume-snap-000.img') assert r.state == 'dirty' assert r.size == SIZE_STR assert r.sectorSize == 512 assert r.head == 'volume-head-002.img' assert r.parent == 'volume-snap-001.img' assert r.chain == ['volume-head-002.img', 'volume-snap-001.img'] r = grpc_client.replica_reload() assert r.state == 'dirty' assert r.size == SIZE_STR assert r.sectorSize == 512 assert r.chain == ['volume-head-002.img', 'volume-snap-001.img'] assert r.head == 'volume-head-002.img' assert r.parent == 'volume-snap-001.img' grpc_client.replica_close() r = grpc_client.replica_open() assert r.state == 'open' assert r.size == SIZE_STR assert r.sectorSize == 512 assert r.chain == ['volume-head-002.img', 'volume-snap-001.img'] assert r.head == 'volume-head-002.img' assert r.parent == 'volume-snap-001.img'
def test_snapshot_last( bin, grpc_controller_client, # NOQA grpc_replica_client, # NOQA grpc_replica_client2): # NOQA open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, ]) assert v.replicaCount == 1 cmd = [bin, '--url', grpc_controller_client.address, 'add', r2_url] subprocess.check_output(cmd) cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'ls'] output = subprocess.check_output(cmd) output = output.splitlines()[1] chain = grpc_replica_client.replica_get().chain assert len(chain) == 2 assert chain[0] == 'volume-head-001.img' assert chain[1] == 'volume-snap-{}.img'.format(output) chain = grpc_replica_client2.replica_get().chain assert len(chain) == 2 assert chain[0] == 'volume-head-001.img' assert chain[1] == 'volume-snap-{}.img'.format(output) # it will be marked as removed cmd = [ bin, '--url', grpc_controller_client.address, 'snapshot', 'rm', output ] subprocess.check_call(cmd)
def backup_core( bin, engine_manager_client, # NOQA grpc_controller_client, # NOQA grpc_replica_client, # NOQA grpc_replica_client2, # NOQA backup_target): open_replica(grpc_replica_client) open_replica(grpc_replica_client2) r1_url = grpc_replica_client.url r2_url = grpc_replica_client2.url v = grpc_controller_client.volume_start(replicas=[ r1_url, r2_url, ]) assert v.replicaCount == 2 env = dict(os.environ) backup_type = urlparse(backup_target).scheme cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'create'] snapshot1 = subprocess.check_output(cmd).strip() output = grpc_replica_client.replica_get().chain[1] assert output == 'volume-snap-{}.img'.format(snapshot1) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'create', snapshot1, '--dest', backup_target, '--label', 'name=backup1', '--label', 'type=' + backup_type ] backup = json.loads(subprocess.check_output(cmd, env=env).strip()) assert "backupID" in backup.keys() assert "isIncremental" in backup.keys() assert backup["isIncremental"] is False backup1 = get_backup_url(bin, grpc_controller_client.address, backup["backupID"]) cmd = [bin, '--url', grpc_controller_client.address, 'snapshot', 'create'] snapshot2 = subprocess.check_output(cmd).strip() output = grpc_replica_client.replica_get().chain[1] assert output == 'volume-snap-{}.img'.format(snapshot2) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'create', snapshot2, '--dest', backup_target ] backup = json.loads(subprocess.check_output(cmd, env=env).strip()) assert "backupID" in backup.keys() assert "isIncremental" in backup.keys() assert backup["isIncremental"] is True backup2 = get_backup_url(bin, grpc_controller_client.address, backup["backupID"]) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'inspect', backup1 ] data = subprocess.check_output(cmd, env=env) backup1_info = json.loads(data) assert backup1_info["URL"] == backup1 assert backup1_info["VolumeName"] == VOLUME_NAME assert backup1_info["VolumeSize"] == SIZE_STR assert backup1_info["SnapshotName"] == snapshot1 assert len(backup1_info["Labels"]) == 2 assert backup1_info["Labels"]["name"] == "backup1" assert backup1_info["Labels"]["type"] == backup_type cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'inspect', backup2 ] data = subprocess.check_output(cmd, env=env) backup2_info = json.loads(data) assert backup2_info["URL"] == backup2 assert backup2_info["VolumeName"] == VOLUME_NAME assert backup2_info["VolumeSize"] == SIZE_STR assert backup2_info["SnapshotName"] == snapshot2 if backup2_info["Labels"] is not None: assert len(backup2_info["Labels"]) == 0 cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'ls', backup_target ] data = subprocess.check_output(cmd, env=env).strip() volume_info = json.loads(data)[VOLUME_NAME] assert volume_info["Name"] == VOLUME_NAME assert volume_info["Size"] == SIZE_STR backup_list = volume_info["Backups"] assert backup_list[backup1]["URL"] == backup1_info["URL"] assert backup_list[backup1]["SnapshotName"] == backup1_info["SnapshotName"] assert backup_list[backup1]["Size"] == backup1_info["Size"] assert backup_list[backup1]["Created"] == backup1_info["Created"] assert backup_list[backup2]["URL"] == backup2_info["URL"] assert backup_list[backup2]["SnapshotName"] == backup2_info["SnapshotName"] assert backup_list[backup2]["Size"] == backup2_info["Size"] assert backup_list[backup2]["Created"] == backup2_info["Created"] # test backup volume list # https://github.com/rancher/longhorn/issues/399 volume_dir = finddir(BACKUP_DEST, VOLUME_NAME) assert volume_dir assert path.exists(volume_dir) volume_cfg_path = findfile(volume_dir, VOLUME_CONFIG_FILE) assert path.exists(volume_cfg_path) volume_tmp_cfg_path = volume_cfg_path.replace(VOLUME_CONFIG_FILE, VOLUME_TMP_CONFIG_FILE) os.rename(volume_cfg_path, volume_tmp_cfg_path) assert path.exists(volume_tmp_cfg_path) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'ls', '--volume-only', backup_target ] data = subprocess.check_output(cmd, env=env) volume_info = json.loads(data) assert volume_info assert volume_info[VOLUME_NAME] is not None assert volume_info[VOLUME_NAME]["Messages"] is not None assert MESSAGE_TYPE_ERROR in volume_info[VOLUME_NAME]["Messages"] os.rename(volume_tmp_cfg_path, volume_cfg_path) assert path.exists(volume_cfg_path) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'ls', '--volume-only', backup_target ] data = subprocess.check_output(cmd, env=env) volume_info = json.loads(data) assert volume_info assert volume_info[VOLUME_NAME] is not None assert volume_info[VOLUME_NAME]["Messages"] is not None assert MESSAGE_TYPE_ERROR not in volume_info[VOLUME_NAME]["Messages"] cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'inspect', backup_target + "?backup=backup-1234" + "&volume=" + VOLUME_NAME ] # cannot find the backup with pytest.raises(subprocess.CalledProcessError): subprocess.check_call(cmd, env=env) restore_backup(engine_manager_client, bin, grpc_controller_client.address, backup1, env, grpc_controller_client) restore_backup(engine_manager_client, bin, grpc_controller_client.address, backup2, env, grpc_controller_client) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'rm', backup1 ] subprocess.check_call(cmd, env=env) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'rm', backup2 ] subprocess.check_call(cmd, env=env) assert os.path.exists(BACKUP_DEST) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'inspect', backup_target + "?backup=backup-1234" + "&volume=" + VOLUME_NAME ] # cannot find the backup with pytest.raises(subprocess.CalledProcessError): subprocess.check_call(cmd, env=env) cmd = [ bin, '--url', grpc_controller_client.address, 'backup', 'inspect', "xxx" ] # cannot find the backup with pytest.raises(subprocess.CalledProcessError): subprocess.check_call(cmd, env=env) engine_manager_client.frontend_start(ENGINE_NAME, FRONTEND_TGT_BLOCKDEV) v = grpc_controller_client.volume_get() assert v.frontendState == "up"