Example #1
0
def _package_create(request):
    """Create a package."""
    try:
        payload = json.loads(request.body)
        path = base64.b64decode(payload.get('path'))
    except (TypeError, ValueError):
        return helpers.json_response(
            {
                'error': True,
                'message': 'Parameter "path" cannot be decoded.'
            }, 400)
    args = (
        payload.get('name'),
        payload.get('type'),
        payload.get('accession'),
        payload.get('access_system_id'),
        path,
        payload.get('metadata_set_id'),
    )
    kwargs = {
        'auto_approve': payload.get('auto_approve', True),
        'wait_until_complete': False,
    }
    processing_config = payload.get('processing_config')
    if processing_config is not None:
        kwargs['processing_config'] = processing_config
    try:
        client = MCPClient()
        id_ = client.create_package(*args, **kwargs)
    except Exception as err:
        msg = 'Package cannot be created'
        LOGGER.error("{}: {}".format(msg, err))
        return helpers.json_response({'error': True, 'message': msg}, 500)
    return helpers.json_response({'id': id_}, 202)
Example #2
0
def _package_create(request):
    """Create a package."""
    try:
        payload = json.loads(request.body.decode("utf8"))
        path = base64.b64decode(payload.get("path"))
    except (TypeError, ValueError):
        return helpers.json_response(
            {
                "error": True,
                "message": 'Parameter "path" cannot be decoded.'
            }, 400)
    args = (
        payload.get("name"),
        payload.get("type"),
        payload.get("accession"),
        payload.get("access_system_id"),
        path,
        payload.get("metadata_set_id"),
    )
    kwargs = {
        "auto_approve": payload.get("auto_approve", True),
        "wait_until_complete": False,
    }
    processing_config = payload.get("processing_config")
    if processing_config is not None:
        kwargs["processing_config"] = processing_config
    try:
        client = MCPClient(request.user)
        id_ = client.create_package(*args, **kwargs)
    except Exception as err:
        msg = "Package cannot be created"
        LOGGER.error("%s: %s", msg, err)
        return helpers.json_response({"error": True, "message": msg}, 500)
    return helpers.json_response({"id": id_}, 202)
Example #3
0
def complete_matching(request, uuid):
    """Complete the process by moving to the ArchivesSpace upload chain.

    This is the final step that we execute when the user has reviewed the
    matchings and submits the form. It only accepts POST because the action
    performed is not idempotent.
    """
    if request.method != 'POST':
        return HttpResponse(status=405)
    try:
        client = MCPClient(request.user)
        client.execute_unit(
            uuid,
            # Microservice: Upload DIP
            mscl_id="92879a29-45bf-4f0b-ac43-e64474f0f2f9",
            # Chain: Upload DIP to ArchivesSpace
            choice="3572f844-5e69-4000-a24b-4e32d3487f82")
    except Exception as err:
        messages.error(
            request,
            _("Operation failed, please try again later"
              " or contact your administrator."))
        logger.error("Upload DIP to ArchivesSpace failed: %s", err)
        return HttpResponseRedirect(
            reverse(
                "components.ingest.views_as.ingest_upload_as_review_matches",
                args=[uuid]))
    return HttpResponseRedirect(reverse("components.ingest.views.ingest_grid"))
Example #4
0
def approve_transfer_via_mcp(directory, type, user_id):
    error = None

    if (directory != ''):
        # assemble transfer path
        modified_transfer_path = get_modified_standard_transfer_path(type)

        if modified_transfer_path == None:
            error = 'Invalid transfer type.'
        else:
            transfer_path = os.path.join(modified_transfer_path,
                                         directory) + '/'

            # look up job UUID using transfer path
            try:
                job = models.Job.objects.filter(
                    directory=transfer_path,
                    currentstep='Awaiting decision')[0]

                # approve transfer
                client = MCPClient()

                # 3rd arg should be uid?
                result = client.execute(job.pk, 'Approve', user_id)

            except:
                error = 'Unable to find unapproved transfer directory.'

    else:
        error = 'Please specify a transfer directory.'

    return error
