inginious.agent package

class inginious.agent.Agent(context, backend_addr, friendly_name, concurrency, filesystem, ssh_allowed=False)[source]

Bases: object

An INGInious agent, that grades specific kinds of jobs, and interacts with a Backend.

abstract property environments
Returns

a dict of available environments (containers most of the time) in the form

{
    "type": {
        "name": {                 #  for example, "default"
            "id": "env img id",   # "sha256:715...dd3"
            "created": 12345678,  # create date
            "ports": [22, 434],   # list of ports needed
        }
    }
}

If the environments are not environments, fills created with a fixed date (that will be shared by all agents of the same version), that could be 0. id can be anything, but should also be the same for the same versions of environments.

Only the type and name field are shared with the Clients.

abstract async kill_job(message: inginious.common.messages.BackendKillJob)[source]
abstract async new_job(message: inginious.common.messages.BackendNewJob)[source]

Starts a new job. Most of the time, this function should not call send_job_result directly (as job are intended to be asynchronous). When there is a problem starting the job, raise CannotCreateJobException. If the job ends immediately, you are free to call send_job_result.

Parameters

message – message containing all the data needed to start the job

Returns

nothing. If any problems occurs, this method should raise a CannotCreateJobException, which will result in the cancellation of the job.

async run()[source]

Runs the agent. Answer to the requests made by the Backend. May raise an asyncio.CancelledError, in which case the agent should clean itself and restart completely.

async send_job_result(job_id: str, result: str, text: str = '', grade: Optional[float] = None, problems: Optional[Dict[str, Tuple[str, str]]] = None, tests: Optional[Dict[str, Any]] = None, custom: Optional[Dict[str, Any]] = None, state: str = '', archive: Optional[bytes] = None, stdout: Optional[str] = None, stderr: Optional[str] = None)[source]

Send the result of a job back to the backend. Must be called once and only once for each job

Raises

JobNotRunningException – is raised when send_job_result is called more than once for a given job_id

async send_ssh_job_info(job_id: str, host: str, port: int, username: str, key: str)[source]

Send info about the SSH debug connection to the backend/client. Must be called at most once for each job.

Raises
exception inginious.agent.CannotCreateJobException(message)[source]

Bases: Exception

Exception that should be raised when a (batch or std) job cannot be created in Agent.new_job or Agent.new_batch_job

exception inginious.agent.JobNotRunningException[source]

Bases: Exception

Exception raised by the Agent when the functions send_job_result/send_ssh_job_info are called but the job is not running anymore

exception inginious.agent.TooManyCallsException[source]

Bases: Exception

Exception raised by the Agent when the function send_ssh_job_info has been called more than once

Submodules

inginious.agent.docker_agent module

class inginious.agent.docker_agent.DockerAgent(context, backend_addr, friendly_name, concurrency, tasks_fs: inginious.common.filesystems.provider.FileSystemProvider, address_host=None, external_ports=None, tmp_dir='./agent_tmp', runtimes=None, ssh_allowed=False)[source]

Bases: inginious.agent.Agent

buffer_has_data(buffer)[source]

Helper to know if a buffer still has available data

async create_student_container(parent_info, socket_id, environment_name, memory_limit, time_limit, hard_time_limit, share_network, write_stream, ssh, run_as_root)[source]

Creates a new student container. :param write_stream: stream on which to write the return value of the container (with a correctly formatted msgpack message)

property environments
Returns

a dict of available environments (containers most of the time) in the form

{
    "type": {
        "name": {                 #  for example, "default"
            "id": "env img id",   # "sha256:715...dd3"
            "created": 12345678,  # create date
            "ports": [22, 434],   # list of ports needed
        }
    }
}

If the environments are not environments, fills created with a fixed date (that will be shared by all agents of the same version), that could be 0. id can be anything, but should also be the same for the same versions of environments.

Only the type and name field are shared with the Clients.

async handle_job_closing(container_id, retval, manual_feedback=None)[source]

Handle a closing student container. Do some cleaning, verify memory limits, timeouts, … and returns data to the backend

async handle_running_container(info: inginious.agent.docker_agent.DockerRunningJob, future_results)[source]

Talk with a container. Sends the initial input. Allows to start student containers

