def test_abacus_collection_replica_new(vo, rse_factory, rucio_client,
                                       did_factory, core_config_mock,
                                       caches_mock):
    """ ABACUS (COLLECTION REPLICA): Test update of collection replica. """
    file_sizes = 2
    nfiles = 2
    dataset_scope = 'mock'
    rse, rse_id = rse_factory.make_posix_rse()
    dids = did_factory.upload_test_dataset(rse_name=rse,
                                           scope=dataset_scope,
                                           size=file_sizes,
                                           nb_files=nfiles)
    files = [{
        'scope': did['did_scope'],
        'name': did['did_name']
    } for did in dids]
    dataset = dids[0]['dataset_name']
    rucio_client.set_metadata(dataset_scope, dataset, 'lifetime', -1)
    rucio_client.add_replication_rule([{
        'scope': dataset_scope,
        'name': dataset
    }],
                                      1,
                                      rse,
                                      lifetime=-1)

    # Check dataset replica after rule creation - initial data
    dataset_replica = [
        replica for replica in rucio_client.list_dataset_replicas(
            dataset_scope, dataset)
    ][0]
    assert dataset_replica['bytes'] == 0
    assert dataset_replica['length'] == 0
    assert dataset_replica['available_bytes'] == 0
    assert dataset_replica['available_length'] == 0
    assert str(dataset_replica['state']) == 'UNAVAILABLE'

    # Run Abacus
    collection_replica.run(once=True)

    # Check dataset replica after abacus - abacus should update the collection_replica table from updated_col_rep
    dataset_replica = [
        replica for replica in rucio_client.list_dataset_replicas(
            dataset_scope, dataset)
    ][0]
    assert dataset_replica['bytes'] == len(files) * file_sizes
    assert dataset_replica['length'] == len(files)
    assert dataset_replica['available_bytes'] == len(files) * file_sizes
    assert dataset_replica['available_length'] == len(files)
    assert str(dataset_replica['state']) == 'AVAILABLE'

    # Delete one file -> collection replica should be unavailable
    cleaner.run(once=True)
    delete_replicas(rse_id=rse_id,
                    files=[{
                        'name': files[0]['name'],
                        'scope': InternalScope(dataset_scope, vo)
                    }])
    rucio_client.add_replication_rule([{
        'scope': dataset_scope,
        'name': dataset
    }],
                                      1,
                                      rse,
                                      lifetime=-1)
    collection_replica.run(once=True)
    dataset_replica = [
        replica for replica in rucio_client.list_dataset_replicas(
            dataset_scope, dataset)
    ][0]
    assert dataset_replica['length'] == len(files)
    assert dataset_replica['bytes'] == len(files) * file_sizes
    assert dataset_replica['available_length'] == len(files) - 1
    assert dataset_replica['available_bytes'] == (len(files) - 1) * file_sizes
    assert str(dataset_replica['state']) == 'UNAVAILABLE'

    # Delete all files -> collection replica should be deleted
    # New behaviour (dataset should be deleted)
    cleaner.run(once=True)
    delete_replicas(rse_id=rse_id,
                    files=[{
                        'name': files[1]['name'],
                        'scope': InternalScope(dataset_scope, vo)
                    }])
    with pytest.raises(DataIdentifierNotFound):
        get_did(scope=InternalScope(dataset_scope), name=dataset)
    def test_abacus_collection_replica(self):
        """ ABACUS (COLLECTION REPLICA): Test update of collection replica. """
        self.files = [{
            'did_scope': self.scope,
            'did_name': 'file_' + generate_uuid(),
            'path': file_generator(size=self.file_sizes),
            'rse': self.rse,
            'lifetime': -1
        } for _ in range(0, 2)]
        self.did_client.add_did(self.scope,
                                self.dataset,
                                DIDType.DATASET,
                                lifetime=-1)
        self.upload_client.upload(self.files)
        self.did_client.attach_dids(scope=self.scope,
                                    name=self.dataset,
                                    dids=[{
                                        'name': file['did_name'],
                                        'scope': file['did_scope']
                                    } for file in self.files])
        self.rule_client.add_replication_rule([{
            'scope': self.scope,
            'name': self.dataset
        }],
                                              1,
                                              self.rse,
                                              lifetime=-1)
        [os.remove(file['path']) for file in self.files]

        # Check dataset replica after rule creation - initial data
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ][0]
        assert dataset_replica['bytes'] == 0
        assert dataset_replica['length'] == 0
        assert dataset_replica['available_bytes'] == 0
        assert dataset_replica['available_length'] == 0
        assert str(dataset_replica['state']) == 'UNAVAILABLE'

        # Run Abacus
        collection_replica.run(once=True)

        # Check dataset replica after abacus - abacus should update the collection_replica table from updated_col_rep
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ][0]
        assert dataset_replica['bytes'] == len(self.files) * self.file_sizes
        assert dataset_replica['length'] == len(self.files)
        assert dataset_replica['available_bytes'] == len(
            self.files) * self.file_sizes
        assert dataset_replica['available_length'] == len(self.files)
        assert str(dataset_replica['state']) == 'AVAILABLE'

        # Delete one file -> collection replica should be unavailable
        cleaner.run(once=True)
        delete_replicas(rse_id=self.rse_id,
                        files=[{
                            'name':
                            self.files[0]['did_name'],
                            'scope':
                            InternalScope(self.files[0]['did_scope'],
                                          **self.vo)
                        }])
        self.rule_client.add_replication_rule([{
            'scope': self.scope,
            'name': self.dataset
        }],
                                              1,
                                              self.rse,
                                              lifetime=-1)
        collection_replica.run(once=True)
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ][0]
        assert dataset_replica['length'] == len(self.files)
        assert dataset_replica['bytes'] == len(self.files) * self.file_sizes
        assert dataset_replica['available_length'] == len(self.files) - 1
        assert dataset_replica['available_bytes'] == (len(self.files) -
                                                      1) * self.file_sizes
        assert str(dataset_replica['state']) == 'UNAVAILABLE'

        # Delete all files -> collection replica should be deleted
        # Old behaviour (doesn't delete the DID)
        cleaner.run(once=True)
        reaper.REGION.invalidate()
        if self.vo:
            reaper.run(once=True,
                       include_rses='vo=%s&(%s)' % (self.vo['vo'], self.rse),
                       greedy=True)
        else:
            reaper.run(once=True, include_rses=self.rse, greedy=True)
        self.rule_client.add_replication_rule([{
            'scope': self.scope,
            'name': self.dataset
        }],
                                              1,
                                              self.rse,
                                              lifetime=-1)
        collection_replica.run(once=True)
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ]
        assert dataset_replica[0]['length'] == 0
        assert dataset_replica[0]['available_length'] == 0
    def test_abacus_collection_replica(self):
        """ ABACUS (COLLECTION REPLICA): Test update of collection replica. """
        self.files = [{
            'did_scope': self.scope,
            'did_name': 'file_' + generate_uuid(),
            'path': file_generator(size=self.file_sizes),
            'rse': self.rse,
            'lifetime': -1
        } for i in range(0, 2)]
        self.did_client.add_did(self.scope,
                                self.dataset,
                                DIDType.DATASET,
                                lifetime=-1)
        self.upload_client.upload(self.files)
        self.did_client.attach_dids(scope=self.scope,
                                    name=self.dataset,
                                    dids=[{
                                        'name': file['did_name'],
                                        'scope': file['did_scope']
                                    } for file in self.files])
        self.rule_client.add_replication_rule([{
            'scope': self.scope,
            'name': self.dataset
        }],
                                              1,
                                              self.rse,
                                              lifetime=-1)
        [os.remove(file['path']) for file in self.files]

        # Check dataset replica after rule creation - initial data
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ][0]
        assert_equal(dataset_replica['bytes'], 0)
        assert_equal(dataset_replica['length'], 0)
        assert_equal(dataset_replica['available_bytes'], 0)
        assert_equal(dataset_replica['available_length'], 0)
        assert_equal(str(dataset_replica['state']), 'UNAVAILABLE')

        # Run Abacus
        collection_replica.run(once=True)

        # Check dataset replica after abacus - abacus should update the collection_replica table from updated_col_rep
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ][0]
        assert_equal(dataset_replica['bytes'],
                     len(self.files) * self.file_sizes)
        assert_equal(dataset_replica['length'], len(self.files))
        assert_equal(dataset_replica['available_bytes'],
                     len(self.files) * self.file_sizes)
        assert_equal(dataset_replica['available_length'], len(self.files))
        assert_equal(str(dataset_replica['state']), 'AVAILABLE')

        # Delete one file -> collection replica should be unavailable
        cleaner.run(once=True)
        delete_replicas(rse_id=self.rse_id,
                        files=[{
                            'name':
                            self.files[0]['did_name'],
                            'scope':
                            InternalScope(self.files[0]['did_scope'],
                                          **self.vo)
                        }])
        self.rule_client.add_replication_rule([{
            'scope': self.scope,
            'name': self.dataset
        }],
                                              1,
                                              self.rse,
                                              lifetime=-1)
        collection_replica.run(once=True)
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ][0]
        assert_equal(dataset_replica['length'], len(self.files))
        assert_equal(dataset_replica['bytes'],
                     len(self.files) * self.file_sizes)
        assert_equal(dataset_replica['available_length'], len(self.files) - 1)
        assert_equal(dataset_replica['available_bytes'],
                     (len(self.files) - 1) * self.file_sizes)
        assert_equal(str(dataset_replica['state']), 'UNAVAILABLE')

        # Delete all files -> collection replica should be deleted
        cleaner.run(once=True)
        reaper.run(once=True, rses=[self.rse], greedy=True)
        self.rule_client.add_replication_rule([{
            'scope': self.scope,
            'name': self.dataset
        }],
                                              1,
                                              self.rse,
                                              lifetime=-1)
        collection_replica.run(once=True)
        dataset_replica = [
            replica for replica in self.replica_client.list_dataset_replicas(
                self.scope, self.dataset)
        ]
        assert_equal(len(dataset_replica), 0)
    def test_api_rse(self):
        """ RSE (API): Test external representation of RSEs """

        out = api_rse.get_rse(self.rse_name, **self.vo)
        assert out['rse'] == self.rse_name
        assert out['id'] == self.rse_id

        out = api_rse.list_rses(**self.new_vo)
        out = list(out)
        assert 0 != len(out)
        rse_ids = [rse['id'] for rse in out]
        assert self.rse3_id in rse_ids
        assert self.rse4_id in rse_ids
        for rse in out:
            assert 'rse' in rse
            if rse['id'] == self.rse3_id:
                assert rse['rse'] == self.rse3_name
            elif rse['id'] == self.rse4_id:
                assert rse['rse'] == self.rse4_name

        key = "KEY_" + generate_uuid()
        api_rse.add_rse_attribute(self.rse_name,
                                  key,
                                  1,
                                  issuer='root',
                                  **self.vo)
        out = api_rse.get_rses_with_attribute(key)
        out = list(out)
        assert 0 != len(out)
        for rse in out:
            assert rse['rse'] == self.rse_name

        out = api_rse.get_rse_protocols(self.rse_name,
                                        issuer='root',
                                        **self.vo)
        assert out['rse'] == self.rse_name

        # add some account and RSE counters
        rse_mock = 'MOCK4'
        rse_mock_id = get_rse_id(rse_mock, **self.vo)
        account_counter.del_counter(rse_id=rse_mock_id, account=self.account)
        account_counter.add_counter(rse_id=rse_mock_id, account=self.account)
        account_counter.increase(rse_id=rse_mock_id,
                                 account=self.account,
                                 files=1,
                                 bytes_=10)
        account_counter.update_account_counter(self.account, rse_mock_id)
        did = 'file_' + generate_uuid()
        add_did(self.scope_name,
                did,
                'DATASET',
                'root',
                account=self.account_name,
                rse=rse_mock,
                **self.vo)
        abacus_rse.run(once=True)

        out = api_rse.get_rse_usage(rse_mock,
                                    per_account=True,
                                    issuer='root',
                                    **self.vo)
        assert rse_mock_id in [o['rse_id'] for o in out]
        for usage in out:
            if usage['rse_id'] == rse_mock_id:
                assert usage['rse'] == rse_mock
                accounts = [u['account'] for u in usage['account_usages']]
                assert self.account_name in accounts
                if self.multi_vo:
                    assert self.account.internal not in accounts

        # clean up files
        cleaner.run(once=True)
        if self.multi_vo:
            reaper.run(once=True,
                       include_rses='vo=%s&(%s)' % (self.vo['vo'], rse_mock),
                       greedy=True)
        else:
            reaper.run(once=True, include_rses=rse_mock, greedy=True)
        abacus_rse.run(once=True)

        out = api_rse.parse_rse_expression(
            '%s|%s' % (self.rse_name, self.rse2_name), **self.vo)
        assert self.rse_name in out
        assert self.rse2_name in out
        assert self.rse_id not in out
        assert self.rse2_id not in out
 def tearDown(self):
     undertaker.run(once=True)
     cleaner.run(once=True)
     reaper.run(once=True, rses=[self.rse], greedy=True)