Example #5
0
def approve_transfer_via_mcp(directory, type, user_id):
    error = None

    if (directory != ''):
        # assemble transfer path
        modified_transfer_path = get_modified_standard_transfer_path(type)

        if modified_transfer_path == None:
            error = 'Invalid transfer type.'
        else:
            transfer_path = os.path.join(modified_transfer_path, directory) + '/'

            # look up job UUID using transfer path
            try:
                job = models.Job.objects.filter(directory=transfer_path, currentstep='Awaiting decision')[0]

                # approve transfer
                client = MCPClient()

                # 3rd arg should be uid?
                result = client.execute(job.pk, 'Approve', user_id)

            except:
                error = 'Unable to find unapproved transfer directory.'

    else:
        error = 'Please specify a transfer directory.'

    return error
Example #6
0
def execute(request):
    result = ""
    if "uuid" in request.REQUEST:
        client = MCPClient()
        uuid = request.REQUEST.get("uuid", "")
        choice = request.REQUEST.get("choice", "")
        result = client.execute(uuid, choice)
    return HttpResponse(result, mimetype="text/plain")
Example #7
0
def execute(request):
    result = ""
    if request.POST.get("uuid"):
        client = MCPClient(request.user)
        result = client.execute(
            request.POST.get("uuid"), request.POST.get("choice", "")
        )
    return HttpResponse(result, content_type="text/plain")
def execute(request):
    result = ''
    if 'uuid' in request.REQUEST:
        client = MCPClient()
        uuid = request.REQUEST.get('uuid', '')
        choice = request.REQUEST.get('choice', '')
        result = client.execute(uuid, choice)
    return HttpResponse(result, mimetype = 'text/plain')
Example #9
0
def ingest_status(request, uuid=None):
    # Equivalent to: "SELECT SIPUUID, MAX(createdTime) AS latest FROM Jobs WHERE unitType='unitSIP' GROUP BY SIPUUID
    objects = models.Job.objects.filter(hidden=False, subjobof='').values('sipuuid').annotate(timestamp=Max('createdtime')).exclude(sipuuid__icontains = 'None').filter(unittype__exact = 'unitSIP')
    mcp_available = False
    try:
        client = MCPClient()
        mcp_status = etree.XML(client.list())
        mcp_available = True
    except Exception: pass
    def encoder(obj):
        items = []
        for item in obj:
            # Check if hidden (TODO: this method is slow)
            if models.SIP.objects.is_hidden(item['sipuuid']):
                continue
            jobs = helpers.get_jobs_by_sipuuid(item['sipuuid'])
            item['directory'] = utils.get_directory_name(jobs[0])
            item['timestamp'] = calendar.timegm(item['timestamp'].timetuple())
            item['uuid'] = item['sipuuid']
            item['id'] = item['sipuuid']
            del item['sipuuid']
            item['jobs'] = []
            for job in jobs:
                newJob = {}
                item['jobs'].append(newJob)

                # allow user to know name of file that has failed normalization
                if job.jobtype == 'Access normalization failed - copying' or job.jobtype == 'Preservation normalization failed - copying' or job.jobtype == 'thumbnail normalization failed - copying':
                    task = models.Task.objects.get(job=job)
                    newJob['filename'] = task.filename

                newJob['uuid'] = job.jobuuid
                newJob['type'] = job.jobtype
                newJob['microservicegroup'] = job.microservicegroup
                newJob['subjobof'] = job.subjobof
                newJob['currentstep'] = job.currentstep
                newJob['timestamp'] = '%d.%s' % (calendar.timegm(job.createdtime.timetuple()), str(job.createdtimedec).split('.')[-1])
                try: mcp_status
                except NameError: pass
                else:
                    xml_unit = mcp_status.xpath('choicesAvailableForUnit[UUID="%s"]' % job.jobuuid)
                    if xml_unit:
                        xml_unit_choices = xml_unit[0].findall('choices/choice')
                        choices = {}
                        for choice in xml_unit_choices:
                            choices[choice.find("chainAvailable").text] = choice.find("description").text
                        newJob['choices'] = choices
            items.append(item)
        return items

    response = {}
    response['objects'] = objects
    response['mcp'] = mcp_available

    return HttpResponse(
        simplejson.JSONEncoder(default=encoder).encode(response),
        mimetype='application/json'
    )