async handle_student_job_closing(container_id, retval)[source]

Handle a closing student container. Do some cleaning, verify memory limits, timeouts, … and returns data to the associated grading container

async kill_job(message: inginious.common.messages.BackendKillJob)[source]

Handles kill messages. Kill things.

async new_job(message: inginious.common.messages.BackendNewJob)[source]

Handles a new job: starts the grading container

async open_student_stream(student_container_id)[source]
read_buffer(buffer, decode=True)[source]

Helper to read a buffer containing data from a stream

async read_stream(reader_stream, buffer)[source]

Helper to read a read and put data on a buffer

async run()[source]

Runs the agent. Answer to the requests made by the Backend. May raise an asyncio.CancelledError, in which case the agent should clean itself and restart completely.

async start_ssh(reader_stream, info)[source]

Wait for ssh information from student_container and send ssh info to frontend

class inginious.agent.docker_agent.DockerRunningJob(message: inginious.common.messages.BackendNewJob, container_path: str, future_results: _asyncio.Future, job_id: str, container_id: str, inputdata: Dict[str, Any], debug: Union[bool, str], ports: Dict[int, int], environment_type: str, environment_name: str, mem_limit: int, time_limit: int, hard_time_limit: int, sockets_path: str, student_path: str, systemfiles_path: str, course_common_student_path: str, run_cmd: str, assigned_external_ports: List[int], student_containers: Set[str], enable_network: bool, ssh_allowed: bool)[source]

Bases: object

assigned_external_ports: List[int]
container_id: str
container_path: str
course_common_student_path: str
debug: Union[bool, str]
enable_network: bool
environment_name: str
environment_type: str
future_results: _asyncio.Future
hard_time_limit: int
inputdata: Dict[str, Any]
job_id: str
mem_limit: int
message: inginious.common.messages.BackendNewJob
ports: Dict[int, int]
run_cmd: str
sockets_path: str
ssh_allowed: bool
student_containers: Set[str]
student_path: str
systemfiles_path: str
time_limit: int
class inginious.agent.docker_agent.DockerRunningStudentContainer(container_id: str, parent_info: inginious.agent.docker_agent.DockerRunningJob, socket_id: str, write_stream: Any, ssh: bool, ports: Dict[int, int], assigned_external_ports: List[int])[source]

Bases: object

assigned_external_ports: List[int]
container_id: str
parent_info: inginious.agent.docker_agent.DockerRunningJob
ports: Dict[int, int]
socket_id: str
ssh: bool
write_stream: Any

inginious.agent.mcq_agent module

class inginious.agent.mcq_agent.MCQAgent(context, backend_addr, friendly_name, concurrency, tasks_filesystem, problem_types)[source]

Bases: inginious.agent.Agent

check_answer(problems, task_input, language)[source]

Verify the answers in task_input. Returns six values:

  1. True the input is currently valid. (may become invalid after running the code), False else

  2. True if the input needs to be run in the VM, False else

  3. Main message, as a list (that can be join with \n or <br/> for example)

  4. Problem specific message, as a dictionnary (tuple of result/text)

  5. Number of subproblems that (already) contain errors. <= Number of subproblems

  6. Number of errors in MCQ problems. Not linked to the number of subproblems

property environments
Returns

a dict of available environments (containers most of the time) in the form

{
    "type": {
        "name": {                 #  for example, "default"
            "id": "env img id",   # "sha256:715...dd3"
            "created": 12345678,  # create date
            "ports": [22, 434],   # list of ports needed
        }
    }
}

If the environments are not environments, fills created with a fixed date (that will be shared by all agents of the same version), that could be 0. id can be anything, but should also be the same for the same versions of environments.

Only the type and name field are shared with the Clients.

async kill_job(message: inginious.common.messages.BackendKillJob)[source]
async new_job(msg: inginious.common.messages.BackendNewJob)[source]

Starts a new job. Most of the time, this function should not call send_job_result directly (as job are intended to be asynchronous). When there is a problem starting the job, raise CannotCreateJobException. If the job ends immediately, you are free to call send_job_result.

Parameters

message – message containing all the data needed to start the job

Returns

nothing. If any problems occurs, this method should raise a CannotCreateJobException, which will result in the cancellation of the job.