From ecf9c7c5d4ad205244878411b2826e21564601c6 Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Sun, 5 Jun 2022 17:39:02 -0400 Subject: [PATCH 1/7] fix go version --- functions/go_grader/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/functions/go_grader/Makefile b/functions/go_grader/Makefile index 008e8a6..226a378 100644 --- a/functions/go_grader/Makefile +++ b/functions/go_grader/Makefile @@ -1,15 +1,16 @@ SOURCES=workload.py +GO_VERSION=1.17.10-r0 .PHONY: all all: out -go-1.17.9-r0.apk: - wget https://dl-cdn.alpinelinux.org/alpine/v3.15/community/x86_64/go-1.17.9-r0.apk +go-$(GO_VERSION).apk: + wget https://dl-cdn.alpinelinux.org/alpine/v3.15/community/x86_64/go-$(GO_VERSION).apk -out/usr/lib/go/bin/go: go-1.17.9-r0.apk +out/usr/lib/go/bin/go: go-$(GO_VERSION).apk mkdir -p out - tar -C out -xzf go-1.17.9-r0.apk usr/lib 2> /dev/null + tar -C out -xzf go-$(GO_VERSION).apk usr/lib 2> /dev/null out: ${SOURCES} out/usr/lib/go/bin/go mkdir -p out From d5e6b38c9c28990e9de3d469bf8d1238c424c853 Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Sun, 5 Jun 2022 19:49:29 -0400 Subject: [PATCH 2/7] ported and tested go_grader&grades --- Makefile | 31 +++++++++++++-- example_grader/grader_config.json | 1 + functions/gh_repo/workload.py | 18 ++++++--- functions/go_grader/workload.py | 25 ++++++++----- functions/grades/workload.py | 19 +++++++--- functions/start_assignment/workload.py | 13 ++++--- payloads/go_grader.jsonl | 2 +- payloads/grades.jsonl | 2 +- test_ported_functions.sh | 52 ++++++++++++++++++++++++++ 9 files changed, 132 insertions(+), 31 deletions(-) create mode 100644 example_grader/grader_config.json create mode 100755 test_ported_functions.sh diff --git a/Makefile b/Makefile index c489e26..c51d64f 100644 --- a/Makefile +++ b/Makefile @@ -29,10 +29,35 @@ prepdb: output/example_grader.tgz output/example_submission.tgz sfdb -b cos316/example/grading_script - < output/example_grader.tgz sfdb -b submission.tgz - < output/example_submission.tgz -run/%: output/%.img payloads/%.jsonl - @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img < payloads/$*.jsonl +.PHONY: prepfs +prepfs: output/example_grader.tgz output/example_submission.tgz example_grader/grader_config.json + sffs mkdir /gh_repo --endorse false --secrecy true --integrity gh_repo + sffs mkdir /go_grader --endorse false --secrecy true --integrity go_grader + sffs mkdir /grades --endorse false --secrecy true --integrity grades + sffs mkdir /gh_repo/user --endorse false --secrecy user --integrity gh_repo + sffs mkdir /go_grader/user --endorse false --secrecy user --integrity go_grader + sffs mkdir /grades/user --endorse false --secrecy user --integrity grades + # write /gh_repo/user/submission.tgz + sffs mkfile /gh_repo/user/submission.tgz --endorse gh_repo --secrecy user --integrity gh_repo + sffs write /gh_repo/user/submission.tgz --endorse gh_repo --file output/example_submission.tgz + # write /cos316/example/grading_script & /cos316/example/grader_config.json + sffs mkdir /cos316 --endorse false --secrecy true --integrity cos316 + sffs mkdir /cos316/example --endorse cos316 --secrecy true --integrity cos316 + sffs mkfile /cos316/example/grading_script --endorse cos316 --secrecy cos316,go_grader --integrity cos316 + sffs write /cos316/example/grading_script --endorse cos316 --file output/example_grader.tgz + sffs mkfile /cos316/example/grader_config.json --endorse cos316 --secrecy true --integrity cos316 + sffs write /cos316/example/grader_config.json --endorse cos316 --file example_grader/grader_config.json + + +run/%: output/%.img payloads/%.jsonl python3.ext4 + @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* < payloads/$*.jsonl @touch $@ +.PHONY: debug/% +debug/%: export RUST_LOG=debug +debug/%: output/%.img payloads/%.jsonl python3.ext4 + @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* --kernel_args "console=ttyS0" < payloads/$*.jsonl + .PHONY: clean clean: - rm -f $(OUTPUTS) $(RUNS) + rm -f $(OUTPUTS) $(RUNS) storage/*.mdb diff --git a/example_grader/grader_config.json b/example_grader/grader_config.json new file mode 100644 index 0000000..c8771d1 --- /dev/null +++ b/example_grader/grader_config.json @@ -0,0 +1 @@ +{"tests": {"TestNegate": {"points": 10}}} diff --git a/functions/gh_repo/workload.py b/functions/gh_repo/workload.py index 20e3f7c..e63d0e9 100644 --- a/functions/gh_repo/workload.py +++ b/functions/gh_repo/workload.py @@ -4,17 +4,23 @@ import time def handle(req, syscall): - key = "github/%s/%s.tgz" % (req["repository"]["full_name"], req["after"]) - meta_key = "github/%s/_meta" % (req["repository"]["full_name"]) - workflow_key = "github/%s/_workflow" % (req["repository"]["full_name"]) +# key = "github/%s/%s.tgz" % (req["repository"]["full_name"], req["after"]) +# meta_key = "github/%s/_meta" % (req["repository"]["full_name"]) +# workflow_key = "github/%s/_workflow" % (req["repository"]["full_name"]) + usergroup = req['repository']['full_name'] + key = '/gh_repo/%s/%s.tgz' % (req['repository']['full_name'], req['after']) + base_dir = '/gh_repo/%s' % usergroup + meta_path = '/start_assignment/%s/_meta' % usergroup + workflow_path = '/start_assignment/%s/_workflow' % usergroup - metadataString = syscall.read_key(bytes(meta_key, "utf-8")) or "{}" + metadataString = syscall.fsread(meta_path) or "{}" if metadataString: metadata = json.loads(metadataString) - workflow = json.loads(syscall.read_key(bytes(workflow_key, "utf-8")) or "[]") + workflow = json.loads(syscall.fsread(workflow_path) or "[]") resp = syscall.github_rest_get("/repos/%s/tarball/%s" % (req["repository"]["full_name"], req["after"])); - syscall.write_key(bytes(key, "utf-8"), resp.data) + syscall.fscreate_file(base_dir, '%s.tgz' % req['after'], syscall.get_current_label()) + syscall.fswrite(path, resp.data) if len(workflow) > 0: next_function = workflow.pop(0) diff --git a/functions/go_grader/workload.py b/functions/go_grader/workload.py index 8ad1882..da7c4d6 100644 --- a/functions/go_grader/workload.py +++ b/functions/go_grader/workload.py @@ -17,21 +17,20 @@ def handle(req, syscall): })) return result -def app_handle(args, state, syscall): +def app_handle(args, context, syscall): os.system("ifconfig lo up") # Fetch and untar submission tarball - assignment = state["metadata"]["assignment"] + assignment = context["metadata"]["assignment"] with tempfile.NamedTemporaryFile(suffix=".tar.gz") as submission_tar: - submission_tar_data = syscall.read_key(bytes(args["submission"], "utf-8")) + submission_tar_data = syscall.fsread(args['submission']) submission_tar.write(submission_tar_data) submission_tar.flush() with tempfile.TemporaryDirectory() as submission_dir: - os.system("mkdir %s" % submission_dir) os.system("tar -C %s -xzf %s --strip-components=1" % (submission_dir, submission_tar.name)) # Fetch and untar grading script tarball with tempfile.NamedTemporaryFile(suffix=".tar.gz") as script_tar: - script_tar_data = syscall.read_key(bytes("cos316/%s/grading_script" % assignment, "utf-8")) + script_tar_data = syscall.fsread('/cos316/%s/grading_script' % assignment) script_tar.write(script_tar_data) script_tar.flush() with tempfile.TemporaryDirectory() as script_dir: @@ -39,7 +38,7 @@ def app_handle(args, state, syscall): # OK, run tests os.putenv("GOCACHE", "%s/.cache" % script_dir) - os.putenv("GOROOT", "/srv/usr/lib/go") + os.putenv("GOROOT", "/srv/usr/lib/go") os.putenv("SOLUTION_DIR", submission_dir) os.putenv("PATH", "%s:%s" % ("/srv/usr/lib/go/bin", os.getenv("PATH"))) os.chdir(script_dir) @@ -58,11 +57,19 @@ def app_handle(args, state, syscall): if tr["Action"] in ["pass", "fail", "run"]: tr = dict((name.lower(), val) for name, val in tr.items()) final_results.append(json.dumps(tr)) - key = os.path.join(os.path.splitext(args["submission"])[0], "test_results.jsonl") - syscall.write_key(bytes(key, "utf-8"), bytes('\n'.join(final_results), "utf-8")) +# key = os.path.join(os.path.splitext(args["submission"])[0], "test_results.jsonl") + submission = os.path.basename(os.path.splitext(args['submission'])[0]) + user = context['user'] + func = context['function'] + file = '/go_grader/%s/%s/test_results.jsonl' % (user, submission) + syscall.endorse_with([[func]]) + syscall.declassify_to([[user]]) + syscall.fscreate_dir('/go_grader/%s' % user, submission, syscall.new_dclabel([[user]], [[func]])) + syscall.fscreate_file('/go_grader/%s/%s' % (user, submission), os.path.basename(file), syscall.new_dclabel([[user]], [[func]])) + syscall.fswrite(file, bytes('\n'.join(final_results), "utf-8")) testrun.wait() if testrun.returncode >= 0: - return { "test_results": key } + return { "test_results": file } else: _, errlog = testrun.communicate() return { "error": { "testrun": str(errlog), "returncode": testrun.returncode } } diff --git a/functions/grades/workload.py b/functions/grades/workload.py index c651b5c..c8189a3 100644 --- a/functions/grades/workload.py +++ b/functions/grades/workload.py @@ -16,11 +16,11 @@ def handle(req, syscall): return result def app_handle(args, context, syscall): - test_lines = [ json.loads(line) for line in syscall.read_key(bytes(args["test_results"], "utf-8")).split(b'\n') ] + test_lines = [ json.loads(line) for line in syscall.fsread(args['test_results']).split(b'\n') ] test_runs = dict((line['test'], line) for line in test_lines if 'test' in line) - grader_config = "cos316/%s/grader_config" % context["metadata"]["assignment"] - config = json.loads(syscall.read_key(bytes(grader_config, "utf-8"))) + grader_config = "/cos316/%s/grader_config.json" % context["metadata"]["assignment"] + config = json.loads(syscall.fsread(grader_config)) total_points = sum([ test["points"] for test in config["tests"].values() if "extraCredit" not in test or not test["extraCredit"]]) @@ -45,10 +45,17 @@ def app_handle(args, context, syscall): "push_date": context["push_date"] } - key = os.path.join(os.path.dirname(args["test_results"]),"grade.json") - syscall.write_key(bytes(key, "utf-8"), bytes(json.dumps(output), "utf-8")) + user = context['user'] + func = context['function'] + base_dir = os.path.join('/', func, user, context['metadata']['assignment']) + file = os.path.join(base_dir, 'grade.json') + syscall.endorse_with([[func]]) + target_label = syscall.new_dclabel([[user]], [[func]]) + syscall.fscreate_dir(os.path.dirname(base_dir), os.path.basename(base_dir), target_label) + syscall.fscreate_file(base_dir, os.path.basename(file), target_label) + syscall.fswrite(file, bytes(json.dumps(output), "utf-8")) return { "grade": points / total_points, - "grade_report": key + "grade_report": file } diff --git a/functions/start_assignment/workload.py b/functions/start_assignment/workload.py index 37b604f..a24b1e8 100644 --- a/functions/start_assignment/workload.py +++ b/functions/start_assignment/workload.py @@ -20,7 +20,7 @@ frost voice paper frog smoke star""".split() def handle(req, syscall): - assignments = json.loads(syscall.read_key(b'cos316/assignments')) + assignments = json.loads(syscall.fsread('/cos316/assignments')) if req["assignment"] not in assignments: return { 'error': 'No such assignment' } @@ -30,7 +30,7 @@ def handle(req, syscall): return { 'error': 'This assignment requires a group size of %d, given %d.' % (group_size, len(users)) } for user in users: - repo = syscall.read_key(bytes('cos316/assignments/%s/%s' % (req["assignment"], user), 'utf-8')); + repo = syscall.fsread('/%s/%s' % (user, req["assignment"])); if repo: return { 'error': ("%s is already completing %s at %s" % (user, req['assignment'], repo.decode('utf-8'))) @@ -62,15 +62,18 @@ def handle(req, syscall): return { 'error': "Couldn't add user to repository", "status": resp.status } - syscall.write_key(bytes('github/cos316/%s/_meta' % name, 'utf-8'), + syscall.fscreate_file('/start_assignment/%s' % name, '_meta', syscall.get_current_label()) + syscall.fswrite('/start_assignment/%s/_meta' % name, bytes(json.dumps({ 'assignment': req['assignment'], 'users': list(users), }), 'utf-8')) - syscall.write_key(bytes('github/cos316/%s/_workflow' % name, 'utf-8'), + syscall.fscreate_file('/start_assignment/%s' % name, '_workflow', syscall.get_current_label()) + syscall.fswrite('/start_assignment/%s/_workflow' % name, bytes(json.dumps(["go_grader", "grades", "generate_report", "post_comment"]), 'utf-8')) for user in users: - syscall.write_key(bytes('cos316/assignments/%s/%s' % (req["assignment"], user), 'utf-8'), + syscall.fscreate_file('/%s' % user, req['assignment'], syscall.get_current_label()) + syscall.fswrite('/%s/%s' % (user, req['assignment']), bytes("cos316/%s" % name, 'utf-8')) return { 'name': name, 'users': list(users), 'github_handles': req['gh_handles'] } diff --git a/payloads/go_grader.jsonl b/payloads/go_grader.jsonl index 333a1dc..3e7bd0b 100644 --- a/payloads/go_grader.jsonl +++ b/payloads/go_grader.jsonl @@ -1 +1 @@ -{"args": {"submission": "submission.tgz"}, "workflow": [ "grades", "generate_report" ], "context": { "metadata": {"assignment": "example"}}} +{"args": {"submission": "/gh_repo/user/submission.tgz"}, "workflow": ["grades"], "context": { "metadata": {"assignment": "example"}, "user": "user", "function": "go_grader"}} diff --git a/payloads/grades.jsonl b/payloads/grades.jsonl index 6bd0c3d..7bd22f2 100644 --- a/payloads/grades.jsonl +++ b/payloads/grades.jsonl @@ -1 +1 @@ -{"args": {"test_results": "github/cos316/assignment2-starter-code/b541c851d79edad1d05fc64c1bcca88800703a30/test_results.jsonl"}, "workflow": [ "generate_report" ], "context": {"commit": "b541c851d79edad1d05fc64c1bcca88800703a30", "metadata": {"assignment": "assignment2"}, "push_date": 1642798607, "repository": "cos316/assignment2-starter-code"}} +{"args": {"test_results": "/go_grader/user/submission/test_results.jsonl"}, "workflow": [], "context": {"commit": "b541c851d79edad1d05fc64c1bcca88800703a30", "metadata": {"assignment": "example"}, "push_date": 1642798607, "repository": "cos316/assignment2-starter-code", "user": "user", "function": "grades"}} diff --git a/test_ported_functions.sh b/test_ported_functions.sh new file mode 100755 index 0000000..05a7e11 --- /dev/null +++ b/test_ported_functions.sh @@ -0,0 +1,52 @@ +SNAPFAAS=https://api.github.com/repos/princeton-sns/snapfaas/tarball/faasten +IMAGES=https://api.github.com/repos/princeton-sns/snapfaas-images/tarball/faasten +WD=$(dirname $(realpath $0)) +cd $WD + +echo '***********************************' +echo '* building faasten binaries *' +echo '***********************************' +mkdir -p snapfaas +curl -sL -H "Accept: application/vnd.github.v3+json" $SNAPFAAS --output snapfaas.tgz +tar xzf snapfaas.tgz --strip-components=1 -C snapfaas +cd snapfaas/snapfaas; cargo build --bins; cd $WD +export PATH=snapfaas/target/debug:$PATH +if [ ! command -v sffs 2>/dev/null ] || [ ! command -v singlevm 2>/dev/null ] || [ ! command -v firerunner 2>/dev/null ]; then + exit 1 +fi + +echo '************************' +echo '* getting images *' +echo '************************' +# download the uncompressed kernel +cp snapfaas/resources/images/vmlinux-4.20.0 . +# build the python3.ext4 +mkdir -p rootfs +curl -sL -H "Accept: application/vnd.github.v3+json" $IMAGES | \ +tar xzf - -C rootfs --strip-components=2 --wildcards '*/rootfs/common' '*/rootfs/faasten' +cd rootfs/faasten; ./mk_rtimage.sh python3 ../../python3.ext4; cd $WD +if [ ! -f python3.ext4 ] || [ ! -f vmlinux-4.20.0 ]; then + exit 1 +fi + +echo '*****************' +echo '* testing *' +echo '*****************' +make clean +make prepfs +make run/go_grader +make run/grades + +echo +echo '**************************************' +echo '* cating function output files *' +echo '**************************************' +sffs cat /go_grader/user/submission/test_results.jsonl +sffs cat /grades/user/example/grade.json + +#echo '*********************' +#echo '* cleaning up *' +#echo '*********************' +#rm -r snapfaas rootfs +#rm vmlinux-4.20.0 +#rm python3.ext4 From 1a143776e60ace2fd06dea3ea843df8ef9a68c85 Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Fri, 10 Jun 2022 21:04:57 -0400 Subject: [PATCH 3/7] switch to new syscalls (workspace_xxx & declassify) --- Makefile | 4 ++-- functions/go_grader/workload.py | 20 +++++++++----------- functions/grades/workload.py | 22 +++++++++------------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index c51d64f..994d03b 100644 --- a/Makefile +++ b/Makefile @@ -50,13 +50,13 @@ prepfs: output/example_grader.tgz output/example_submission.tgz example_grader/g run/%: output/%.img payloads/%.jsonl python3.ext4 - @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* < payloads/$*.jsonl + @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* --end_users user < payloads/$*.jsonl @touch $@ .PHONY: debug/% debug/%: export RUST_LOG=debug debug/%: output/%.img payloads/%.jsonl python3.ext4 - @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* --kernel_args "console=ttyS0" < payloads/$*.jsonl + @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* --end_users user --kernel_args "console=ttyS0" < payloads/$*.jsonl .PHONY: clean clean: diff --git a/functions/go_grader/workload.py b/functions/go_grader/workload.py index da7c4d6..af18382 100644 --- a/functions/go_grader/workload.py +++ b/functions/go_grader/workload.py @@ -22,7 +22,8 @@ def app_handle(args, context, syscall): # Fetch and untar submission tarball assignment = context["metadata"]["assignment"] with tempfile.NamedTemporaryFile(suffix=".tar.gz") as submission_tar: - submission_tar_data = syscall.fsread(args['submission']) + submission_tar_data = syscall.fs_read(args['submission']) + secrecy = syscall.get_current_label().secrecy submission_tar.write(submission_tar_data) submission_tar.flush() with tempfile.TemporaryDirectory() as submission_dir: @@ -30,7 +31,7 @@ def app_handle(args, context, syscall): # Fetch and untar grading script tarball with tempfile.NamedTemporaryFile(suffix=".tar.gz") as script_tar: - script_tar_data = syscall.fsread('/cos316/%s/grading_script' % assignment) + script_tar_data = syscall.fs_read('/cos316/%s/grading_script' % assignment) script_tar.write(script_tar_data) script_tar.flush() with tempfile.TemporaryDirectory() as script_dir: @@ -59,17 +60,14 @@ def app_handle(args, context, syscall): final_results.append(json.dumps(tr)) # key = os.path.join(os.path.splitext(args["submission"])[0], "test_results.jsonl") submission = os.path.basename(os.path.splitext(args['submission'])[0]) - user = context['user'] - func = context['function'] - file = '/go_grader/%s/%s/test_results.jsonl' % (user, submission) - syscall.endorse_with([[func]]) - syscall.declassify_to([[user]]) - syscall.fscreate_dir('/go_grader/%s' % user, submission, syscall.new_dclabel([[user]], [[func]])) - syscall.fscreate_file('/go_grader/%s/%s' % (user, submission), os.path.basename(file), syscall.new_dclabel([[user]], [[func]])) - syscall.fswrite(file, bytes('\n'.join(final_results), "utf-8")) + file = 'test_results.jsonl' + syscall.declassify(secrecy) + syscall.workspace_createdir(submission) + syscall.workspace_createfile(file, submission) + syscall.workspace_write(os.path.join(submission, file), bytes('\n'.join(final_results), "utf-8")) testrun.wait() if testrun.returncode >= 0: - return { "test_results": file } + return { "test_results": syscall.workspace_abspath(os.path.join(submission, file))} else: _, errlog = testrun.communicate() return { "error": { "testrun": str(errlog), "returncode": testrun.returncode } } diff --git a/functions/grades/workload.py b/functions/grades/workload.py index c8189a3..15ed235 100644 --- a/functions/grades/workload.py +++ b/functions/grades/workload.py @@ -16,11 +16,11 @@ def handle(req, syscall): return result def app_handle(args, context, syscall): - test_lines = [ json.loads(line) for line in syscall.fsread(args['test_results']).split(b'\n') ] + test_lines = [ json.loads(line) for line in syscall.fs_read(args['test_results']).split(b'\n') ] test_runs = dict((line['test'], line) for line in test_lines if 'test' in line) grader_config = "/cos316/%s/grader_config.json" % context["metadata"]["assignment"] - config = json.loads(syscall.fsread(grader_config)) + config = json.loads(syscall.fs_read(grader_config)) total_points = sum([ test["points"] for test in config["tests"].values() if "extraCredit" not in test or not test["extraCredit"]]) @@ -45,17 +45,13 @@ def app_handle(args, context, syscall): "push_date": context["push_date"] } - user = context['user'] - func = context['function'] - base_dir = os.path.join('/', func, user, context['metadata']['assignment']) - file = os.path.join(base_dir, 'grade.json') - syscall.endorse_with([[func]]) - target_label = syscall.new_dclabel([[user]], [[func]]) - syscall.fscreate_dir(os.path.dirname(base_dir), os.path.basename(base_dir), target_label) - syscall.fscreate_file(base_dir, os.path.basename(file), target_label) - syscall.fswrite(file, bytes(json.dumps(output), "utf-8")) + assignment = context['metadata']['assignment'] + file = 'grade.json' + syscall.workspace_createdir(assignment) + syscall.workspace_createfile(file, assignment) + syscall.workspace_write(os.path.join(assignment, file), bytes(json.dumps(output), "utf-8")) return { "grade": points / total_points, - "grade_report": file - } + "grade_report": syscall.workspace_abspath(os.path.join(assignment, file)) + } From 6b55f33ff094369bb3774c3ee641994a4b3944e5 Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Fri, 10 Jun 2022 22:01:26 -0400 Subject: [PATCH 4/7] update test_ported_functions.sh & payloads --- payloads/go_grader.jsonl | 2 +- payloads/grades.jsonl | 2 +- test_ported_functions.sh | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/payloads/go_grader.jsonl b/payloads/go_grader.jsonl index 3e7bd0b..f299a40 100644 --- a/payloads/go_grader.jsonl +++ b/payloads/go_grader.jsonl @@ -1 +1 @@ -{"args": {"submission": "/gh_repo/user/submission.tgz"}, "workflow": ["grades"], "context": { "metadata": {"assignment": "example"}, "user": "user", "function": "go_grader"}} +{"args": {"submission": "/gh_repo/user/submission.tgz"}, "workflow": ["grades"], "context": { "metadata": {"assignment": "example"}}} diff --git a/payloads/grades.jsonl b/payloads/grades.jsonl index 7bd22f2..098586d 100644 --- a/payloads/grades.jsonl +++ b/payloads/grades.jsonl @@ -1 +1 @@ -{"args": {"test_results": "/go_grader/user/submission/test_results.jsonl"}, "workflow": [], "context": {"commit": "b541c851d79edad1d05fc64c1bcca88800703a30", "metadata": {"assignment": "example"}, "push_date": 1642798607, "repository": "cos316/assignment2-starter-code", "user": "user", "function": "grades"}} +{"args": {"test_results": "/go_grader/user/submission/test_results.jsonl"}, "workflow": [], "context": {"commit": "b541c851d79edad1d05fc64c1bcca88800703a30", "metadata": {"assignment": "example"}, "push_date": 1642798607, "repository": "cos316/assignment2-starter-code"}} diff --git a/test_ported_functions.sh b/test_ported_functions.sh index 05a7e11..6f54600 100755 --- a/test_ported_functions.sh +++ b/test_ported_functions.sh @@ -1,4 +1,4 @@ -SNAPFAAS=https://api.github.com/repos/princeton-sns/snapfaas/tarball/faasten +SNAPFAAS=https://api.github.com/repos/princeton-sns/snapfaas/tarball/syscall IMAGES=https://api.github.com/repos/princeton-sns/snapfaas-images/tarball/faasten WD=$(dirname $(realpath $0)) cd $WD @@ -24,7 +24,7 @@ cp snapfaas/resources/images/vmlinux-4.20.0 . mkdir -p rootfs curl -sL -H "Accept: application/vnd.github.v3+json" $IMAGES | \ tar xzf - -C rootfs --strip-components=2 --wildcards '*/rootfs/common' '*/rootfs/faasten' -cd rootfs/faasten; ./mk_rtimage.sh python3 ../../python3.ext4; cd $WD +cd rootfs/faasten; ./mk_rtimage.sh --local-snapfaas $(realpath ../../snapfaas) python3 ../../python3.ext4; cd $WD if [ ! -f python3.ext4 ] || [ ! -f vmlinux-4.20.0 ]; then exit 1 fi @@ -47,6 +47,7 @@ sffs cat /grades/user/example/grade.json #echo '*********************' #echo '* cleaning up *' #echo '*********************' -#rm -r snapfaas rootfs -#rm vmlinux-4.20.0 -#rm python3.ext4 +rm -r snapfaas +rm -rf rootfs +rm vmlinux-4.20.0 +rm python3.ext4 From 3a804656508601e560e146436f398aee828c133d Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Thu, 23 Jun 2022 15:14:00 -0400 Subject: [PATCH 5/7] switched to use open|create_unnamed syscalls --- Makefile | 3 ++- functions/go_grader/workload.py | 26 ++++++++++----------- functions/grades/workload.py | 31 +++++++++++++++----------- functions/start_assignment/workload.py | 8 +++---- test_ported_functions.sh | 21 ++++++----------- 5 files changed, 43 insertions(+), 46 deletions(-) diff --git a/Makefile b/Makefile index 994d03b..e67c475 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,8 @@ run/%: output/%.img payloads/%.jsonl python3.ext4 .PHONY: debug/% debug/%: export RUST_LOG=debug debug/%: output/%.img payloads/%.jsonl python3.ext4 - @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* --end_users user --kernel_args "console=ttyS0" < payloads/$*.jsonl + @singlevm --mem_size 1024 --kernel vmlinux-4.20.0 --rootfs python3.ext4 --appfs output/$*.img --function $* --secrecy user --integrity user --kernel_args "console=ttyS0" \ + --data test_results:1e38cb34f3a86d9cfadcb735cb92e6869a2ee3f3b952ca30d1d78c5d6ac4e1c0 < payloads/$*.jsonl .PHONY: clean clean: diff --git a/functions/go_grader/workload.py b/functions/go_grader/workload.py index af18382..30cbf7a 100644 --- a/functions/go_grader/workload.py +++ b/functions/go_grader/workload.py @@ -3,27 +3,28 @@ import os import subprocess -def handle(req, syscall): +def handle(req, data_handles, syscall): args = req["args"] workflow = req["workflow"] context = req["context"] - result = app_handle(args, context, syscall) + result, data_handles_out = app_handle(args, context, syscall) if len(workflow) > 0: next_function = workflow.pop(0) syscall.invoke(next_function, json.dumps({ "args": result, "workflow": workflow, "context": context - })) + }), data_handles_out) return result def app_handle(args, context, syscall): + data_handles = dict() + secrecy = syscall.get_current_label().secrecy os.system("ifconfig lo up") # Fetch and untar submission tarball assignment = context["metadata"]["assignment"] with tempfile.NamedTemporaryFile(suffix=".tar.gz") as submission_tar: submission_tar_data = syscall.fs_read(args['submission']) - secrecy = syscall.get_current_label().secrecy submission_tar.write(submission_tar_data) submission_tar.flush() with tempfile.TemporaryDirectory() as submission_dir: @@ -58,17 +59,14 @@ def app_handle(args, context, syscall): if tr["Action"] in ["pass", "fail", "run"]: tr = dict((name.lower(), val) for name, val in tr.items()) final_results.append(json.dumps(tr)) -# key = os.path.join(os.path.splitext(args["submission"])[0], "test_results.jsonl") - submission = os.path.basename(os.path.splitext(args['submission'])[0]) - file = 'test_results.jsonl' - syscall.declassify(secrecy) - syscall.workspace_createdir(submission) - syscall.workspace_createfile(file, submission) - syscall.workspace_write(os.path.join(submission, file), bytes('\n'.join(final_results), "utf-8")) + data = bytes('\n'.join(final_results), "utf-8") + with syscall.create_unnamed(len(data)) as handle: + data_handles['test_results'] = handle.finalize(data) testrun.wait() + syscall.declassify(secrecy) if testrun.returncode >= 0: - return { "test_results": syscall.workspace_abspath(os.path.join(submission, file))} + return {}, data_handles else: _, errlog = testrun.communicate() - return { "error": { "testrun": str(errlog), "returncode": testrun.returncode } } - return {} + return { "error": { "testrun": str(errlog), "returncode": testrun.returncode } }, data_handles + return {}, data_handles diff --git a/functions/grades/workload.py b/functions/grades/workload.py index 15ed235..974a18b 100644 --- a/functions/grades/workload.py +++ b/functions/grades/workload.py @@ -1,22 +1,32 @@ import os import json -def handle(req, syscall): +def handle(req, data_handles, syscall): args = req["args"] workflow = req["workflow"] context = req["context"] - result = app_handle(args, context, syscall) + result, data_handles_out = app_handle(args, context, data_handles, syscall) if len(workflow) > 0: next_function = workflow.pop(0) syscall.invoke(next_function, json.dumps({ "args": result, "workflow": workflow, "context": context - })) + }), data_handles_out) return result -def app_handle(args, context, syscall): - test_lines = [ json.loads(line) for line in syscall.fs_read(args['test_results']).split(b'\n') ] +def read_all(opened_blob): + buf = bytearray() + while True: + data = opened_blob.read() + if len(data) == 0: + return buf + buf.extend(data) + return buf + +def app_handle(args, context, data_handles, syscall): + with syscall.open_unnamed(data_handles['test_results']) as blob: + test_lines = [ json.loads(line) for line in read_all(blob).split(b'\n') ] test_runs = dict((line['test'], line) for line in test_lines if 'test' in line) grader_config = "/cos316/%s/grader_config.json" % context["metadata"]["assignment"] @@ -46,12 +56,7 @@ def app_handle(args, context, syscall): } assignment = context['metadata']['assignment'] - file = 'grade.json' - syscall.workspace_createdir(assignment) - syscall.workspace_createfile(file, assignment) - syscall.workspace_write(os.path.join(assignment, file), bytes(json.dumps(output), "utf-8")) + with syscall.create_unnamed() as blob: + handle = blob.finalize(bytes(json.dumps(output), "utf-8")) - return { - "grade": points / total_points, - "grade_report": syscall.workspace_abspath(os.path.join(assignment, file)) - } + return {"grade": points / total_points}, {"grade_report": handle} diff --git a/functions/start_assignment/workload.py b/functions/start_assignment/workload.py index a24b1e8..7769dc1 100644 --- a/functions/start_assignment/workload.py +++ b/functions/start_assignment/workload.py @@ -20,7 +20,7 @@ frost voice paper frog smoke star""".split() def handle(req, syscall): - assignments = json.loads(syscall.fsread('/cos316/assignments')) + assignments = json.loads(syscall.fs_read('/cos316/assignments')) if req["assignment"] not in assignments: return { 'error': 'No such assignment' } @@ -30,7 +30,7 @@ def handle(req, syscall): return { 'error': 'This assignment requires a group size of %d, given %d.' % (group_size, len(users)) } for user in users: - repo = syscall.fsread('/%s/%s' % (user, req["assignment"])); + repo = syscall.fs_read('/%s/%s' % (user, req["assignment"])); if repo: return { 'error': ("%s is already completing %s at %s" % (user, req['assignment'], repo.decode('utf-8'))) @@ -62,8 +62,8 @@ def handle(req, syscall): return { 'error': "Couldn't add user to repository", "status": resp.status } - syscall.fscreate_file('/start_assignment/%s' % name, '_meta', syscall.get_current_label()) - syscall.fswrite('/start_assignment/%s/_meta' % name, + syscall.workspace_createfile('_meta') + syscall.workspace_write('_meta' % name, bytes(json.dumps({ 'assignment': req['assignment'], 'users': list(users), diff --git a/test_ported_functions.sh b/test_ported_functions.sh index 6f54600..744ee4b 100755 --- a/test_ported_functions.sh +++ b/test_ported_functions.sh @@ -1,4 +1,4 @@ -SNAPFAAS=https://api.github.com/repos/princeton-sns/snapfaas/tarball/syscall +SNAPFAAS=https://api.github.com/repos/princeton-sns/snapfaas/tarball/faasten IMAGES=https://api.github.com/repos/princeton-sns/snapfaas-images/tarball/faasten WD=$(dirname $(realpath $0)) cd $WD @@ -19,12 +19,12 @@ echo '************************' echo '* getting images *' echo '************************' # download the uncompressed kernel -cp snapfaas/resources/images/vmlinux-4.20.0 . +cp snapfaas/resources/images/vmlinux-4.20.0 . # build the python3.ext4 mkdir -p rootfs curl -sL -H "Accept: application/vnd.github.v3+json" $IMAGES | \ tar xzf - -C rootfs --strip-components=2 --wildcards '*/rootfs/common' '*/rootfs/faasten' -cd rootfs/faasten; ./mk_rtimage.sh --local-snapfaas $(realpath ../../snapfaas) python3 ../../python3.ext4; cd $WD +cd rootfs/faasten; ./mk_rtimage.sh --local-snapfaas $(realpath ../../snapfaas) python3 ../../python3.ext4; cd $WD if [ ! -f python3.ext4 ] || [ ! -f vmlinux-4.20.0 ]; then exit 1 fi @@ -37,17 +37,10 @@ make prepfs make run/go_grader make run/grades -echo -echo '**************************************' -echo '* cating function output files *' -echo '**************************************' -sffs cat /go_grader/user/submission/test_results.jsonl -sffs cat /grades/user/example/grade.json - #echo '*********************' #echo '* cleaning up *' #echo '*********************' -rm -r snapfaas -rm -rf rootfs -rm vmlinux-4.20.0 -rm python3.ext4 +#rm -r snapfaas +#rm -rf rootfs +#rm vmlinux-4.20.0 +#rm python3.ext4 From c1ad077ff691f01026c73c2db33b29bb8d64276d Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Wed, 29 Jun 2022 11:34:21 -0400 Subject: [PATCH 6/7] reset start_assignment to the original version --- functions/start_assignment/workload.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/functions/start_assignment/workload.py b/functions/start_assignment/workload.py index 7769dc1..37b604f 100644 --- a/functions/start_assignment/workload.py +++ b/functions/start_assignment/workload.py @@ -20,7 +20,7 @@ frost voice paper frog smoke star""".split() def handle(req, syscall): - assignments = json.loads(syscall.fs_read('/cos316/assignments')) + assignments = json.loads(syscall.read_key(b'cos316/assignments')) if req["assignment"] not in assignments: return { 'error': 'No such assignment' } @@ -30,7 +30,7 @@ def handle(req, syscall): return { 'error': 'This assignment requires a group size of %d, given %d.' % (group_size, len(users)) } for user in users: - repo = syscall.fs_read('/%s/%s' % (user, req["assignment"])); + repo = syscall.read_key(bytes('cos316/assignments/%s/%s' % (req["assignment"], user), 'utf-8')); if repo: return { 'error': ("%s is already completing %s at %s" % (user, req['assignment'], repo.decode('utf-8'))) @@ -62,18 +62,15 @@ def handle(req, syscall): return { 'error': "Couldn't add user to repository", "status": resp.status } - syscall.workspace_createfile('_meta') - syscall.workspace_write('_meta' % name, + syscall.write_key(bytes('github/cos316/%s/_meta' % name, 'utf-8'), bytes(json.dumps({ 'assignment': req['assignment'], 'users': list(users), }), 'utf-8')) - syscall.fscreate_file('/start_assignment/%s' % name, '_workflow', syscall.get_current_label()) - syscall.fswrite('/start_assignment/%s/_workflow' % name, + syscall.write_key(bytes('github/cos316/%s/_workflow' % name, 'utf-8'), bytes(json.dumps(["go_grader", "grades", "generate_report", "post_comment"]), 'utf-8')) for user in users: - syscall.fscreate_file('/%s' % user, req['assignment'], syscall.get_current_label()) - syscall.fswrite('/%s/%s' % (user, req['assignment']), + syscall.write_key(bytes('cos316/assignments/%s/%s' % (req["assignment"], user), 'utf-8'), bytes("cos316/%s" % name, 'utf-8')) return { 'name': name, 'users': list(users), 'github_handles': req['gh_handles'] } From a997530ba7bc8373dceaf73053a6db2062061c40 Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Wed, 29 Jun 2022 13:26:25 -0400 Subject: [PATCH 7/7] reset functions/gh_repo/workload.py to the original version --- functions/gh_repo/workload.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/functions/gh_repo/workload.py b/functions/gh_repo/workload.py index e63d0e9..20e3f7c 100644 --- a/functions/gh_repo/workload.py +++ b/functions/gh_repo/workload.py @@ -4,23 +4,17 @@ import time def handle(req, syscall): -# key = "github/%s/%s.tgz" % (req["repository"]["full_name"], req["after"]) -# meta_key = "github/%s/_meta" % (req["repository"]["full_name"]) -# workflow_key = "github/%s/_workflow" % (req["repository"]["full_name"]) - usergroup = req['repository']['full_name'] - key = '/gh_repo/%s/%s.tgz' % (req['repository']['full_name'], req['after']) - base_dir = '/gh_repo/%s' % usergroup - meta_path = '/start_assignment/%s/_meta' % usergroup - workflow_path = '/start_assignment/%s/_workflow' % usergroup + key = "github/%s/%s.tgz" % (req["repository"]["full_name"], req["after"]) + meta_key = "github/%s/_meta" % (req["repository"]["full_name"]) + workflow_key = "github/%s/_workflow" % (req["repository"]["full_name"]) - metadataString = syscall.fsread(meta_path) or "{}" + metadataString = syscall.read_key(bytes(meta_key, "utf-8")) or "{}" if metadataString: metadata = json.loads(metadataString) - workflow = json.loads(syscall.fsread(workflow_path) or "[]") + workflow = json.loads(syscall.read_key(bytes(workflow_key, "utf-8")) or "[]") resp = syscall.github_rest_get("/repos/%s/tarball/%s" % (req["repository"]["full_name"], req["after"])); - syscall.fscreate_file(base_dir, '%s.tgz' % req['after'], syscall.get_current_label()) - syscall.fswrite(path, resp.data) + syscall.write_key(bytes(key, "utf-8"), resp.data) if len(workflow) > 0: next_function = workflow.pop(0)