def oais_start_transfer(uuid, accession_id='', archivematica_id=None):
    """Archive a sip.

    This function should be called to start a transfer to archive a sip.
    Once the transfer is finished, you should call
    :py:func:`invenio_archivematica.tasks.oais_finish_transfer`.

    The signal :py:data:`invenio_archivematica.signals.oais_transfer_started`
    is called with the sip as function parameter.

    :param str uuid: the UUID of the sip to archive
    :param str accession_id: the AIP accession ID. You can generate one from
    :py:func:`invenio_archivematica.factories.create_accession_id`
    """
    # we get the sip
    sip = SIP.get_sip(uuid)
    # we register the sip as being processed
    ark = Archive.get_from_sip(uuid)
    if not ark:
        ark = Archive.create(sip.model)
    ark.accession_id = accession_id
    ark.status = ArchiveStatus.WAITING
    # we start the transfer
    imp = current_app.config['ARCHIVEMATICA_TRANSFER_FACTORY']
    transfer = import_string(imp)
    ret = transfer(sip.id, current_app.config['ARCHIVEMATICA_TRANSFER_FOLDER'])
    if ret == 0:
        db.session.commit()
        oais_transfer_started.send(sip)
        return
    oais_fail_transfer(uuid, accession_id)
Пример #2
0
def test_Archive(db):
    """Test the Archive model class."""
    assert Archive.query.count() == 0
    # we create an SIP, it will automatically create an Archive via signals
    user = create_test_user('*****@*****.**')
    sip = SIP.create(True, user_id=user.id, agent={'test': 'test'})
    db.session.commit()

    assert Archive.query.count() == 1
    ark = Archive.get_from_sip(sip.id)
    assert ark.sip.user.id == sip.user.id
    assert ark.status == ArchiveStatus.NEW
    assert ark.accession_id is None
    assert ark.archivematica_id is None
    # let's change the object
    ark.status = ArchiveStatus.REGISTERED
    ark.accession_id = '08'
    ark.archivematica_id = sip.id
    db.session.commit()
    ark = Archive.get_from_accession_id('08')
    assert Archive.query.count() == 1
    assert ark.status == ArchiveStatus.REGISTERED
    assert ark.archivematica_id == sip.id
    # we try to get a non existing record
    assert Archive.get_from_sip(uuid.uuid4()) is None
Пример #3
0
def test_oais_fail_transfer(db):
    """Test the oais_fail_transfer function."""
    # let's create a SIP
    sip = SIP.create()
    Archive.create(sip)
    db.session.commit()
    # we fail the transfer
    oais_fail_transfer(sip.id)
    assert Archive.query.count() == 1
    ark = Archive.get_from_sip(sip.id)
    assert ark.status == ArchiveStatus.FAILED
Пример #4
0
def test_oais_process_transfer(db):
    """Test the oais_process_transfer function."""
    # let's create a SIP
    sip = SIP.create()
    Archive.create(sip)
    db.session.commit()
    aipid = uuid.uuid4()
    oais_process_transfer(sip.id, archivematica_id=aipid)
    assert Archive.query.count() == 1
    ark = Archive.get_from_sip(sip.id)
    assert ark.status == ArchiveStatus.PROCESSING_TRANSFER
    assert ark.archivematica_id == aipid
Пример #5
0
def test_oais_finish_transfer(db):
    """Test the oais_finish_transfer function."""
    # let's create a SIP
    sip = SIP.create()
    Archive.create(sip)
    aipid = uuid.uuid4()
    db.session.commit()
    # we finish the transfer
    oais_finish_transfer(sip.id, archivematica_id=aipid)
    assert Archive.query.count() == 1
    ark = Archive.get_from_sip(sip.id)
    assert ark.status == ArchiveStatus.REGISTERED
    assert ark.archivematica_id == aipid
    assert ark.sip.archived is True
Пример #6
0
def test_Archive_get_realstatus_transfer(db, client, oauth2):
    """Test the Archive's get method with transfer processing."""
    sip = SIP.create()
    ark = Archive.create(sip=sip,
                         accession_id='id',
                         archivematica_id=uuid.uuid4())
    ark.status = ArchiveStatus.WAITING
    db.session.commit()

    mock_response = Response()
    mock_response.status_code = 200
    mock_response._content = json.dumps({
        'status': 'SIP_PROCESSING'
    }).encode('utf-8')
    with patch('requests.get', return_value=mock_response):
        response = client.get(url_for('invenio_archivematica_api.archive_api',
                                      accession_id=ark.accession_id,
                                      access_token=oauth2.token),
                              data=json.dumps({'realStatus': True}),
                              content_type='application/json')
    assert response.status_code == 200
    result = json.loads(response.data.decode('utf-8'))
    assert 'sip_id' in result and result['sip_id'] == str(sip.id)
    assert 'status' in result and result['status'] == 'PROCESSING_TRANSFER'
    assert 'accession_id' in result and result['accession_id'] == 'id'
    assert 'archivematica_id' in result \
        and result['archivematica_id'] == str(ark.archivematica_id)
