Example #1
0
    def _get_repositories_list(obj, eng):
        repositories_to_harvest = repositories
        reposlist_temp = []
        if obj.extra_data["options"]["repository"]:
            repositories_to_harvest = obj.extra_data["options"]["repository"]
        if repositories_to_harvest:
            for reposname in repositories_to_harvest:
                try:
                    reposlist_temp.append(
                        OaiHARVEST.get(OaiHARVEST.name == reposname).one())
                except (MultipleResultsFound, NoResultFound):
                    eng.log.critical(
                        "Repository %s doesn't exit into our database",
                        reposname)
        else:
            reposlist_temp = OaiHARVEST.get(OaiHARVEST.name != "").all()
        true_repo_list = []
        for repo in reposlist_temp:
            true_repo_list.append(repo.to_dict())

        if true_repo_list:
            return true_repo_list
        else:
            eng.halt(
                "No Repository named %s. Impossible to harvest non-existing things."
                % repositories_to_harvest)
Example #2
0
    def _get_repositories_list(obj, eng):
        repositories_to_harvest = repositories
        reposlist_temp = []
        if obj.extra_data["options"]["repository"]:
            repositories_to_harvest = obj.extra_data["options"]["repository"]
        if repositories_to_harvest:
            for reposname in repositories_to_harvest:
                try:
                    reposlist_temp.append(
                        OaiHARVEST.get(OaiHARVEST.name == reposname).one())
                except (MultipleResultsFound, NoResultFound):
                    eng.log.critical(
                        "Repository %s doesn't exit into our database",
                        reposname)
        else:
            reposlist_temp = OaiHARVEST.get(OaiHARVEST.name != "").all()
        true_repo_list = []
        for repo in reposlist_temp:
            true_repo_list.append(repo.to_dict())

        if true_repo_list:
            return true_repo_list
        else:
            eng.halt(
                "No Repository named %s. Impossible to harvest non-existing things."
                % repositories_to_harvest)
