Beispiel #1
0
def view_assignment(assignment_id):
    simple_archive_form = SimpleArchiveForm()

    # Convert the assignment in the URL into an ObjectId
    try:
        id = ObjectId(assignment_id)
    except InvalidId:
        logger.info("Invalid Assignment ID requested.")

        abort(404)

    # Retrieve the assignment
    try:
        assignment = Assignment.objects.get(id=id)
    except Assignment.DoesNotExist:
        logger.info("Non-extant ID requested.")

        abort(404)

    assignment.apply_personal_deadlines(current_user)

    # Get all of the submissions for this assignment
    submissions = list(Submission.objects(user=current_user.id, assignment=id).order_by("-most_recent", "-timestamp"))

    # Get student submissions if being viewed as teacher
    student_submissions = []
    students = []
    if current_user.account_type in ["teacher", "teaching_assistant"]:
        students = list(User.objects(classes=assignment.for_class, account_type="student").order_by("-email"))

        student_submissions = list(
            Submission.objects(user__in=[i.email for i in students], assignment=assignment_id, most_recent=True)
        )

    test_results = list(TestResult.objects(id__in=[i.test_results for i in submissions if i.test_results]))

    # Match test results to submissions
    for i in submissions:
        for j in test_results:
            if i.test_results == j.id:
                i.test_results_obj = j

    # Current time to be compared to submission test_request_timestamp
    now = datetime.datetime.now()

    # Flag to set refresh trigger if user is waiting on test results
    wait_and_refresh = False

    # Add the pretty version of each submissions timestamp
    for i in submissions:
        i.timestamp_pretty = pretty_time(i.timestamp)
        i.status = "Submitted"

        # If the user submitted a test request and there aren't any results
        if i.test_request_timestamp and not i.test_results:
            timedelta = now - i.test_request_timestamp
            i.show_resubmit = timedelta > config["STUDENT_RETRY_INTERVAL"]
            if not i.show_resubmit:
                i.status = "Waiting for test results..."
            else:
                i.status = "Test request timed out"
        elif i.test_results and i.test_results_obj.failed:
            i.status = "Tests Failed"
            i.show_resubmit = True
        elif i.test_results and not i.test_results_obj.failed:
            i.status = "Tests Completed"

    wait_and_refresh = any(i.status == "Waiting for test results..." for i in submissions)

    return render_template(
        "assignment.html",
        now=datetime.datetime.today(),
        create_time_element=create_time_element,
        assignment=assignment,
        submissions=submissions,
        simple_archive_form=simple_archive_form,
        wait_and_refresh=wait_and_refresh,
        new_submissions=[v for k, v in get_flashed_messages(with_categories=True) if k == "new_submission"],
        view_as_teacher=(current_user.account_type in ["teacher", "teaching_assistant"]),
        students=students,
        student_submissions=student_submissions,
        enumerate=enumerate,
    )