Пример #7
0
def transfer_demo(uuid, config):
    """Transfer the files contained in the sip to the destination.

    Very similar to the rsync transfer. However, because of time, I use the
    VERY UNSECURE sshpass package for rsync authentication.
    DO NOT USE IN PROD!!!

    :param str uuid: the id of the sip containing files to transfer
    :param dict config: here config must be a dict with the following keys:
        - user - the SSH user
        - password_file - a path where the password is stored
        - remote - the URL or IP of the remote
        - remote_path - where to store files on the remote
        - args - the args for rsync
    """
    # we retrieve the archive and the SIP associated
    sip = SIP.get_sip(uuid)
    ark = Archive.get_from_sip(uuid)

    # we export it to the temp folder
    archiver = BaseArchiver(sip)
    archiver.write_all_files()

    # we rsync it to the remote
    src_path = archiver.get_fullpath('')
    dest_path = join(config['remote_path'], ark.accession_id)
    dest_path = '{}:{}'.format(config['remote'], dest_path)
    ssh_command = 'sshpass -f {filename} ssh -l {user}'.format(
        filename=config['password_file'], user=config['user'])
    return call([
        'rsync', config['args'], '--rsh={}'.format(ssh_command), src_path,
        dest_path
    ])
def listener_sip_created(sip, *args, **kwargs):
    """Create an entry in the database when a sip is created."""
    imp = current_app.config['ARCHIVEMATICA_ISARCHIVABLE_FACTORY']
    is_archivable = import_string(imp) if imp else None
    ark = Archive.create(sip.model)
    if not is_archivable or not is_archivable(sip):
        ark.status = ArchiveStatus.IGNORED
Пример #9
0
def test_create_accessioned_id(db):
    """Test ``create_accessioned_id`` function."""
    # First, we create a SIP
    sip = SIP.create()
    ark = Archive.create(sip)
    db.session.commit()
    accessioned_id = factories.create_accession_id(ark)
    assert accessioned_id == 'CERN-' + str(sip.id)
Пример #10
0
def test_create_accessioned_id(db):
    """Test ``create_accessioned_id`` function."""
    # First, we create a SIP
    sip = SIP.create()
    ark = Archive.create(sip)
    db.session.commit()
    accessioned_id = factories.create_accession_id(ark)
    assert accessioned_id \
        == current_app.config['ARCHIVEMATICA_ORGANIZATION_NAME'] + '-' \
        + str(sip.id)
Пример #11
0
def test_ArchiveDownload_get_412(db, client, oauth2):
    """Test the Download's get method with no archivematica_id."""
    sip = SIP.create()
    ark = Archive.create(sip=sip, accession_id='id')
    db.session.commit()

    response = client.get(
        url_for('invenio_archivematica_api.download_api',
                accession_id=ark.accession_id,
                access_token=oauth2.token))
    assert response.status_code == 412
Пример #12
0
def test_ArchiveDownload_get_520(db, client, oauth2):
    """Test the Download's get method with no storage server running."""
    sip = SIP.create()
    ark = Archive.create(sip=sip,
                         accession_id='id',
                         archivematica_id=uuid.uuid4())
    ark.status = ArchiveStatus.REGISTERED
    db.session.commit()
    response = client.get(
        url_for('invenio_archivematica_api.download_api',
                accession_id=ark.accession_id,
                access_token=oauth2.token))
    assert response.status_code == 520
Пример #13
0
def archive_directory_builder(sip):
    """Build a directory structure for the archived SIP.

    Creates a structure that is based on the Archive object linked to the SIP.
    It takes its accession_id. In case no Archive object exists, it returns
    the ID of the SIP.
    :param sip: SIP which is to be archived
    :type SIP: invenio_sipstore.models.SIP
    :returns: list of str
    """
    ark = Archive.get_from_sip(sip.id)
    if not ark and not ark.accession_id:
        return [str(sip.id)]
    return [ark.accession_id]
