Exemple #1
0
def test_sort_geoip_wan(vo, rest_client, auth_token, protocols_setup,
                        content_type):
    """Replicas: test sorting a few WANs via geoip."""
    n = 10
    nmap = {}

    def fake_get_distance(se1, se2, *args, **kwargs):
        nonlocal n, nmap
        n = n - 1
        print("fake_get_distance", {'se1': se1, 'se2': se2, 'n': n})
        assert se1, 'pfn host must be se1 for this test'
        nmap[se1] = n
        return n

    data = {
        'dids': [{
            'scope': f['scope'].external,
            'name': f['name'],
            'type': 'FILE'
        } for f in protocols_setup['files']],
        'schemes':
        schemes,
        'sort':
        'geoip',
    }

    with mock.patch('rucio.core.replica_sorter.__get_distance',
                    side_effect=fake_get_distance):
        response = rest_client.post('/replicas/list',
                                    headers=headers(auth(auth_token),
                                                    vohdr(vo),
                                                    accept(content_type)),
                                    json=data)
    assert response.status_code == 200

    replicas_response = response.get_data(as_text=True)
    assert replicas_response

    # because urlparse hostname result is lower case
    sorted_hosts = list(map(str.lower, sorted(nmap, key=nmap.get)))

    if content_type == Mime.METALINK:
        replicas = parse_replicas_from_string(replicas_response)
        print(replicas)
        assert len(replicas) == 1
        sources_list = replicas[0]['sources']
        print(sources_list)
        assert len(sources_list) == 6

        sorted_replica_hosts = list(
            sorted(sources_list, key=lambda source: source['priority']))
        sorted_replica_hosts = list(
            map(lambda source: urlparse(source['pfn']).hostname,
                sorted_replica_hosts))
        assert sorted_hosts == sorted_replica_hosts, 'assert sorting of result as distance suggested'

    elif content_type == Mime.JSON_STREAM:
        replicas = list(
            map(
                json.loads,
                filter(
                    bool,
                    map(str.strip,
                        replicas_response.splitlines(keepends=False)))))
        print(replicas)
        assert len(replicas) == 1
        sources_dict = replicas[0]['pfns']
        assert len(sources_dict) == 6

        sorted_replica_hosts = list(
            sorted(sources_dict,
                   key=lambda pfn: sources_dict[pfn]['priority']))
        sorted_replica_hosts = list(
            map(lambda source: urlparse(source).hostname,
                sorted_replica_hosts))
        assert sorted_hosts == sorted_replica_hosts, 'assert sorting of result as distance suggested'