Beispiel #2
0
def view_assignment(assignment_id):
    simple_archive_form = SimpleArchiveForm()

    # Convert the assignment in the URL into an ObjectId
    try:
        id = ObjectId(assignment_id)
    except InvalidId:
        logger.info("Invalid Assignment ID requested.")

        abort(404)

    # Retrieve the assignment
    try:
        assignment = Assignment.objects.get(id=id)
    except Assignment.DoesNotExist:
        logger.info("Non-extant ID requested.")

        abort(404)

    assignment.apply_personal_deadlines(current_user)

    # Get all of the submissions for this assignment
    submissions = list(
        Submission.objects(user=current_user.id,
                           assignment=id).order_by("-most_recent",
                                                   "-timestamp"))

    # Get student submissions if being viewed as teacher
    student_submissions = []
    students = []
    if current_user.account_type in ["teacher", "teaching_assistant"]:
        students = list(
            User.objects(classes=assignment.for_class,
                         account_type="student").order_by("-email"))

        student_submissions = list(
            Submission.objects(user__in=[i.email for i in students],
                               assignment=assignment_id,
                               most_recent=True))

    test_results = list(
        TestResult.objects(
            id__in=[i.test_results for i in submissions if i.test_results]))

    # Match test results to submissions
    for i in submissions:
        for j in test_results:
            if i.test_results == j.id:
                i.test_results_obj = j

    # Current time to be compared to submission test_request_timestamp
    now = datetime.datetime.now()

    # Flag to set refresh trigger if user is waiting on test results
    wait_and_refresh = False

    # Add the pretty version of each submissions timestamp
    for i in submissions:
        i.timestamp_pretty = pretty_time(i.timestamp)
        i.status = "Submitted"

        # If the user submitted a test request and there aren't any results
        if (i.test_request_timestamp and not i.test_results):
            timedelta = now - i.test_request_timestamp
            i.show_resubmit = (timedelta > config["STUDENT_RETRY_INTERVAL"])
            if not i.show_resubmit:
                i.status = "Waiting for test results..."
            else:
                i.status = "Test request timed out"
        elif (i.test_results and i.test_results_obj.failed):
            i.status = "Tests Failed"
            i.show_resubmit = True
        elif (i.test_results and not i.test_results_obj.failed):
            i.status = "Tests Completed"

    wait_and_refresh = \
        any(i.status == "Waiting for test results..." for i in submissions)

    return render_template(
        "assignment.html",
        now=datetime.datetime.today(),
        create_time_element=create_time_element,
        assignment=assignment,
        submissions=submissions,
        simple_archive_form=simple_archive_form,
        wait_and_refresh=wait_and_refresh,
        new_submissions=[
            v for k, v in get_flashed_messages(with_categories=True)
            if k == "new_submission"
        ],
        view_as_teacher=(current_user.account_type
                         in ["teacher", "teaching_assistant"]),
        students=students,
        student_submissions=student_submissions,
        enumerate=enumerate)