Example #10
0
def ingest_status(request, uuid=None):
    # Equivalent to: "SELECT SIPUUID, MAX(createdTime) AS latest FROM Jobs WHERE unitType='unitSIP' GROUP BY SIPUUID
    objects = models.Job.objects.filter(hidden=False, subjobof='').values('sipuuid').annotate(timestamp=Max('createdtime')).exclude(sipuuid__icontains = 'None').filter(unittype__exact = 'unitSIP')
    mcp_available = False
    try:
        client = MCPClient()
        mcp_status = etree.XML(client.list())
        mcp_available = True
    except Exception: pass
    def encoder(obj):
        items = []
        for item in obj:
            # Check if hidden (TODO: this method is slow)
            if models.SIP.objects.is_hidden(item['sipuuid']):
                continue
            jobs = helpers.get_jobs_by_sipuuid(item['sipuuid'])
            item['directory'] = utils.get_directory_name_from_job(jobs[0])
            item['timestamp'] = calendar.timegm(item['timestamp'].timetuple())
            item['uuid'] = item['sipuuid']
            item['id'] = item['sipuuid']
            del item['sipuuid']
            item['jobs'] = []
            for job in jobs:
                newJob = {}
                item['jobs'].append(newJob)

                # allow user to know name of file that has failed normalization
                if job.jobtype == 'Access normalization failed - copying' or job.jobtype == 'Preservation normalization failed - copying' or job.jobtype == 'thumbnail normalization failed - copying':
                    task = models.Task.objects.get(job=job)
                    newJob['filename'] = task.filename

                newJob['uuid'] = job.jobuuid
                newJob['type'] = job.jobtype
                newJob['microservicegroup'] = job.microservicegroup
                newJob['subjobof'] = job.subjobof
                newJob['currentstep'] = job.currentstep
                newJob['timestamp'] = '%d.%s' % (calendar.timegm(job.createdtime.timetuple()), str(job.createdtimedec).split('.')[-1])
                try: mcp_status
                except NameError: pass
                else:
                    xml_unit = mcp_status.xpath('choicesAvailableForUnit[UUID="%s"]' % job.jobuuid)
                    if xml_unit:
                        xml_unit_choices = xml_unit[0].findall('choices/choice')
                        choices = {}
                        for choice in xml_unit_choices:
                            choices[choice.find("chainAvailable").text] = choice.find("description").text
                        newJob['choices'] = choices
            items.append(item)
        return items

    response = {}
    response['objects'] = objects
    response['mcp'] = mcp_available

    return HttpResponse(
        json.JSONEncoder(default=encoder).encode(response),
        content_type='application/json'
    )
Example #11
0
def list(request):
    client = MCPClient(request.user)
    jobs = etree.XML(client.list())
    response = ""
    if 0 < len(jobs):
        for job in jobs:
            response += etree.tostring(job)
    response = "<MCP>%s</MCP>" % response
    return HttpResponse(response, content_type="text/xml")
Example #12
0
def execute(request):
    result = ''
    if request.POST.get('uuid'):
        client = MCPClient(request.user)
        result = client.execute(
            request.POST.get('uuid'),
            request.POST.get('choice', ''),
        )
    return HttpResponse(result, content_type='text/plain')
Example #13
0
def execute(request):
    result = ''
    if 'uuid' in request.REQUEST:
        client = MCPClient()
        uuid = request.REQUEST.get('uuid', '')
        choice = request.REQUEST.get('choice', '')
        uid = request.REQUEST.get('uid', '')
        result = client.execute(uuid, choice, uid)
    return HttpResponse(result, mimetype='text/plain')
Example #14
0
def approve_transfer_via_mcp(directory, type, user_id):
    error = None

    if (directory != ''):
        # assemble transfer path
        modified_transfer_path = get_modified_standard_transfer_path(type)

        if modified_transfer_path == None:
            error = 'Invalid transfer type.'
        else:
            if type == 'zipped bag':
                transfer_path = os.path.join(modified_transfer_path, directory)
            else:
                transfer_path = os.path.join(modified_transfer_path, directory) + '/'

            # look up job UUID using transfer path
            try:
                job = models.Job.objects.filter(directory=transfer_path, currentstep='Awaiting decision')[0]

                type_task_config_descriptions = {
                    'standard':     'Approve standard transfer',
                    'unzipped bag': 'Approve bagit transfer',
                    'zipped bag':   'Approve zipped bagit transfer',
                    'dspace':       'Approve DSpace transfer',
                    'maildir':      'Approve maildir transfer',
                    'TRIM':         'Approve TRIM transfer'
                }

                type_description = type_task_config_descriptions[type]

                # use transfer type to fetch possible choices to execute
                task = models.TaskConfig.objects.get(description=type_description)
                link = models.MicroServiceChainLink.objects.get(currenttask=task.pk)
                choices = models.MicroServiceChainChoice.objects.filter(choiceavailableatlink=link.pk)

                # attempt to find appropriate choice
                chain_to_execute = None
                for choice in choices:
                    chain = models.MicroServiceChain.objects.get(pk=choice.chainavailable)
                    if chain.description == 'Approve transfer':
                        chain_to_execute=chain.pk

                # execute choice if found
                if chain_to_execute != None:
                    client = MCPClient()

                    result = client.execute(job.pk, chain_to_execute, user_id)
                else:
                    error = 'Error: could not find MCP choice to execute.'

            except:
                error = 'Unable to find unapproved transfer directory.'

    else:
        error = 'Please specify a transfer directory.'

    return error
