Example #1
0
def init(plugin_manager):
    """ inits everything that makes the backend working """

    # Updates the submissions that are waiting with the status error, as the server restarted
    get_database().submissions.update(
        {"status": "waiting"},
        {
            "$unset": {"jobid": ""},
            "$set": {"status": "error", "grade": 0.0, "text": "Internal error. Server restarted"},
        },
        multi=True,
    )

    # Updates all batch job still running
    get_database().batch_jobs.update(
        {"result": {"$exists": False}},
        {"$set": {"result": {"retval": -1, "stderr": "Internal error. Server restarted"}}},
        multi=True,
    )

    # Create the job manager
    backend_type = INGIniousConfiguration.get("backend", "local")
    if backend_type == "local":
        get_job_manager.job_manager = LocalJobManager(
            INGIniousConfiguration.get(
                "containers", {"default": "ingi/inginious-c-default", "sekexe": "ingi/inginious-c-sekexe"}
            ),
            INGIniousConfiguration.get("local_agent_tmp_dir", "/tmp/inginious_agent"),
            plugin_manager,
        )
    elif backend_type == "remote":
        get_job_manager.job_manager = RemoteDockerJobManager(
            INGIniousConfiguration.get("docker_daemons", []),
            INGIniousConfiguration.get(
                "containers", {"default": "ingi/inginious-c-default", "sekexe": "ingi/inginious-c-sekexe"}
            ),
            plugin_manager,
        )
    elif backend_type == "remote_manual":
        get_job_manager.job_manager = RemoteManualAgentJobManager(
            INGIniousConfiguration.get("agents", [{"host": "localhost", "port": 5001}]),
            INGIniousConfiguration.get(
                "containers", {"default": "ingi/inginious-c-default", "sekexe": "ingi/inginious-c-sekexe"}
            ),
            plugin_manager,
        )
    else:
        raise Exception("Unknown backend {}".format(backend_type))
Example #2
0
def get_batch_container_metadata(container_name):
    """
        Returns the arguments needed by a particular batch container.
        :returns: a tuple in the form
            ("container title",
             "container description in restructuredtext",
             {"key":
                {
                 "type:" "file", #or "text",
                 "path": "path/to/file/inside/input/dir", #not mandatory in file, by default "key"
                 "name": "name of the field", #not mandatory in file, default "key"
                 "description": "a short description of what this field is used for" #not mandatory, default ""
                }
             }
            )
    """
    if container_name not in INGIniousConfiguration.get("batch_containers", []):
        raise Exception("This batch container is not allowed to be started")

    return get_job_manager().get_batch_container_metadata(container_name)
Example #3
0
def add_batch_job(course, container_name, inputdata, launcher_name=None, skip_permission=False):
    """
        Add a job in the queue and returns a batch job id.
        inputdata is a dict containing all the keys of get_batch_container_metadata(container_name)[2] BUT the keys "course" and "submission" IF their
        type is "file". (the content of the course and the submission will be automatically included by this function.)
        The values associated are file-like objects for "file" types and  strings for "text" types.
    """

    if not skip_permission:
        if not User.is_logged_in():
            raise Exception("A user must be logged in to submit an object")

        username = User.get_username()
        launcher_name = launcher_name or username

        if username not in course.get_admins():
            raise Exception("The user must be an administrator to start a batch job")

    if container_name not in INGIniousConfiguration.get("batch_containers", []):
        raise Exception("This batch container is not allowed to be started")

    container_args = get_job_manager().get_batch_container_metadata(container_name)[2]
    if container_args is None:
        raise Exception("This batch container is not available")

    # Download the course content and submissions and add them to the input
    if "course" in container_args and container_args["course"]["type"] == "file" and "course" not in inputdata:
        inputdata["course"] = _get_course_data(course)
    if "submissions" in container_args and container_args["submissions"]["type"] == "file" and "submissions" not in inputdata:
        inputdata["submissions"] = _get_submissions_data(course)

    obj = {"courseid": course.get_id(), 'container_name': container_name, "submitted_on": datetime.now()}

    batch_job_id = get_database().batch_jobs.insert(obj)

    launcher_name = launcher_name or "plugin"

    get_job_manager().new_batch_job(container_name, inputdata, lambda r: _batch_job_done_callback(batch_job_id, r),
                                    launcher_name="Frontend - {}".format(launcher_name))

    return batch_job_id
Example #4
0
 def get_admins(self, with_superadmin=True):
     """ Returns a list containing the usernames of the administrators of this course """
     if with_superadmin:
         return list(set(self._admins + INGIniousConfiguration.get('superadmins', [])))
     else:
         return self._admins
Example #5
0
def get_all_batch_containers_metadata():
    """
        Returns the arguments needed for all batch containers.
        :returns: a dict, containing as keys the container image names, and as value tuples in the form
            ("container title",
             "container description in restructuredtext",
             {"key":
                {
                 "type:" "file", #or "text",
                 "path": "path/to/file/inside/input/dir", #not mandatory in file, by default "key"
                 "name": "name of the field", #not mandatory in file, default "key"
                 "description": "a short description of what this field is used for" #not mandatory, default ""
                }
             }
            )
    """
    return {container_name:get_batch_container_metadata(container_name) for container_name in INGIniousConfiguration.get("batch_containers", [])}
Example #6
0
def new_database_client():
    """ Creates a new MongoClient instance for INGINious """
    config = {'host': INGIniousConfiguration.get('mongo_opt', {}).get('host', 'localhost')}
    client = MongoClient(**config)
    return client[INGIniousConfiguration.get('mongo_opt', {}).get('database', 'INGInious')]