Exemple #2
0
def test_sort_geoip_lan_before_wan(vo, rest_client, auth_token,
                                   protocols_setup, content_type, info_id):
    """Replicas: test sorting LAN sites before WANs via geoip."""
    n = 2
    nmap = {}

    def fake_get_distance(se1, se2, *args, **kwargs):
        nonlocal n, nmap
        n = n - 1
        print("fake_get_distance", {'se1': se1, 'se2': se2, 'n': n})
        assert se1, 'pfn host must be se1 for this test'
        nmap[se1] = n
        return n

    data = {
        'dids': [{
            'scope': f['scope'].external,
            'name': f['name'],
            'type': 'FILE'
        } for f in protocols_setup['files']],
        'client_location': {
            'site': protocols_setup['rse_info'][info_id]['site']
        },
        'schemes':
        schemes,
        'sort':
        'geoip',
    }

    with mock.patch('rucio.core.replica_sorter.__get_distance',
                    side_effect=fake_get_distance):
        response = rest_client.post('/replicas/list',
                                    headers=headers(auth(auth_token),
                                                    vohdr(vo),
                                                    accept(content_type)),
                                    json=data)
    assert response.status_code == 200

    replicas_response = response.get_data(as_text=True)
    assert replicas_response

    # because urlparse hostname result is lower case
    sorted_wan_hosts = list(map(str.lower, sorted(nmap, key=nmap.get)))

    if content_type == Mime.METALINK:
        replicas = parse_replicas_from_string(replicas_response)
        print(replicas)
        assert len(replicas) == 1
        sources_list = replicas[0]['sources']
        print(sources_list)
        # 3 for wan and 2 for lan, since one is blocked for lan for each site
        assert len(sources_list) == 5

        sorted_replica_hosts = list(
            sorted(sources_list, key=lambda source: source['priority']))
        print(sorted_replica_hosts)
        lan_pfns = list(
            filter(lambda source: source['domain'] == 'lan',
                   sorted_replica_hosts))
        assert len(lan_pfns) == 2
        for lanpfn in lan_pfns:
            assert protocols_setup['rse_info'][info_id]['name'] == lanpfn[
                'rse']

        sorted_replica_wan_hosts = list(
            map(
                lambda source: urlparse(source['pfn']).hostname,
                filter(lambda source: source['domain'] != 'lan',
                       sorted_replica_hosts)))
        assert sorted_wan_hosts == sorted_replica_wan_hosts

    elif content_type == Mime.JSON_STREAM:
        replicas = list(
            map(
                json.loads,
                filter(
                    bool,
                    map(str.strip,
                        replicas_response.splitlines(keepends=False)))))
        print(replicas)
        assert len(replicas) == 1
        sources_dict = replicas[0]['pfns']
        # 3 for wan and 2 for lan, since one is blocked for lan for each site
        assert len(sources_dict) == 5

        sorted_replica_hosts = list(
            sorted(sources_dict,
                   key=lambda pfn: sources_dict[pfn]['priority']))
        lan_pfns = list(
            filter(lambda pfn: sources_dict[pfn]['domain'] == 'lan',
                   sorted_replica_hosts))
        assert len(lan_pfns) == 2
        for lanpfn in lan_pfns:
            assert protocols_setup['rse_info'][info_id]['id'] == sources_dict[
                lanpfn]['rse_id']

        wan_pfns = filter(lambda pfn: sources_dict[pfn]['domain'] != 'lan',
                          sorted_replica_hosts)
        sorted_replica_wan_hosts = list(
            map(lambda pfn: urlparse(pfn).hostname, wan_pfns))
        assert sorted_wan_hosts == sorted_replica_wan_hosts
Exemple #3
0
def test_not_sorting_lan_replicas(vo, rest_client, auth_token, protocols_setup,
                                  content_type):
    """Replicas: test not sorting only LANs."""

    data = {
        'dids': [{
            'scope': f['scope'].external,
            'name': f['name'],
            'type': 'FILE'
        } for f in protocols_setup['files']],
        # yes, this is rather a hack (but works on the API as well). I would like to have an rse_expression parameter instead.
        'client_location': {
            'site':
            '|site='.join(
                map(lambda info: info['site'], protocols_setup['rse_info']))
        },
        'schemes':
        schemes,
    }

    rest_backend = os.environ.get('REST_BACKEND', 'webpy')
    if rest_backend == 'webpy':
        sort_replicas_mock_target = 'rucio.web.rest.replica.sort_replicas'
    elif rest_backend == 'flask':
        sort_replicas_mock_target = 'rucio.web.rest.flaskapi.v1.replicas.sort_replicas'
    else:
        return pytest.xfail('unknown REST_BACKEND: ' + rest_backend)

    def fake_sort_replicas(dictreplica, *args, **kwargs):
        # test that nothing is passed to sort_replicas
        assert not dictreplica
        return []

    # invalidate cache for parse_expression('site=…')
    rse_expression_parser.REGION.invalidate()

    with mock.patch(sort_replicas_mock_target, side_effect=fake_sort_replicas):
        response = rest_client.post('/replicas/list',
                                    headers=headers(auth(auth_token),
                                                    vohdr(vo),
                                                    accept(content_type)),
                                    json=data)
    assert response.status_code == 200

    replicas_response = response.get_data(as_text=True)
    assert replicas_response

    if content_type == Mime.METALINK:
        replicas = parse_replicas_from_string(replicas_response)
        print(replicas)
        assert len(replicas) == 1
        sources_list = replicas[0]['sources']
        print(sources_list)
        # 4 for lan, since one is blocked for lan for each site
        assert len(sources_list) == 4

    elif content_type == Mime.JSON_STREAM:
        replicas = list(
            map(
                json.loads,
                filter(
                    bool,
                    map(str.strip,
                        replicas_response.splitlines(keepends=False)))))
        print(replicas)
        assert len(replicas) == 1
        sources_dict = replicas[0]['pfns']
        # 4 for lan, since one is blocked for lan for each site
        assert len(sources_dict) == 4