def list(request):
    client = MCPClient()
    jobs = etree.XML(client.list())
    response = ''
    if 0 < len(jobs):
        for job in jobs:
            response += etree.tostring(job)
    response = '<MCP>%s</MCP>' % response
    return HttpResponse(response, mimetype = 'text/xml')
Example #16
0
def list(request):
    client = MCPClient()
    jobs = etree.XML(client.list())
    response = ''
    if 0 < len(jobs):
        for job in jobs:
            response += etree.tostring(job)
    response = '<MCP>%s</MCP>' % response
    return HttpResponse(response, mimetype='text/xml')
Example #17
0
def status(request, uuid=None):
    response = {"objects": {}, "mcp": False}
    try:
        client = MCPClient(request.user)
        response["objects"] = client.get_transfers_statuses()
    except Exception:
        pass
    else:
        response["mcp"] = True
    return HttpResponse(json.dumps(response), content_type="application/json")
Example #18
0
def reingest_approve(request):
    """Approve an AIP partial re-ingest.

    - Method:      POST
    - URL:         api/ingest/reingest/approve
    - POST params:
                   - username -- AM username
                   - api_key  -- AM API key
                   - uuid     -- SIP UUID

    TODO: this is just a temporary way of getting the API to do the
    equivalent of clicking "Approve AIP reingest" in the dashboard when faced
    with "Approve AIP reingest". This is non-dry given
    ``approve_transfer_via_mcp`` above and should probably me made congruent
    with that function and ``approve_transfer``.
    """
    sip_uuid = request.POST.get('uuid')
    if sip_uuid is None:
        response = {'error': True, 'message': '"uuid" is required.'}
        return helpers.json_response(response, status_code=400)
    job = models.Job.objects.filter(
        sipuuid=sip_uuid,
        microservicegroup='Reingest AIP',
        currentstep=models.Job.STATUS_AWAITING_DECISION).first()
    if job:
        chain = models.MicroServiceChainChoice.objects.filter(
            choiceavailableatlink__currenttask__description=
            'Approve AIP reingest',
            chainavailable__description='Approve AIP reingest').first()

        if chain:
            approve_aip_reingest_choice_uuid = chain.chainavailable.pk
            client = MCPClient()
            client.execute(job.pk, approve_aip_reingest_choice_uuid,
                           request.user.id)

            response = {'message': 'Approval successful.'}
        else:
            # No choice was found.
            response = {
                'error': True,
                'message': 'Could not find choice for approve AIP reingest'
            }
            return helpers.json_response(response, status_code=400)

        return helpers.json_response(response)
    else:
        # No job to be found.
        response = {
            'error':
            True,
            'message': ('There is no "Reingest AIP" job awaiting a'
                        ' decision for SIP {}'.format(sip_uuid))
        }
        return helpers.json_response(response, status_code=400)
Example #19
0
def status(request):
    client = MCPClient()
    xml = etree.XML(client.list())

    sip_count = len(xml.xpath('//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="SIP"]'))
    transfer_count = len(xml.xpath('//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="Transfer"]'))
    dip_count = len(xml.xpath('//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="DIP"]'))

    response = {'sip': sip_count, 'transfer': transfer_count, 'dip': dip_count}

    return HttpResponse(simplejson.JSONEncoder().encode(response), mimetype='application/json')
