diff --git a/oer/exercise-formats/choice/multiple/script.js b/oer/exercise-formats/choice/multiple/script.js old mode 100644 new mode 100755 diff --git a/oer/exercise-formats/input/text/script.js b/oer/exercise-formats/input/text/script.js old mode 100644 new mode 100755 diff --git a/oer/exercise-formats/program/match-regex-multifile/script.js b/oer/exercise-formats/program/match-regex-multifile/script.js old mode 100644 new mode 100755 diff --git a/oer/exercise-formats/program/match-regex-parallel/script.js b/oer/exercise-formats/program/match-regex-parallel/script.js old mode 100644 new mode 100755 diff --git a/oer/exercise-formats/program/match-regex/controller.py b/oer/exercise-formats/program/match-regex/controller.py old mode 100644 new mode 100755 index a456f73..81c6cb2 --- a/oer/exercise-formats/program/match-regex/controller.py +++ b/oer/exercise-formats/program/match-regex/controller.py @@ -20,7 +20,7 @@ def build(ctx): # start subprocess in with work_path as cwd p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) msgs,errs = p.communicate() - retval = p.wait() + retval = p.wait() errs = errs.decode("utf-8") msgs = msgs.decode("utf-8") @@ -37,7 +37,7 @@ def execute(ctx): p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path) msgs,errs = p.communicate() - retval = p.wait() + retval = p.wait() errs = errs.decode("utf-8") msgs = msgs.decode("utf-8") @@ -62,10 +62,8 @@ def grade(ctx): else: return 'FAIL' - def response(ctx): - output = "" if ctx.build_result[0] != 0: output = ctx.build_result[1] diff --git a/oer/exercise-formats/program/match-regex/script.js b/oer/exercise-formats/program/match-regex/script.js old mode 100644 new mode 100755 diff --git a/oer/exercise-formats/program/scriptgrade/script.js b/oer/exercise-formats/program/scriptgrade/script.js old mode 100644 new mode 100755 diff --git a/oer/exercise-formats/text/html/script.js b/oer/exercise-formats/text/html/script.js old mode 100644 new mode 100755 diff --git a/src/frontend/templates/frontend/footer.html b/src/frontend/templates/frontend/footer.html index 7f1f5ba..c74fa31 100644 --- a/src/frontend/templates/frontend/footer.html +++ b/src/frontend/templates/frontend/footer.html @@ -14,6 +14,8 @@ .sep { color: silver; margin: 0.3em; } + Privacy + | Impressum | Contact diff --git a/src/frontend/templates/frontend/privacy.html b/src/frontend/templates/frontend/privacy.html new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/views.py b/src/frontend/views.py index f42e6b3..716ea7c 100644 --- a/src/frontend/views.py +++ b/src/frontend/views.py @@ -34,6 +34,10 @@ def attribution(request): data = {} return render(request, 'frontend/attribution.html', data) +def privacy(request): + data = {} + return render(request, 'frontend/privacy.html', data) + def dashboard(request): # only registered users can see their statistics if not request.user.is_authenticated: diff --git a/src/main/urls.py b/src/main/urls.py index 1bce2cc..4aa22e6 100644 --- a/src/main/urls.py +++ b/src/main/urls.py @@ -29,6 +29,7 @@ urlpatterns = [ url(r'^dashboard/$', frontend.views.dashboard, name='dashboard'), url(r'^settings/$', frontend.views.settings, name='settings'), url(r'^attribution/$', frontend.views.attribution, name='attribution'), + url(r'^privacy/$', frontend.views.privacy, name='privacy'), # Courses url(r'^courses/', include('courses.urls', namespace='courses')), diff --git a/src/rest/views.py b/src/rest/views.py index f498c50..c190424 100644 --- a/src/rest/views.py +++ b/src/rest/views.py @@ -27,6 +27,7 @@ import sys import os import pprint import re +import os.path from courses.models import Course from courses.models import Section @@ -34,14 +35,26 @@ from courses.models import Slide from courses.models import UserCourse from courses.models import UserSolution +from runner.tasks import compile_and_run +import json + def local_execute(dic): - print("LOCAL EXECUTE") - print(dic) - return {"id" : 100} + #print("LOCAL EXECUTE") + id = 100 + ret = compile_and_run(id, dic) + print(ret, file=sys.stderr) + return {"status" : 'SUCCESS', "id" : id, "result": ret} def local_execute_result(id): - print("Retrieving: " + id) - return {"status" : 201, "result": {"output" : False, "grade" : "PASS"}} + #return {"status" : 201, "result": {"output" : False, "grade" : "PASS"}} + file = "/data/run/jobs/%s/job.json" % (id) + print("Retrieving: " + file) + if os.path.isfile(file): + with open(file) as json_data: + d = json.load(json_data) + return {"status" : 'SUCCESS', "result": d["response"]} + else: + return {"status" : 0, "result": {"output" : False}} # helpers class JSONResponse(HttpResponse): @@ -178,7 +191,6 @@ def job_status(request, jid): #data = JSONParser().parse(json_docs) return JSONResponse(data) - return HttpResponse("huh", status=401) diff --git a/src/runner/tasks.py b/src/runner/tasks.py index 2e6d7fc..81d24fb 100644 --- a/src/runner/tasks.py +++ b/src/runner/tasks.py @@ -1,34 +1,23 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from runner.celery import app +#from runner.celery import app import subprocess import os import sys import shutil import json - - import importlib.machinery - -# To conserve resources consider using the ignore result decorator, when the result is not used by someone else -#@app.task(ignore_result=True) - -############################################################################### -# Settings -############################################################################### -WORK_DIR = os.path.expanduser(os.environ["WORKER_DIR"]) -OER_FORMATS_PATH = os.path.expanduser(os.environ["WORKER_OER_DIR"] + "/exercise-formats/") -############################################################################### - +WORK_DIR = "/data/run/jobs" +OER_FORMATS_PATH = "/data/oer/exercise-formats/" def load_handler(path): - handler = {'name': None, 'loader': None, 'mod': None} + handler = {'name': None, 'loader': None, 'mod': None} + #print(path, file=sys.stderr) for root, dirs, files in os.walk(path): - #print(root, file=sys.stderr) #print(dirs, file=sys.stderr) #print(files, file=sys.stderr) if 'controller.py' in files: @@ -50,7 +39,7 @@ def load_handler(path): class Job(object): """ - The job class for tasks implements some default behaivior for every + The job class for tasks implements some default behaivior for every format and tries to call special event handlers when they are defined for the formats or exercises. @@ -66,8 +55,8 @@ class Job(object): """ - def __init__(self, job, celery_task=None): - print("Job.__init__()", file=sys.stderr) + def __init__(self, job): + #print("Job.__init__()", file=sys.stderr) self.data = job self.work_path = WORK_DIR + '/' + str(job['_id']) + '/' self.handler_format = {'name': None, 'loader': None, 'mod': None} @@ -78,31 +67,22 @@ class Job(object): self.grade_result = 'FAIL' self.response_data = {} - - - - - # allow controllers to manipulate celery task - # e.g. to set meta data after submitting slurm jobs - self.celery_task = celery_task - def import_handlers(self): print("Job.init_handlers()", file=sys.stderr) # find exercise specific and default handler for exercise format self.handler_format = load_handler("%s/%s" % (OER_FORMATS_PATH, self.data['type'])) - self.handler_exercise = load_handler( self.data['source_path']) + self.handler_exercise = load_handler(self.data['source_path']) - if self.handler_format != None: + if self.handler_format != None: print("INFO: Format handler found ;", file=sys.stderr) - if self.handler_exercise != None: + if self.handler_exercise != None: print("INFO: Exercise handlers found ;", file=sys.stderr) def extract(self): - print("Job.extract()", file=sys.stderr) - + #print("Job.extract()", file=sys.stderr) # creates workdir and files print(self.data['source_path'], file=sys.stderr) print(self.work_path, file=sys.stderr) @@ -111,7 +91,7 @@ class Job(object): src = self.data['source_path'] dst = self.work_path shutil.copytree(src, dst) - + self.sourcefile = self.work_path + 'program.c' self.programfile = self.work_path + 'program' @@ -121,14 +101,6 @@ class Job(object): source.close() - - - - - - pass - - def build(self): print("Job.build()", file=sys.stderr) @@ -208,11 +180,8 @@ class Job(object): fp = open(self.jobfile, 'w') json.dump({"job": self.data, "response": self.response_data}, fp) fp.close() - # into mongodb - - def get_file_content(self, filename): try: with open(self.work_path + '/' + filename, 'r') as f: @@ -228,60 +197,43 @@ class Job(object): -@app.task(time_limit=20) -def timelimited_task(): - try: - return do_work() - except SoftTimeLimitExceeded: - cleanup_in_a_hurry() - -@app.task -def compile(): - return True +#@app.task(time_limit=20) +#def timelimited_task(): +# try: +# return do_work() +# except SoftTimeLimitExceeded: +# cleanup_in_a_hurry() +# +#@app.task +#def compile(): +# return True -@app.task(bind=True) -def compile_and_run(self, data): - - print(data, file=sys.stderr) - print(self.request.id, file=sys.stderr) - - print(data['type'], file=sys.stderr) - print(data['action'], file=sys.stderr) - print(data['source_path'], file=sys.stderr) - - data['_id'] = self.request.id - +#@app.task(bind=True) +def compile_and_run(id, data): + #print(data, file=sys.stderr) + #print(data['type'], file=sys.stderr) + #print(data['action'], file=sys.stderr) + #print(data['source_path'], file=sys.stderr) + data['_id'] = id # create job object and call the different handlers - j = Job(data, celery_task=self) - + j = Job(data) j.import_handlers() - if data['action'] not in ["quiz"]: j.extract() j.build() - + if data['action'] in ["test", "execute", "run"]: j.execute() - + if data['action'] in ["grade", "quiz"]: j.grade() - print("Result prepare") + #print("Result prepare") ret = j.response() + j.response_data = ret j.store_result() - print("Result sent!") + #print("Result sent!") return ret - - # self.update_state(state='SUBMITTED TO SLURM', meta={}) - - - - -# Convienence task definitions for programming assignments -@app.task -def compile_run_and_grade(): - # start the celeryropriete subtasks - return True