Beispiel #3
0
def main():
    flock = FlockManager(
        match_found,
        config["BLEET_TIMEOUT"],
        config["SERVICE_TIMEOUT"]
    )

    logger.info("Shepherd starting.")

    while True:
        # Wait until either the public or sheep socket has messages waiting
        zmq.select([public, sheep], [], [], timeout = 5)

        # Will grab all of the outstanding messages from the outside and place them
        # in the request queue
        while public.getsockopt(zmq.EVENTS) & zmq.POLLIN != 0:
            request = public.recv_json()
            logger.debug("Raw test request: %s", str(request))

            request = TestRequest.from_dict(request)
            try:
                submission = \
                    Submission.objects.get(id = ObjectId(request.submission_id))
            except Submission.DoesNotExist as e:
                logger.warning(
                    "Received test request for non-existant submission [%s].",
                    str(request.submission_id)
                )
                continue
            except bson.errors.InvalidId as e:
                logger.warning("Received malformed test request. %s", str(e))
                continue

            try:
                assignment = Assignment.objects.get(id = submission.assignment)
            except Assignment.DoesNotExist as e:
                logger.error(
                    "Received test request for a submission [%s] referencing "
                    "an invalid assignment [%s].",
                    str(submission.id),
                    str(submission.assignment)
                )
                continue

            if not assignment.test_harness:
                logger.warning(
                    "Received test request for a submission [%s] referencing "
                    "an assignment [%s] that does not have a test harness "
                    "associated with it.",
                    str(submission.id),
                    str(submission.assignment)
                )
                continue

            try:
                test_harness = \
                    TestHarness.objects.get(id = assignment.test_harness)
            except TestHarness.DoesNotExit as e:
                logger.error(
                    "Received test request for a submission [%s] referencing "
                    "an assignment [%s] that references a non-existant test "
                    "harness [%s].",
                    str(submission.id),
                    str(submission.assignment),
                    str(assignment.test_harness)
                )
                continue

            # Gather all the necessary information from the test request
            # received from the outside.
            processed_request = InternalTestRequest(
                submission.id,
                test_harness.config.get("galah/timeout",
                    config["BLEET_TIMEOUT"].seconds),
                test_harness.config.get("galah/environment", {})
            )

            logger.info("Received test request.")

            flock.received_request(processed_request)


        # Will grab all of the outstanding messages from the sheep and process them
        while sheep.getsockopt(zmq.EVENTS) & zmq.POLLIN != 0:
            try:
                sheep_identity, sheep_message = router_recv_json(sheep)
                sheep_message = FlockMessage.from_dict(sheep_message)
                logger.debug(
                    "Received message from sheep: %s",
                    str(sheep_message)
                )
            except ValueError as e:
                logger.error("Could not decode sheep's message: %s", str(e))
                logger.debug(
                    "Exception thrown while decoding sheep's message...",
                    exc_info = sys.exc_info()
                )
                continue

            if sheep_message.type == "distress":
                logger.warn("Received distress message. Sending bloot.")
                router_send_json(
                    sheep, sheep_identity, FlockMessage("bloot", "").to_dict()
                )

            elif sheep_message.type == "bleet":
                logger.debug(
                    "Sheep [%s] bleeted. Sending bloot.",
                    repr(sheep_identity)
                )

                result = flock.sheep_bleeted(sheep_identity)

                # Under certain circumstances we want to completely ignore a
                # bleet (see FlockManager.sheep_bleeted() for more details)
                if result is FlockManager.IGNORE:
                    logger.debug("Ignoring bleet.")
                    continue

                if not result:
                    router_send_json(
                        sheep,
                        sheep_identity,
                        FlockMessage("identify", "").to_dict()
                    )

                    logger.info(
                        "Unrecognized sheep [%s] connected, identify sent.",
                        repr(sheep_identity)
                    )

                    continue

                router_send_json(
                    sheep,
                    sheep_identity,
                    FlockMessage("bloot", "").to_dict()
                )
            elif sheep_message.type == "environment":
                if not flock.manage_sheep(sheep_identity, sheep_message.body):
                    logger.warn(
                        "Received environment from an already-recognized sheep."
                    )
            elif sheep_message.type == "result":
                logger.info("Received test result from sheep.")
                logger.debug(
                    "Received test result from sheep: %s",
                    str(sheep_message.body)
                )

                try:
                    submission_id = ObjectId(sheep_message.body["id"])

                    submission = Submission.objects.get(id = submission_id)

                    test_result = TestResult.from_dict(sheep_message.body)
                    try:
                        test_result.save()
                    except InvalidDocument:
                        logger.warn(
                            "Test result is too large for the database.",
                            exc_info = True
                        )
                        test_result = TestResult(failed = True)
                        test_result.save()

                    submission.test_results = test_result.id
                    submission.save()
                except (InvalidId, Submission.DoesNotExist) as e:
                    logger.warn(
                        "Could not retrieve submission [%s] for test result "
                        "received from sheep [%s].",
                        str(submission_id),
                        repr(sheep_identity)
                    )

                    continue

                router_send_json(
                    sheep,
                    sheep_identity,
                    FlockMessage(
                        "bloot", sheep_message.body["id"]
                    ).to_dict()
                )

                if not flock.sheep_finished(sheep_identity):
                    logger.info(
                        "Got result from sheep [%s] who was not processing "
                        "a test request.",
                        repr(sheep_identity)
                    )

        # Let the flock manager get rid of any dead or killed sheep.
        lost_sheep, killed_sheep = flock.cleanup()

        if lost_sheep:
            logger.warn(
                "%d sheep lost due to bleet timeout: %s",
                len(lost_sheep),
                str([repr(i) for i in lost_sheep])
            )

        if killed_sheep:
            logger.warn(
                "%d sheep lost due to request timeout: %s",
                len(killed_sheep),
                str([repr(i) for i in killed_sheep])
            )