Example #20
0
def status(request):
    client = MCPClient()
    xml = etree.XML(client.list())

    sip_count = len(xml.xpath('//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="SIP"]'))
    transfer_count = len(xml.xpath('//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="Transfer"]'))
    dip_count = len(xml.xpath('//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="DIP"]'))

    response = {'sip': sip_count, 'transfer': transfer_count, 'dip': dip_count}

    return helpers.json_response(response)
Example #21
0
def microservices(request, unit_type, unit_uuid):
    """
    Display information about what microservices have run.

    :param unit_type: 'transfer' or 'ingest' for a Transfer or SIP respectively
    :param unit_uuid: UUID of the Transfer or SIP

    """
    client = MCPClient(request.user)
    resp = client.get_unit_status(unit_uuid)
    return render(request, unit_type + '/microservices.html', {
        'uuid': unit_uuid,
        'unit_type': unit_type,
        'name': resp.get("name"),
        'jobs': resp.get("jobs"),
    })
Example #22
0
def approve_transfer(request):
    """Approve a transfer.

    The user may find the Package API a better option when the ID of the
    unit is known in advance.

    The errors returned use the 500 status code for backward-compatibility
    reasons.

    Example::

        $ curl --data "directory=MyTransfer" \
               --header "Authorization: ApiKey: user:token" \
               http://127.0.0.1/api/transfer/approve
    """
    directory = request.POST.get("directory")
    if not directory:
        return _error_response(
            "Please specify a transfer directory.", status_code=500)
    directory = archivematicaFunctions.unicodeToStr(directory)
    transfer_type = request.POST.get("type", "standard")
    if not transfer_type:
        return _error_response(
            "Please specify a transfer type.", status_code=500)
    modified_transfer_path = get_modified_standard_transfer_path(transfer_type)
    if modified_transfer_path is None:
        return _error_response("Invalid transfer type.", status_code=500)
    watched_path = os.path.join(modified_transfer_path, directory)
    transfer_file = watched_path.replace(
        SHARED_PATH_TEMPLATE_VAL, SHARED_DIRECTORY_ROOT
    )
    if transfer_type in ("zipped bag", "dspace") and os.path.isfile(transfer_file):
        db_transfer_path = watched_path
    else:
        # Append a slash to complete the directory path.
        db_transfer_path = os.path.join(watched_path, "")
    try:
        client = MCPClient(request.user)
        unit_uuid = client.approve_transfer_by_path(
            db_transfer_path, transfer_type)
    except Exception as err:
        msg = "Unable to start the transfer."
        LOGGER.error("%s %s (db_transfer_path=%s)",
                     msg, err, db_transfer_path)
        return _error_response(msg, status_code=500)
    return _ok_response("Approval successful.", uuid=unit_uuid)
Example #23
0
def reingest_approve(request):
    """Approve an AIP partial re-ingest.

    - Method:      POST
    - URL:         api/ingest/reingest/approve
    - POST params:
                   - username -- AM username
                   - api_key  -- AM API key
                   - uuid     -- SIP UUID
    """
    sip_uuid = request.POST.get('uuid')
    if sip_uuid is None:
        return _error_response('"uuid" is required.')
    try:
        client = MCPClient()
        client.approve_partial_reingest(sip_uuid, request.user.id)
    except Exception as err:
        msg = "Unable to approve the partial reingest."
        LOGGER.error("%s %s (sip_uuid=%s)", msg, err, sip_uuid)
        return _error_response(msg)
    return _ok_response("Approval successful.")
Example #24
0
def status(request):
    client = MCPClient()
    xml = etree.XML(client.list())

    sip_count = len(
        xml.xpath(
            '//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="SIP"]'
        ))
    transfer_count = len(
        xml.xpath(
            '//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="Transfer"]'
        ))
    dip_count = len(
        xml.xpath(
            '//choicesAvailableForUnits/choicesAvailableForUnit/unit/type[text()="DIP"]'
        ))

    response = {'sip': sip_count, 'transfer': transfer_count, 'dip': dip_count}

    return HttpResponse(simplejson.JSONEncoder().encode(response),
                        mimetype='application/json')
Example #25
0
 def _load_processing_config_fields(self, user):
     client = MCPClient(user)
     self.processing_fields = client.get_processing_config_fields()
     for choice_uuid, field in self.processing_fields.items():
         field["label"] = self.LABELS[choice_uuid]
