Example #1
0
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]
Example #2
0
def test_snapshot_ls(
        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

    snap = grpc_controller_client.volume_snapshot()
    assert snap != ''

    snap2 = grpc_controller_client.volume_snapshot()
    assert snap2 != ''

    cmd = [
        bin, '--debug', '--url', grpc_controller_client.address, 'snapshot',
        'ls'
    ]
    output = subprocess.check_output(cmd)

    assert output == '''ID
{}
{}
'''.format(snap2, snap)
Example #3
0
def test_replica_failure_detection(
        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

    # wait for initial read/write period to pass
    time.sleep(2)

    cleanup_replica(grpc_replica_client)

    detected = False
    for i in range(10):
        replicas = grpc_controller_client.replica_list()
        assert len(replicas) == 2
        for r in replicas:
            if r.address == r1_url and r.mode == 'ERR':
                detected = True
                break
        if detected:
            break
        time.sleep(1)
    assert detected
Example #4
0
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"] == ""
Example #5
0
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
Example #6
0
def test_shutdown(grpc_client):  # NOQA
    v = grpc_client.volume_get()
    assert v.replicaCount == 0

    f1 = create_backend_file()
    f2 = create_backend_file()
    addresses = ['file://' + f1, 'file://' + f2]
    v = grpc_client.volume_start(replicas=addresses)
    assert v.replicaCount == 2

    v = grpc_client.volume_shutdown()
    assert v.replicaCount == 0

    rs = grpc_client.replica_list()
    assert len(rs) == 0

    cleanup_backend_file([f1, f2])
Example #7
0
def test_start(grpc_client):  # NOQA
    v = grpc_client.volume_get()
    assert v.replicaCount == 0

    f1 = create_backend_file()
    f2 = create_backend_file()
    addresses = ['file://' + f1, 'file://' + f2]
    v = grpc_client.volume_start(replicas=addresses)

    rs = grpc_client.replica_list()
    assert len(rs) == 2
    assert v.replicaCount == 2

    found_addresses = [r.address for r in rs]
    assert set(found_addresses) == set(addresses)

    cleanup_backend_file([f1, f2])
Example #8
0
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]
Example #9
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
Example #10
0
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)
Example #11
0
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"
Example #12
0
def test_snapshot_info(
        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

    snap = grpc_controller_client.volume_snapshot()
    assert snap != ''

    snap2 = grpc_controller_client.volume_snapshot(labels={
        "name": "snap",
        "key": "value"
    })
    assert snap2 != ''

    cmd = [
        bin, '--debug', '--url', grpc_controller_client.address, 'snapshot',
        'info'
    ]
    output = subprocess.check_output(cmd)
    info = json.loads(output)

    assert len(info) == 3

    volumehead = "volume-head"

    head_info = info[volumehead]
    assert head_info["name"] == volumehead
    assert head_info["parent"] == snap2
    assert not head_info["children"]
    assert head_info["removed"] is False
    assert head_info["usercreated"] is False
    assert head_info["created"] != ""
    assert len(head_info["labels"]) == 0

    snap2_info = info[snap2]
    assert snap2_info["name"] == snap2
    assert snap2_info["parent"] == snap
    assert volumehead in snap2_info["children"]
    assert snap2_info["removed"] is False
    assert snap2_info["usercreated"] is True
    assert snap2_info["created"] != ""
    assert snap2_info["labels"]["name"] == "snap"
    assert snap2_info["labels"]["key"] == "value"

    snap_info = info[snap]
    assert snap_info["name"] == snap
    assert snap_info["parent"] == ""
    assert snap2 in snap_info["children"]
    assert snap_info["removed"] is False
    assert snap_info["usercreated"] is True
    assert snap_info["created"] != ""
    assert len(snap_info["labels"]) == 0