Example #3
0
def task_run_core():
    """Core task of oaiharvest.

    This function will run all the operations needed
    to run an oaiharvest task into bibsched.

    :return: :raise InvenioOAIHarvestWarning:
    """
    workflow_id_preservation = 0
    workflow = None
    start_time = time.time()
    list_of_workflow_without_repository = []
    list_of_repository_per_workflow = {}

    repository = task_get_option("repository")
    if not repository:
        workflow_option = task_get_option("workflow")

        if isinstance(workflow_option, list):
            for name in workflow_option:
                if name not in list_of_workflow_without_repository:
                    list_of_workflow_without_repository.append(name)

        else:
            list_of_workflow_without_repository.append(workflow_option)
    else:
        if task_get_option("workflow"):

            workflow_option = task_get_option("workflow")
            if isinstance(workflow_option, list):
                for name in workflow_option:
                    if name not in list_of_repository_per_workflow:
                        list_of_repository_per_workflow[name] = repository

            else:
                list_of_repository_per_workflow[workflow_option] = repository

        elif isinstance(repository, list):

            for name_repository in repository:
                name_workflow = OaiHARVEST.get(
                    OaiHARVEST.name == name_repository).one().workflows
                if name_workflow not in list_of_repository_per_workflow:
                    list_of_repository_per_workflow[name_workflow] = [
                        name_repository]
                else:
                    list_of_repository_per_workflow[name_workflow].append(
                        name_repository)

        else:
            workflow_found = OaiHARVEST.get(
                OaiHARVEST.name == repository).one().workflows
            list_of_repository_per_workflow[workflow_found] = repository
    try:
        if list_of_repository_per_workflow:
            for workflow_to_launch in list_of_repository_per_workflow:
                options = task_get_option(None)
                options["repository"] = list_of_repository_per_workflow[
                    workflow_to_launch]
                workflow = start(workflow_to_launch,
                                 data=[""],
                                 stop_on_error=True,
                                 options=options)
        else:
            for workflow_to_launch in list_of_workflow_without_repository:
                workflow = start(workflow_to_launch,
                                 data=[""],
                                 stop_on_error=True,
                                 options=task_get_option(None))
        if workflow:
            workflow_id_preservation = workflow.uuid
            workflowlog = BibWorkflowEngineLog.query.filter(
                BibWorkflowEngineLog.id_object == workflow.uuid
            ).all()
            for log in workflowlog:
                write_message(log.message)
        execution_time = round(time.time() - start_time, 2)
        write_message("Execution time :" + str(execution_time))
    except WorkflowError as e:
        write_message("ERRORS HAPPENED")
        write_message("____________Workflow log output____________")
        workflow_id_preservation = e.id_workflow
        workflowlog = BibWorkflowEngineLog.query.filter(
            BibWorkflowEngineLog.id_object == e.id_workflow
        ).filter(BibWorkflowEngineLog.log_type >= 40).all()

        for log in workflowlog:
            write_message(log.message)

        for i in e.payload:
            write_message("\n\n____________Workflow " + i + " log output____________")
            workflowlog = BibWorkflowEngineLog.query.filter(
                BibWorkflowEngineLog.id_object == i
            ).filter(BibWorkflowEngineLog.log_type >= 40).all()
            for log in workflowlog:
                write_message(log.message)

        write_message("____________Object log output____________")

        objectlog = BibWorkflowObjectLog.query.filter(
            BibWorkflowObjectLog.id_object == e.id_object
        ).filter(BibWorkflowEngineLog.log_type >= 40).all()

        for log in objectlog:
            write_message(log.message)

        execution_time = round(time.time() - start_time, 2)
        write_message("Execution time :" + str(execution_time))

    # Generate reports
    ticket_queue = task_get_option("create-ticket-in")
    notification_email = task_get_option("notify-email-to")
    workflow_main = Workflow.query.filter(
        Workflow.uuid == workflow_id_preservation
    ).one()

    if ticket_queue or notification_email:

        subject, text = generate_harvest_report(
            workflow_main,
            current_task_id=task_get_task_param("task_id")
        )
        # Create ticket for finished harvest?
        if ticket_queue:
            ticketid = create_ticket(ticket_queue, subject=subject, text=text)
            if ticketid:
                write_message("Ticket %s submitted." % (str(ticketid),))

        # Send e-mail for finished harvest?
        if notification_email:
            send_email(fromaddr=CFG_SITE_SUPPORT_EMAIL,
                       toaddr=notification_email,
                       subject=subject,
                       content=text)

    if workflow_main.counter_error:
        if CFG_OAI_FAILED_HARVESTING_STOP_QUEUE == 0 or \
           not task_get_task_param("sleeptime") or \
           workflow_main.counter_error > 1:
            # Admin want BibSched to stop, or the task is not set to
            # run at a later date: we must stop the queue.
            write_message("An error occurred. Task is configured to stop")
            return False
        else:
            # An error happened, but it can be recovered at next run
            # (task is re-scheduled) and admin set BibSched to
            # continue even after failure.
            write_message("Error occurred, but task is configured to continue")
            if CFG_OAI_FAILED_HARVESTING_EMAILS_ADMIN:
                try:
                    raise InvenioOAIHarvestWarning(
                        "OAIHarvest (task #%s) failed at fully harvesting."
                        " BibSched has NOT been stopped, and OAIHarvest will"
                        " try to recover at next run" %
                        (task_get_task_param("task_id"),)
                    )
                except InvenioOAIHarvestWarning:
                    register_exception(stream='warning', alert_admin=True)
            return True
    else:
        return True