Пример #14
0
def test_archive_new_sips(db, location):
    """Test the archive_new_sips function."""
    # we create 2 SIP
    sip1 = SIP.create()
    Archive.create(sip1)
    db.session.commit()
    time.sleep(3)
    sip2 = SIP.create()
    Archive.create(sip2)
    db.session.commit()
    # we archive all records older than 2 seconds
    archive_new_sips('invenio_archivematica.factories.create_accession_id',
                     days=0,
                     seconds=2,
                     delay=False)
    arks = Archive.query.all()
    assert len(arks) == 2
    for ark in arks:
        if ark.sip_id == sip1.id:
            assert ark.status == ArchiveStatus.WAITING
            # we update the archive so it will be ignored in what follows
            ark.status = ArchiveStatus.IGNORED
            db.session.commit()
        else:
            assert ark.status == ArchiveStatus.NEW
    # now we archive everything, but rec2 shouldn't be archived as it is
    # flagged as IGNORED
    archive_new_sips('invenio_archivematica.factories.create_accession_id',
                     days=0,
                     delay=False)
    arks = Archive.query.all()
    assert len(arks) == 2
    for ark in arks:
        if ark.sip_id == sip1.id:
            assert ark.status == ArchiveStatus.IGNORED
        else:
            assert ark.status == ArchiveStatus.WAITING
Пример #15
0
def test_listeners(conf, expected_status, app, db):
    """Test listener_sip_created and listener_record_updated functions."""
    # first we change the is_archivable function
    app.config['ARCHIVEMATICA_ISARCHIVABLE_FACTORY'] = conf

    assert Archive.query.count() == 0
    # let's create an SIP
    user = create_test_user('*****@*****.**')
    sip = SIP.create(True, user_id=user.id, agent={'test': 'test'})
    db.session.commit()

    assert Archive.query.count() == 1
    ark = Archive.get_from_sip(sip.id)
    assert ark.sip.user.id == sip.user.id
    assert ark.status == expected_status
Пример #16
0
def test_oais_start_transfer(app, db, location):
    """Test the oais_start_transfer function."""
    assert Archive.query.count() == 0
    # let's create a SIP
    sip = SIP.create()
    Archive.create(sip)
    db.session.commit()
    assert Archive.query.count() == 1
    # we start the transfer
    oais_start_transfer(sip.id, '1991')
    ark = Archive.get_from_sip(sip.id)
    assert ark.status == ArchiveStatus.WAITING
    assert ark.accession_id == '1991'
    # we try the case where no archive exist and transfer fails
    db.session.delete(ark)
    db.session.commit()
    app.config['ARCHIVEMATICA_TRANSFER_FACTORY'] = 'helpers:transfer_fail'
    assert Archive.query.count() == 0
    oais_start_transfer(sip.id, '1991')
    ark = Archive.get_from_sip(sip.id)
    assert Archive.query.count() == 1
    assert ark.status == ArchiveStatus.FAILED
    assert ark.accession_id == '1991'
    assert ark.sip.archived is False
Пример #17
0
def test_ArchiveDownload_get_status_code(db, client, oauth2):
    """Test the API request for Download's get method."""
    sip = SIP.create()
    ark = Archive.create(sip=sip,
                         accession_id='id',
                         archivematica_id=uuid.uuid4())
    ark.status = ArchiveStatus.REGISTERED
    db.session.commit()
    mock_response = Response()
    mock_response.status_code = 404
    with patch('requests.get', return_value=mock_response):
        response = client.get(
            url_for('invenio_archivematica_api.download_api',
                    accession_id=ark.accession_id,
                    access_token=oauth2.token))
    assert response.status_code == mock_response.status_code
Пример #18
0
def test_Archive_get_status_code(db, client, oauth2):
    """Test the Archive's get method with error on Archivematica."""
    sip = SIP.create()
    ark = Archive.create(sip=sip,
                         accession_id='id',
                         archivematica_id=uuid.uuid4())
    ark.status = ArchiveStatus.WAITING
    db.session.commit()
    mock_response = Response()
    mock_response.status_code = 404
    with patch('requests.get', return_value=mock_response):
        response = client.get(url_for('invenio_archivematica_api.archive_api',
                                      accession_id=ark.accession_id,
                                      access_token=oauth2.token),
                              data=json.dumps({'realStatus': True}),
                              content_type='application/json')
    assert response.status_code == mock_response.status_code