Example #26
0
def ingest_status(request, uuid=None):
    """Returns the status of the SIPs in ingest as a JSON object with an
    ``objects`` attribute that is an array of objects, each of which represents
    a single SIP. Each SIP object has a ``jobs`` attribute whose value is an
    array of objects, each of which represents a Job of the SIP.
    """
    sql = """
        SELECT SIPUUID,
                MAX(UNIX_TIMESTAMP(createdTime) + createdTimeDec) AS timestamp
            FROM Jobs
            WHERE unitType='unitSIP' AND NOT SIPUUID LIKE '%%None%%'
            GROUP BY SIPUUID;"""
    with connection.cursor() as cursor:
        cursor.execute(sql)
        sipuuids_and_timestamps = cursor.fetchall()
    mcp_available = False
    try:
        client = MCPClient()
        mcp_status = etree.XML(client.list())
        mcp_available = True
    except Exception:
        pass
    objects = []
    for sipuuid, timestamp in sipuuids_and_timestamps:
        timestamp = float(timestamp)
        item = {'sipuuid': sipuuid, 'timestamp': timestamp}
        # Check if hidden (TODO: this method is slow)
        if models.SIP.objects.is_hidden(sipuuid):
            continue
        jobs = models.Job.objects\
            .filter(sipuuid=item['sipuuid'], subjobof='')\
            .order_by('-createdtime', 'subjobof')
        item['directory'] = utils.get_directory_name_from_job(jobs)
        item['uuid'] = item['sipuuid']
        item['id'] = item['sipuuid']
        del item['sipuuid']
        item['jobs'] = []
        for job in jobs:
            newJob = {}
            item['jobs'].append(newJob)
            newJob['uuid'] = job.jobuuid
            newJob['type'] = job.jobtype
            newJob['microservicegroup'] = job.microservicegroup
            newJob['subjobof'] = job.subjobof
            newJob['currentstep'] = job.currentstep
            newJob['currentstep_label'] = job.get_currentstep_display()
            newJob['timestamp'] = '%d.%s' % (calendar.timegm(
                job.createdtime.timetuple()), str(
                    job.createdtimedec).split('.')[-1])
            try:
                mcp_status
            except NameError:
                pass
            else:
                xml_unit = mcp_status.xpath(
                    'choicesAvailableForUnit[UUID="%s"]' % job.jobuuid)
                if xml_unit:
                    xml_unit_choices = xml_unit[0].findall('choices/choice')
                    choices = {}
                    for choice in xml_unit_choices:
                        choices[choice.find("chainAvailable").
                                text] = choice.find("description").text
                    newJob['choices'] = choices
        objects.append(item)
    response = {}
    response['objects'] = objects
    response['mcp'] = mcp_available
    return HttpResponse(json.dumps(response), content_type='application/json')
Example #27
0
def approve_transfer_via_mcp(directory, transfer_type, user_id):
    error = None
    unit_uuid = None
    if (directory != ''):
        # assemble transfer path
        modified_transfer_path = get_modified_standard_transfer_path(
            transfer_type)

        if modified_transfer_path is None:
            error = 'Invalid transfer type.'
        else:
            db_transfer_path = os.path.join(modified_transfer_path, directory)
            transfer_path = db_transfer_path.replace('%sharedPath%',
                                                     SHARED_DIRECTORY_ROOT, 1)
            # Ensure directories end with /
            if os.path.isdir(transfer_path):
                db_transfer_path = os.path.join(db_transfer_path, '')
            # look up job UUID using transfer path
            try:
                job = models.Job.objects.filter(
                    directory=db_transfer_path,
                    currentstep='Awaiting decision')[0]
                unit_uuid = job.sipuuid

                type_task_config_descriptions = {
                    'standard': 'Approve standard transfer',
                    'unzipped bag': 'Approve bagit transfer',
                    'zipped bag': 'Approve zipped bagit transfer',
                    'dspace': 'Approve DSpace transfer',
                    'maildir': 'Approve maildir transfer',
                    'TRIM': 'Approve TRIM transfer'
                }

                type_description = type_task_config_descriptions[transfer_type]

                # use transfer type to fetch possible choices to execute
                choices = models.MicroServiceChainChoice.objects.filter(
                    choiceavailableatlink__currenttask__description=
                    type_description)

                # attempt to find appropriate choice
                chain_to_execute = None
                for choice in choices:
                    if choice.chainavailable.description == 'Approve transfer':
                        chain_to_execute = choice.chainavailable.pk

                # execute choice if found
                if chain_to_execute is not None:
                    client = MCPClient()
                    client.execute(job.pk, chain_to_execute, user_id)
                else:
                    error = 'Error: could not find MCP choice to execute.'

            except Exception:
                error = 'Unable to find unapproved transfer directory.'
                # logging.exception(error)

    else:
        error = 'Please specify a transfer directory.'

    return error, unit_uuid