Example #4
0
def main():
    """Start the tool.

    If the command line arguments are those of the 'manual' mode, then
    starts a manual one-time harvesting. Else trigger a BibSched task
    for automated harvesting based on the OAIHarvest admin settings.
    """
    # Let's try to parse the arguments as used in manual harvesting:
    try:

        opts, args = getopt.getopt(sys.argv[1:], "o:v:m:p:i:s:f:u:r:c:k:l:w:",
                                   ["output=",
                                    "verb=",
                                    "method=",
                                    "metadataPrefix=",
                                    "identifier=",
                                    "set=",
                                    "from=",
                                    "until=",
                                    "resumptionToken=",
                                    "certificate=",
                                    "key=",
                                    "user="******"password="******"workflow=",
                                    ])

        # So everything went smoothly: start harvesting in manual mode
        if len([opt for opt, opt_value in opts
                if opt in ['-v', '--verb']]) > 0:
            # verb parameter is given
            http_param_dict = {}
            method = "POST"
            output = ""
            user = None
            password = None
            cert_file = None
            key_file = None
            sets = []
            # get options and arguments
            for opt, opt_value in opts:
                if opt in ["-v", "--verb"]:
                    http_param_dict['verb'] = opt_value
                elif opt in ["-m", '--method']:
                    if opt_value == "GET" or opt_value == "POST":
                        method = opt_value
                elif opt in ["-p", "--metadataPrefix"]:
                    http_param_dict['metadataPrefix'] = opt_value
                elif opt in ["-i", "--identifier"]:
                    http_param_dict['identifier'] = opt_value
                elif opt in ["-s", "--set"]:
                    sets = opt_value.split()
                elif opt in ["-f", "--from"]:
                    http_param_dict['from'] = opt_value
                elif opt in ["-u", "--until"]:
                    http_param_dict['until'] = opt_value
                elif opt in ["-r", "--resumptionToken"]:
                    http_param_dict['resumptionToken'] = opt_value
                elif opt in ["-o", "--output"]:
                    output = opt_value
                elif opt in ["-c", "--certificate"]:
                    cert_file = opt_value
                elif opt in ["-k", "--key"]:
                    key_file = opt_value
                elif opt in ["-l", "--user"]:
                    user = opt_value
                elif opt in ["-w", "--password"]:
                    password = opt_value
                elif opt in ["-V", "--version"]:
                    print(__revision__)
                    sys.exit(0)
                else:
                    usage(1, "Option %s is not allowed" % opt)

            if len(args) > 0:
                base_url = args[-1]
                if not base_url.lower().startswith('http'):
                    base_url = 'http://' + base_url
                (addressing_scheme, network_location, path, dummy1,
                 dummy2, dummy3) = urllib.parse.urlparse(base_url)
                secure = (addressing_scheme == "https")

                if (cert_file and not key_file) or \
                        (key_file and not cert_file):
                    # Both are needed if one specified
                    usage(1, "You must specify both certificate and key files")

                if password and not user:
                    # User must be specified when password is given
                    usage(1, "You must specify a username")
                elif user and not password:
                    if not secure:
                        sys.stderr.write(
                            "*WARNING* Your password will be sent in clear!\n")
                    try:
                        password = getpass.getpass()
                    except KeyboardInterrupt as error:
                        sys.stderr.write("\n%s\n" % (error,))
                        sys.exit(0)

                getter.harvest(network_location, path,
                               http_param_dict, method,
                               output, sets, secure, user,
                               password, cert_file,
                               key_file)

                sys.stderr.write("Harvesting completed at: %s\n\n" %
                                 time.strftime("%Y-%m-%d %H:%M:%S --> ",
                                               time.localtime()))
                return
            else:
                usage(1, "You must specify the URL to harvest")
        else:
            # verb is not given. We will continue with periodic
            # harvesting. But first check if URL parameter is given:
            # if it is, then warn directly now

            if len([opt for opt, opt_value in opts if
                    opt in ['-i', '--identifier']]) == 0 \
                and len(args) > 1 or \
                    (len(args) == 1 and not args[0].isdigit()):
                usage(1, "You must specify the --verb parameter")
    except getopt.error:
        # So could it be that we are using different arguments? Try to
        # start the BibSched task (automated harvesting) and see if it
        # validates
        pass
        # BibSched mode - periodical harvesting
    # Note that the 'help' is common to both manual and automated
    # mode.

    num_of_critical_parameter = 0
    num_of_critical_parameterb = 0
    repositories = []

    for opt in sys.argv[1:]:
        if opt in "-r" or opt in "--repository":
            num_of_critical_parameter += 1
        elif opt in "--workflow":
            num_of_critical_parameterb += 1
        if num_of_critical_parameter > 1 or num_of_critical_parameterb > 1:
            usage(1, "You can't specify twice -r or --workflow")

    if num_of_critical_parameter == 1:
        if "-r" in sys.argv:
            position = sys.argv.index("-r")
        else:
            position = sys.argv.index("--repository")
        repositories = sys.argv[position + 1].split(",")
        if len(repositories) > 1 and \
                ("-i" in sys.argv or "--identifier" in sys.argv):
            usage(1,
                  "It is impossible to harvest an identifier from several "
                  "repositories.")

    if num_of_critical_parameterb == 1:

        position = sys.argv.index("--workflow")
        workflows = sys.argv[position + 1].split(",")

        for workflow_candidate in workflows:
            if workflow_candidate not in registry_workflows:
                usage(1, "The workflow %s doesn't exist." % workflow_candidate)

    if num_of_critical_parameter == 1 and num_of_critical_parameterb == 0:

        for name_repository in repositories:
            try:
                oaiharvest_instance = OaiHARVEST.get(
                    OaiHARVEST.name == name_repository).one()
                if oaiharvest_instance.workflows not in registry_workflows:
                    usage(1,
                          "The repository %s doesn't have a valid workflow specified." % name_repository)
            except orm.exc.NoResultFound:
                usage(1,
                      "The repository %s doesn't exist in our database." % name_repository)

    elif num_of_critical_parameter == 1 and num_of_critical_parameterb == 1:

        for name_repository in repositories:
            try:
                OaiHARVEST.get(OaiHARVEST.name == name_repository).one()
            except orm.exc.NoResultFound:
                usage(1,
                      "The repository %s doesn't exist in our database." % name_repository)

        print("A workflow has been specified, overriding the repository one.")

    task_set_option("repository", None)
    task_set_option("dates", None)
    task_set_option("workflow", None)
    task_set_option("identifiers", None)
    task_init(authorization_action='runoaiharvest',
              authorization_msg="oaiharvest Task Submission",
              description="""
Harvest records from OAI sources.
Manual vs automatic harvesting:
   - Manual harvesting retrieves records from the specified URL,
     with the specified OAI arguments. Harvested records are displayed
     on the standard output or saved to a file, but are not integrated
     into the repository. This mode is useful to 'play' with OAI
     repositories or to build special harvesting scripts.
   - Automatic harvesting relies on the settings defined in the OAI
     Harvest admin interface to periodically retrieve the repositories
     and sets to harvest. It also take care of harvesting only new or
     modified records. Records harvested using this mode are converted
     and integrated into the repository, according to the settings
     defined in the OAI Harvest admin interface.

Examples:
Manual (single-shot) harvesting mode:
   Save to /tmp/z.xml records from CDS added/modified between 2004-04-01
   and 2004-04-02, in MARCXML:
     $ oaiharvest -vListRecords -f2004-04-01 -u2004-04-02 -pmarcxml -o/tmp/z.xml http://cds.cern.ch/oai2d
Automatic (periodical) harvesting mode:
   Schedule daily harvesting of all repositories defined in OAIHarvest admin:
     $ oaiharvest -s 24h
   Schedule daily harvesting of repository 'arxiv', defined in OAIHarvest admin:
     $ oaiharvest -r arxiv -s 24h
   Harvest in 10 minutes from 'pubmed' repository records added/modified
   between 2005-05-05 and 2005-05-10:
     $ oaiharvest -r pubmed -d 2005-05-05:2005-05-10 -t 10m
""",

              help_specific_usage='Manual single-shot harvesting mode:\n'
                                  '  -o, --output         specify output file\n'
                                  '  -v, --verb           OAI verb to be executed\n'
                                  '  -m, --method         http method (default POST)\n'
                                  '  -p, --metadataPrefix metadata format\n'
                                  '  -i, --identifier     OAI identifier\n'
                                  '  -s, --set            OAI set(s). Whitespace-separated list\n'
                                  '  -r, --resuptionToken Resume previous harvest\n'
                                  '  -f, --from           from date (datestamp)\n'
                                  '  -u, --until          until date (datestamp)\n'
                                  '  -c, --certificate    path to public certificate (in case of certificate-based harvesting)\n'
                                  '  -k, --key            path to private key (in case of certificate-based harvesting)\n'
                                  '  -l, --user           username (in case of password-protected harvesting)\n'
                                  '  -w, --password       password (in case of password-protected harvesting)\n'
                                  'Deamon mode (periodical or one-shot harvesting mode):\n'
                                  '  -r, --repository="repo A"[,"repo B"] \t which repositories to harvest (default=all)\n'
                                  '  -d, --dates=yyyy-mm-dd:yyyy-mm-dd \t reharvest given dates only\n'
                                  '  -i, --identifier     OAI identifier if wished to run in as a task.\n'
                                  '  --notify-email-to    Receive notifications on given email on successful upload and/or finished harvest.\n'
                                  '  --workflow       specify the workflow to execute.\n'
                                  '  --create-ticket-in   Provide desired ticketing queue to create a ticket in it on upload and/or finished harvest.\n'
                                  '                       Requires a configured ticketing system (BibCatalog).\n',
              specific_params=(
                  "r:i:d:W",
                  ["repository=", "identifier=", "dates=", "workflow=",
                   "notify-email-to=", "create-ticket-in="]),
              task_submit_elaborate_specific_parameter_fnc=task_submit_elaborate_specific_parameter,
              task_run_fnc=task_run_core)