Пример #19
0
def oais_fail_transfer(uuid, accession_id='', archivematica_id=None):
    """Mark the transfer as failed.

    This function should be called if the transfer failed. See
    :py:func:`invenio_archivematica.tasks.oais_start_transfer`.

    The signal :py:data:`invenio_archivematica.signals.oais_transfer_failed`
    is called with the sip as function parameter.

    :param str uuid: the UUID of the sip
    """
    ark = Archive.get_from_sip(uuid)
    ark.status = ArchiveStatus.FAILED
    ark.sip.archived = False

    db.session.commit()
    oais_transfer_failed.send(SIP(ark.sip))
Пример #20
0
def test_Archive_get_200(db, client, oauth2):
    """Test the Archive's get method with no archivematica_id."""
    sip = SIP.create()
    ark = Archive.create(sip=sip,
                         accession_id='id',
                         archivematica_id=uuid.uuid4())
    db.session.commit()

    response = client.get(
        url_for('invenio_archivematica_api.archive_api',
                accession_id=ark.accession_id,
                access_token=oauth2.token))
    assert response.status_code == 200
    result = json.loads(response.data.decode('utf-8'))
    assert 'sip_id' in result and result['sip_id'] == str(sip.id)
    assert 'status' in result and result['status'] == 'NEW'
    assert 'accession_id' in result and result['accession_id'] == 'id'
    assert 'archivematica_id' in result \
        and result['archivematica_id'] == str(ark.archivematica_id)
Пример #21
0
def oais_process_aip(uuid, accession_id='', archivematica_id=None):
    """Mark the aip in progress.

    This function should be called if the aip is processing. See
    :py:func:`invenio_archivematica.tasks.oais_start_transfer`.

    The signal
    :py:data:`invenio_archivematica.signals.oais_transfer_processing`
    is called with the sip as function parameter.

    :param str uuid: the UUID of the sip
    :param str archivematica_id: the ID of the AIP in Archivematica
    """
    ark = Archive.get_from_sip(uuid)
    ark.status = ArchiveStatus.PROCESSING_AIP
    ark.archivematica_id = archivematica_id

    db.session.commit()
    oais_transfer_processing.send(SIP(ark.sip))
Пример #22
0
def oais_finish_transfer(uuid, accession_id='', archivematica_id=None):
    """Finalize the transfer of a sip.

    This function should be called once the transfer has been finished, to
    mark the sip as correctly archived. See
    :py:func:`invenio_archivematica.tasks.oais_start_transfer`.

    The signal :py:data:`invenio_archivematica.signals.oais_transfer_finished`
    is called with the sip as function parameter.

    :param str uuid: the UUID of the sip
    :param str archivematica_id: the ID in Archivematica of the created AIP
        (should be an UUID)
    """
    ark = Archive.get_from_sip(uuid)
    ark.status = ArchiveStatus.REGISTERED
    ark.archivematica_id = archivematica_id
    ark.sip.archived = True

    db.session.commit()
    oais_transfer_finished.send(SIP(ark.sip))
Пример #23
0
def test_Archive_patch_200(db, client, oauth2):
    """Test the Archive's get method with no archivematica_id."""
    sip = SIP.create()
    ark = Archive.create(sip=sip, accession_id='id')
    db.session.commit()

    params = {'archivematica_id': str(uuid.uuid4()), 'status': 'COMPLETE'}
    response = client.patch(url_for('invenio_archivematica_api.archive_api',
                                    accession_id=ark.accession_id,
                                    access_token=oauth2.token),
                            data=json.dumps(params),
                            content_type='application/json')
    assert response.status_code == 200
    result = json.loads(response.data.decode('utf-8'))
    assert 'sip_id' in result and result['sip_id'] == str(sip.id)
    assert 'status' in result and result['status'] == 'REGISTERED'
    assert 'accession_id' in result and result['accession_id'] == 'id'
    assert 'archivematica_id' in result \
        and result['archivematica_id'] == params['archivematica_id']

    ark = Archive.query.one()
    assert ark.status == ArchiveStatus.REGISTERED
    assert str(ark.archivematica_id) == params['archivematica_id']
Пример #24
0
def test(accession_id):
    """Show a test page."""
    ark = Archive.get_from_accession_id(accession_id)
    return """<DOCTYPE html><html><head></head><body>
    <h1>{}</h1>
    </body></html>""".format(create_accession_id(ark))
Пример #25
0
 def decorate(*args, **kwargs):
     accession_id = kwargs.pop('accession_id')
     archive = Archive_.get_from_accession_id(accession_id)
     if not archive:
         abort(404, 'Accession_id {} not found.'.format(accession_id))
     return f(archive=archive, *args, **kwargs)