Example #28
0
def status(request, uuid=None):
    # Equivalent to: "SELECT SIPUUID, MAX(createdTime) AS latest FROM Jobs GROUP BY SIPUUID
    objects = models.Job.objects.filter(
        hidden=False, subjobof='',
        unittype__exact='unitTransfer').values('sipuuid').annotate(
            timestamp=Max('createdtime')).exclude(
                sipuuid__icontains='None').order_by('-timestamp')
    mcp_available = False
    try:
        client = MCPClient()
        mcp_status = etree.XML(client.list())
        mcp_available = True
    except Exception:
        pass

    def encoder(obj):
        items = []
        for item in obj:
            # Check if hidden (TODO: this method is slow)
            if models.Transfer.objects.is_hidden(item['sipuuid']):
                continue
            jobs = models.Job.objects.filter(sipuuid=item['sipuuid'],
                                             subjobof='').order_by(
                                                 '-createdtime', 'subjobof')
            item['directory'] = os.path.basename(
                utils.get_directory_name_from_job(jobs))
            item['timestamp'] = calendar.timegm(item['timestamp'].timetuple())
            item['uuid'] = item['sipuuid']
            item['id'] = item['sipuuid']
            del item['sipuuid']
            item['jobs'] = []
            for job in jobs:
                newJob = {}
                item['jobs'].append(newJob)
                newJob['uuid'] = job.jobuuid
                newJob['type'] = job.jobtype
                newJob['link_id'] = job.microservicechainlink.pk
                newJob['microservicegroup'] = job.microservicegroup
                newJob['subjobof'] = job.subjobof
                newJob['currentstep'] = job.currentstep
                newJob['currentstep_label'] = job.get_currentstep_display()
                newJob['timestamp'] = '%d.%s' % (calendar.timegm(
                    job.createdtime.timetuple()), str(
                        job.createdtimedec).split('.')[-1])
                try:
                    mcp_status
                except NameError:
                    pass
                else:
                    xml_unit = mcp_status.xpath(
                        'choicesAvailableForUnit[UUID="%s"]' % job.jobuuid)
                    if xml_unit:
                        xml_unit_choices = xml_unit[0].findall(
                            'choices/choice')
                        choices = {}
                        for choice in xml_unit_choices:
                            choices[choice.find("chainAvailable").
                                    text] = choice.find("description").text
                        newJob['choices'] = choices
            items.append(item)
        return items

    response = {}
    response['objects'] = objects
    response['mcp'] = mcp_available
    return HttpResponse(json.JSONEncoder(default=encoder).encode(response),
                        content_type='application/json')
Example #29
0
from tastypie.resources import Resource
from tastypie import fields
from tastypie.bundle import Bundle
from main import models
#useful references: 
# https://docs.djangoproject.com/en/dev/topics/db/models/
# http://www.youtube.com/watch?v=Zv26xHYlc8s
# http://django-tastypie.readthedocs.org/en/latest/non_orm_data_sources.html
# http://stackoverflow.com/questions/13094835/how-to-use-tastypie-to-wrap-internal-functions
# http://django-tastypie.readthedocs.org/en/v0.9.11/cookbook.html#adding-search-functionality
# http://django-tastypie.readthedocs.org/en/latest/resources.html

#http://localhost/api/SelectionAvailable/?format=json
#http://localhost/api/SelectionAPI/?format=json

mcpClient = MCPClient()

class SelectionAPIObject(object):
    def __init__(self, initial=None):
        self.__dict__['_data'] = {}

        if hasattr(initial, 'items'):
            self.__dict__['_data'] = initial

    def __getattr__(self, name):
        return self._data.get(name, None)

    def __setattr__(self, name, value):
        self.__dict__['_data'][name] = value

    def to_dict(self):