Example #5
0
def task_run_core():
    """Core task of oaiharvest.

    This function will run all the operations needed
    to run an oaiharvest task into bibsched.

    :return: :raise InvenioOAIHarvestWarning:
    """
    workflow_id_preservation = 0
    workflow = None
    start_time = time.time()
    list_of_workflow_without_repository = []
    list_of_repository_per_workflow = {}

    repository = task_get_option("repository")
    if not repository:
        workflow_option = task_get_option("workflow")

        if isinstance(workflow_option, list):
            for name in workflow_option:
                if name not in list_of_workflow_without_repository:
                    list_of_workflow_without_repository.append(name)

        else:
            list_of_workflow_without_repository.append(workflow_option)
    else:
        if task_get_option("workflow"):

            workflow_option = task_get_option("workflow")
            if isinstance(workflow_option, list):
                for name in workflow_option:
                    if name not in list_of_repository_per_workflow:
                        list_of_repository_per_workflow[name] = repository

            else:
                list_of_repository_per_workflow[workflow_option] = repository

        elif isinstance(repository, list):

            for name_repository in repository:
                name_workflow = OaiHARVEST.get(
                    OaiHARVEST.name == name_repository).one().workflows
                if name_workflow not in list_of_repository_per_workflow:
                    list_of_repository_per_workflow[name_workflow] = [
                        name_repository
                    ]
                else:
                    list_of_repository_per_workflow[name_workflow].append(
                        name_repository)

        else:
            workflow_found = OaiHARVEST.get(
                OaiHARVEST.name == repository).one().workflows
            list_of_repository_per_workflow[workflow_found] = repository
    try:
        if list_of_repository_per_workflow:
            for workflow_to_launch in list_of_repository_per_workflow:
                options = task_get_option(None)
                options["repository"] = list_of_repository_per_workflow[
                    workflow_to_launch]
                workflow = start(workflow_to_launch,
                                 data=[""],
                                 stop_on_error=True,
                                 options=options)
        else:
            for workflow_to_launch in list_of_workflow_without_repository:
                workflow = start(workflow_to_launch,
                                 data=[""],
                                 stop_on_error=True,
                                 options=task_get_option(None))
        if workflow:
            workflow_id_preservation = workflow.uuid
            workflowlog = BibWorkflowEngineLog.query.filter(
                BibWorkflowEngineLog.id_object == workflow.uuid).all()
            for log in workflowlog:
                write_message(log.message)
        execution_time = round(time.time() - start_time, 2)
        write_message("Execution time :" + str(execution_time))
    except WorkflowError as e:
        write_message("ERRORS HAPPENED")
        write_message("____________Workflow log output____________")
        workflow_id_preservation = e.id_workflow
        workflowlog = BibWorkflowEngineLog.query.filter(
            BibWorkflowEngineLog.id_object == e.id_workflow).filter(
                BibWorkflowEngineLog.log_type >= 40).all()

        for log in workflowlog:
            write_message(log.message)

        for i in e.payload:
            write_message("\n\n____________Workflow " + i +
                          " log output____________")
            workflowlog = BibWorkflowEngineLog.query.filter(
                BibWorkflowEngineLog.id_object == i).filter(
                    BibWorkflowEngineLog.log_type >= 40).all()
            for log in workflowlog:
                write_message(log.message)

        write_message("____________Object log output____________")

        objectlog = BibWorkflowObjectLog.query.filter(
            BibWorkflowObjectLog.id_object == e.id_object).filter(
                BibWorkflowEngineLog.log_type >= 40).all()

        for log in objectlog:
            write_message(log.message)

        execution_time = round(time.time() - start_time, 2)
        write_message("Execution time :" + str(execution_time))

    # Generate reports
    ticket_queue = task_get_option("create-ticket-in")
    notification_email = task_get_option("notify-email-to")
    workflow_main = Workflow.query.filter(
        Workflow.uuid == workflow_id_preservation).one()

    if ticket_queue or notification_email:

        subject, text = generate_harvest_report(
            workflow_main, current_task_id=task_get_task_param("task_id"))
        # Create ticket for finished harvest?
        if ticket_queue:
            ticketid = create_ticket(ticket_queue, subject=subject, text=text)
            if ticketid:
                write_message("Ticket %s submitted." % (str(ticketid), ))

        # Send e-mail for finished harvest?
        if notification_email:
            send_email(fromaddr=CFG_SITE_SUPPORT_EMAIL,
                       toaddr=notification_email,
                       subject=subject,
                       content=text)

    if workflow_main.counter_error:
        if CFG_OAI_FAILED_HARVESTING_STOP_QUEUE == 0 or \
           not task_get_task_param("sleeptime") or \
           workflow_main.counter_error > 1:
            # Admin want BibSched to stop, or the task is not set to
            # run at a later date: we must stop the queue.
            write_message("An error occurred. Task is configured to stop")
            return False
        else:
            # An error happened, but it can be recovered at next run
            # (task is re-scheduled) and admin set BibSched to
            # continue even after failure.
            write_message("Error occurred, but task is configured to continue")
            if CFG_OAI_FAILED_HARVESTING_EMAILS_ADMIN:
                try:
                    raise InvenioOAIHarvestWarning(
                        "OAIHarvest (task #%s) failed at fully harvesting."
                        " BibSched has NOT been stopped, and OAIHarvest will"
                        " try to recover at next run" %
                        (task_get_task_param("task_id"), ))
                except InvenioOAIHarvestWarning:
                    register_exception(stream='warning', alert_admin=True)
            return True
    else:
        return True
Example #6
0
def main():
    """Start the tool.

    If the command line arguments are those of the 'manual' mode, then
    starts a manual one-time harvesting. Else trigger a BibSched task
    for automated harvesting based on the OAIHarvest admin settings.
    """
    # Let's try to parse the arguments as used in manual harvesting:
    try:

        opts, args = getopt.getopt(sys.argv[1:], "o:v:m:p:i:s:f:u:r:c:k:l:w:",
                                   [
                                       "output=",
                                       "verb=",
                                       "method=",
                                       "metadataPrefix=",
                                       "identifier=",
                                       "set=",
                                       "from=",
                                       "until=",
                                       "resumptionToken=",
                                       "certificate=",
                                       "key=",
                                       "user="******"password="******"workflow=",
                                   ])

        # So everything went smoothly: start harvesting in manual mode
        if len([opt
                for opt, opt_value in opts if opt in ['-v', '--verb']]) > 0:
            # verb parameter is given
            http_param_dict = {}
            method = "POST"
            output = ""
            user = None
            password = None
            cert_file = None
            key_file = None
            sets = []
            # get options and arguments
            for opt, opt_value in opts:
                if opt in ["-v", "--verb"]:
                    http_param_dict['verb'] = opt_value
                elif opt in ["-m", '--method']:
                    if opt_value == "GET" or opt_value == "POST":
                        method = opt_value
                elif opt in ["-p", "--metadataPrefix"]:
                    http_param_dict['metadataPrefix'] = opt_value
                elif opt in ["-i", "--identifier"]:
                    http_param_dict['identifier'] = opt_value
                elif opt in ["-s", "--set"]:
                    sets = opt_value.split()
                elif opt in ["-f", "--from"]:
                    http_param_dict['from'] = opt_value
                elif opt in ["-u", "--until"]:
                    http_param_dict['until'] = opt_value
                elif opt in ["-r", "--resumptionToken"]:
                    http_param_dict['resumptionToken'] = opt_value
                elif opt in ["-o", "--output"]:
                    output = opt_value
                elif opt in ["-c", "--certificate"]:
                    cert_file = opt_value
                elif opt in ["-k", "--key"]:
                    key_file = opt_value
                elif opt in ["-l", "--user"]:
                    user = opt_value
                elif opt in ["-w", "--password"]:
                    password = opt_value
                elif opt in ["-V", "--version"]:
                    print(__revision__)
                    sys.exit(0)
                else:
                    usage(1, "Option %s is not allowed" % opt)

            if len(args) > 0:
                base_url = args[-1]
                if not base_url.lower().startswith('http'):
                    base_url = 'http://' + base_url
                (addressing_scheme, network_location, path, dummy1, dummy2,
                 dummy3) = urllib.parse.urlparse(base_url)
                secure = (addressing_scheme == "https")

                if (cert_file and not key_file) or \
                        (key_file and not cert_file):
                    # Both are needed if one specified
                    usage(1, "You must specify both certificate and key files")

                if password and not user:
                    # User must be specified when password is given
                    usage(1, "You must specify a username")
                elif user and not password:
                    if not secure:
                        sys.stderr.write(
                            "*WARNING* Your password will be sent in clear!\n")
                    try:
                        password = getpass.getpass()
                    except KeyboardInterrupt as error:
                        sys.stderr.write("\n%s\n" % (error, ))
                        sys.exit(0)

                getter.harvest(network_location, path, http_param_dict, method,
                               output, sets, secure, user, password, cert_file,
                               key_file)

                sys.stderr.write(
                    "Harvesting completed at: %s\n\n" %
                    time.strftime("%Y-%m-%d %H:%M:%S --> ", time.localtime()))
                return
            else:
                usage(1, "You must specify the URL to harvest")
        else:
            # verb is not given. We will continue with periodic
            # harvesting. But first check if URL parameter is given:
            # if it is, then warn directly now

            if len([opt for opt, opt_value in opts if
                    opt in ['-i', '--identifier']]) == 0 \
                and len(args) > 1 or \
                    (len(args) == 1 and not args[0].isdigit()):
                usage(1, "You must specify the --verb parameter")
    except getopt.error:
        # So could it be that we are using different arguments? Try to
        # start the BibSched task (automated harvesting) and see if it
        # validates
        pass
        # BibSched mode - periodical harvesting
    # Note that the 'help' is common to both manual and automated
    # mode.

    num_of_critical_parameter = 0
    num_of_critical_parameterb = 0
    repositories = []

    for opt in sys.argv[1:]:
        if opt in "-r" or opt in "--repository":
            num_of_critical_parameter += 1
        elif opt in "--workflow":
            num_of_critical_parameterb += 1
        if num_of_critical_parameter > 1 or num_of_critical_parameterb > 1:
            usage(1, "You can't specify twice -r or --workflow")

    if num_of_critical_parameter == 1:
        if "-r" in sys.argv:
            position = sys.argv.index("-r")
        else:
            position = sys.argv.index("--repository")
        repositories = sys.argv[position + 1].split(",")
        if len(repositories) > 1 and \
                ("-i" in sys.argv or "--identifier" in sys.argv):
            usage(
                1, "It is impossible to harvest an identifier from several "
                "repositories.")

    if num_of_critical_parameterb == 1:

        position = sys.argv.index("--workflow")
        workflows = sys.argv[position + 1].split(",")

        for workflow_candidate in workflows:
            if workflow_candidate not in registry_workflows:
                usage(1, "The workflow %s doesn't exist." % workflow_candidate)

    if num_of_critical_parameter == 1 and num_of_critical_parameterb == 0:

        for name_repository in repositories:
            try:
                oaiharvest_instance = OaiHARVEST.get(
                    OaiHARVEST.name == name_repository).one()
                if oaiharvest_instance.workflows not in registry_workflows:
                    usage(
                        1,
                        "The repository %s doesn't have a valid workflow specified."
                        % name_repository)
            except orm.exc.NoResultFound:
                usage(
                    1, "The repository %s doesn't exist in our database." %
                    name_repository)

    elif num_of_critical_parameter == 1 and num_of_critical_parameterb == 1:

        for name_repository in repositories:
            try:
                OaiHARVEST.get(OaiHARVEST.name == name_repository).one()
            except orm.exc.NoResultFound:
                usage(
                    1, "The repository %s doesn't exist in our database." %
                    name_repository)

        print("A workflow has been specified, overriding the repository one.")

    task_set_option("repository", None)
    task_set_option("dates", None)
    task_set_option("workflow", None)
    task_set_option("identifiers", None)
    task_init(
        authorization_action='runoaiharvest',
        authorization_msg="oaiharvest Task Submission",
        description="""
Harvest records from OAI sources.
Manual vs automatic harvesting:
   - Manual harvesting retrieves records from the specified URL,
     with the specified OAI arguments. Harvested records are displayed
     on the standard output or saved to a file, but are not integrated
     into the repository. This mode is useful to 'play' with OAI
     repositories or to build special harvesting scripts.
   - Automatic harvesting relies on the settings defined in the OAI
     Harvest admin interface to periodically retrieve the repositories
     and sets to harvest. It also take care of harvesting only new or
     modified records. Records harvested using this mode are converted
     and integrated into the repository, according to the settings
     defined in the OAI Harvest admin interface.

Examples:
Manual (single-shot) harvesting mode:
   Save to /tmp/z.xml records from CDS added/modified between 2004-04-01
   and 2004-04-02, in MARCXML:
     $ oaiharvest -vListRecords -f2004-04-01 -u2004-04-02 -pmarcxml -o/tmp/z.xml http://cds.cern.ch/oai2d
Automatic (periodical) harvesting mode:
   Schedule daily harvesting of all repositories defined in OAIHarvest admin:
     $ oaiharvest -s 24h
   Schedule daily harvesting of repository 'arxiv', defined in OAIHarvest admin:
     $ oaiharvest -r arxiv -s 24h
   Harvest in 10 minutes from 'pubmed' repository records added/modified
   between 2005-05-05 and 2005-05-10:
     $ oaiharvest -r pubmed -d 2005-05-05:2005-05-10 -t 10m
""",
        help_specific_usage='Manual single-shot harvesting mode:\n'
        '  -o, --output         specify output file\n'
        '  -v, --verb           OAI verb to be executed\n'
        '  -m, --method         http method (default POST)\n'
        '  -p, --metadataPrefix metadata format\n'
        '  -i, --identifier     OAI identifier\n'
        '  -s, --set            OAI set(s). Whitespace-separated list\n'
        '  -r, --resuptionToken Resume previous harvest\n'
        '  -f, --from           from date (datestamp)\n'
        '  -u, --until          until date (datestamp)\n'
        '  -c, --certificate    path to public certificate (in case of certificate-based harvesting)\n'
        '  -k, --key            path to private key (in case of certificate-based harvesting)\n'
        '  -l, --user           username (in case of password-protected harvesting)\n'
        '  -w, --password       password (in case of password-protected harvesting)\n'
        'Deamon mode (periodical or one-shot harvesting mode):\n'
        '  -r, --repository="repo A"[,"repo B"] \t which repositories to harvest (default=all)\n'
        '  -d, --dates=yyyy-mm-dd:yyyy-mm-dd \t reharvest given dates only\n'
        '  -i, --identifier     OAI identifier if wished to run in as a task.\n'
        '  --notify-email-to    Receive notifications on given email on successful upload and/or finished harvest.\n'
        '  --workflow       specify the workflow to execute.\n'
        '  --create-ticket-in   Provide desired ticketing queue to create a ticket in it on upload and/or finished harvest.\n'
        '                       Requires a configured ticketing system (BibCatalog).\n',
        specific_params=("r:i:d:W", [
            "repository=", "identifier=", "dates=", "workflow=",
            "notify-email-to=", "create-ticket-in="
        ]),
        task_submit_elaborate_specific_parameter_fnc=
        task_submit_elaborate_specific_parameter,
        task_run_fnc=task_run_core)