mirror of
https://github.com/QingdaoU/JudgeServer.git
synced 2024-12-28 21:31:43 +00:00
Python3 server
This commit is contained in:
parent
e27c662a66
commit
48abe6dacb
@ -6,8 +6,9 @@ before_install:
|
|||||||
- sudo mkdir -p /data/log
|
- sudo mkdir -p /data/log
|
||||||
- pip install requests
|
- pip install requests
|
||||||
script:
|
script:
|
||||||
- docker pull qduoj/judge_server
|
- docker pull qduoj/judge-server
|
||||||
- cp docker-compose.example.yml docker-compose.yml
|
- cp docker-compose.example.yml docker-compose.yml
|
||||||
- docker-compose up -d
|
- docker-compose up -d
|
||||||
- docker ps -a
|
- docker ps -a
|
||||||
|
- sleep 5
|
||||||
- python tests/tests.py
|
- python tests/tests.py
|
||||||
|
13
Dockerfile
13
Dockerfile
@ -1,21 +1,20 @@
|
|||||||
FROM registry.docker-cn.com/library/ubuntu:16.04
|
FROM registry.docker-cn.com/library/ubuntu:16.04
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
|
||||||
|
|
||||||
COPY build/java_policy /etc
|
COPY build/java_policy /etc
|
||||||
|
|
||||||
RUN buildDeps='software-properties-common git libtool cmake python-dev python-pip libseccomp-dev' && \
|
RUN buildDeps='software-properties-common git libtool cmake python-dev python3-pip python-pip libseccomp-dev' && \
|
||||||
apt-get update && apt-get install -y python python3.5 python-pkg-resources gcc g++ $buildDeps && \
|
apt-get update && apt-get install -y python python3.5 python-pkg-resources python3-pkg-resources gcc g++ $buildDeps && \
|
||||||
add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-7-jdk && \
|
add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-9-jdk-headless && \
|
||||||
pip install --no-cache-dir futures psutil gunicorn web.py requests && \
|
pip3 install --no-cache-dir psutil gunicorn flask requests && \
|
||||||
cd /tmp && git clone -b newnew --depth 1 https://github.com/QingdaoU/Judger && cd Judger && \
|
cd /tmp && git clone -b newnew --depth 1 https://github.com/QingdaoU/Judger && cd Judger && \
|
||||||
mkdir build && cd build && cmake .. && make && make install && cd ../bindings/Python && python setup.py install && \
|
mkdir build && cd build && cmake .. && make && make install && cd ../bindings/Python && python3 setup.py install && \
|
||||||
apt-get purge -y --auto-remove $buildDeps && \
|
apt-get purge -y --auto-remove $buildDeps && \
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN mkdir -p /judger_run /test_case /log /code && \
|
RUN mkdir -p /judger_run /test_case /log /code && \
|
||||||
useradd -r compiler
|
useradd -r compiler
|
||||||
|
|
||||||
HEALTHCHECK --interval=5s --retries=3 CMD python /code/service.py
|
HEALTHCHECK --interval=5s --retries=3 CMD python3 /code/service.py
|
||||||
ADD server /code
|
ADD server /code
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import unicode_literals, print_function
|
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@ -27,7 +24,7 @@ class JudgeServerClient(object):
|
|||||||
try:
|
try:
|
||||||
return requests.post(url, **kwargs).json()
|
return requests.post(url, **kwargs).json()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise JudgeServerClientError(e.message)
|
raise JudgeServerClientError(str(e))
|
||||||
|
|
||||||
def ping(self):
|
def ping(self):
|
||||||
return self._request(self.server_base_url + "/ping")
|
return self._request(self.server_base_url + "/ping")
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
# coding=utf-8
|
import _judger
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import _judger
|
|
||||||
|
|
||||||
from config import COMPILER_LOG_PATH, COMPILER_USER_UID, COMPILER_GROUP_GID
|
from config import COMPILER_LOG_PATH, COMPILER_USER_UID, COMPILER_GROUP_GID
|
||||||
from exception import CompileError
|
from exception import CompileError
|
||||||
|
|
||||||
@ -24,13 +20,13 @@ class Compiler(object):
|
|||||||
max_stack=128 * 1024 * 1024,
|
max_stack=128 * 1024 * 1024,
|
||||||
max_output_size=1024 * 1024,
|
max_output_size=1024 * 1024,
|
||||||
max_process_number=_judger.UNLIMITED,
|
max_process_number=_judger.UNLIMITED,
|
||||||
exe_path=_command[0].encode("utf-8"),
|
exe_path=_command[0],
|
||||||
# /dev/null is best, but in some system, this will call ioctl system call
|
# /dev/null is best, but in some system, this will call ioctl system call
|
||||||
input_path=src_path.encode("utf-8"),
|
input_path=src_path,
|
||||||
output_path=compiler_out.encode("utf-8"),
|
output_path=compiler_out,
|
||||||
error_path=compiler_out.encode("utf-8"),
|
error_path=compiler_out,
|
||||||
args=[item.encode("utf-8") for item in _command[1::]],
|
args=_command[1::],
|
||||||
env=[("PATH=" + os.getenv("PATH")).encode("utf-8")],
|
env=["PATH=" + os.getenv("PATH")],
|
||||||
log_path=COMPILER_LOG_PATH,
|
log_path=COMPILER_LOG_PATH,
|
||||||
seccomp_rule_name=None,
|
seccomp_rule_name=None,
|
||||||
uid=COMPILER_USER_UID,
|
uid=COMPILER_USER_UID,
|
||||||
@ -43,7 +39,7 @@ class Compiler(object):
|
|||||||
os.remove(compiler_out)
|
os.remove(compiler_out)
|
||||||
if error:
|
if error:
|
||||||
raise CompileError(error)
|
raise CompileError(error)
|
||||||
raise CompileError("Compiler runtime error, info: %s" % json.dumps(result).decode("utf-8"))
|
raise CompileError("Compiler runtime error, info: %s" % json.dumps(result))
|
||||||
else:
|
else:
|
||||||
os.remove(compiler_out)
|
os.remove(compiler_out)
|
||||||
return exe_path
|
return exe_path
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import grp
|
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
|
|
||||||
|
import grp
|
||||||
|
|
||||||
JUDGER_WORKSPACE_BASE = "/judger_run"
|
JUDGER_WORKSPACE_BASE = "/judger_run"
|
||||||
LOG_BASE = "/log"
|
LOG_BASE = "/log"
|
||||||
|
|
||||||
COMPILER_LOG_PATH = os.path.join(LOG_BASE, "compile.log").encode("utf-8")
|
COMPILER_LOG_PATH = os.path.join(LOG_BASE, "compile.log")
|
||||||
JUDGER_RUN_LOG_PATH = os.path.join(LOG_BASE, "judger.log").encode("utf-8")
|
JUDGER_RUN_LOG_PATH = os.path.join(LOG_BASE, "judger.log")
|
||||||
|
SERVER_LOG_PATH = os.path.join(LOG_BASE, "judge_server.log")
|
||||||
|
|
||||||
RUN_USER_UID = pwd.getpwnam("nobody").pw_uid
|
RUN_USER_UID = pwd.getpwnam("nobody").pw_uid
|
||||||
RUN_GROUP_GID = grp.getgrnam("nogroup").gr_gid
|
RUN_GROUP_GID = grp.getgrnam("nogroup").gr_gid
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
chown compiler:compiler /spj
|
chown compiler:compiler /spj
|
||||||
core=$(grep --count ^processor /proc/cpuinfo)
|
core=$(grep --count ^processor /proc/cpuinfo)
|
||||||
n=$(($core*2))
|
n=$(($core*2))
|
||||||
exec gunicorn --workers $n --threads $n --error-logfile /log/gunicorn.log --time 600 --bind 0.0.0.0:8080 server:wsgiapp
|
exec gunicorn --workers $n --threads $n --error-logfile /log/gunicorn.log --time 600 --bind 0.0.0.0:8080 server:app
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
from __future__ import unicode_literals
|
class JudgeServerException(Exception):
|
||||||
|
def __init__(self, message):
|
||||||
|
super().__init__()
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
class CompileError(Exception):
|
class CompileError(JudgeServerException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SPJCompileError(CompileError):
|
class SPJCompileError(JudgeServerException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TokenVerificationFailed(Exception):
|
class TokenVerificationFailed(JudgeServerException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class JudgeClientError(Exception):
|
class JudgeClientError(JudgeServerException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class JudgeServiceError(Exception):
|
class JudgeServiceError(JudgeServerException):
|
||||||
pass
|
pass
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import _judger
|
import _judger
|
||||||
import psutil
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
import psutil
|
||||||
|
|
||||||
from config import TEST_CASE_DIR, JUDGER_RUN_LOG_PATH, RUN_GROUP_GID, RUN_USER_UID, SPJ_EXE_DIR
|
from config import TEST_CASE_DIR, JUDGER_RUN_LOG_PATH, RUN_GROUP_GID, RUN_USER_UID, SPJ_EXE_DIR
|
||||||
from exception import JudgeClientError
|
from exception import JudgeClientError
|
||||||
|
|
||||||
|
|
||||||
SPJ_WA = 1
|
SPJ_WA = 1
|
||||||
SPJ_AC = 0
|
SPJ_AC = 0
|
||||||
SPJ_ERROR = -1
|
SPJ_ERROR = -1
|
||||||
@ -40,14 +37,15 @@ class JudgeClient(object):
|
|||||||
self._spj_config = spj_config
|
self._spj_config = spj_config
|
||||||
self._output = output
|
self._output = output
|
||||||
if self._spj_version and self._spj_config:
|
if self._spj_version and self._spj_config:
|
||||||
self._spj_exe = os.path.join(SPJ_EXE_DIR, self._spj_config["exe_name"].format(spj_version=self._spj_version))
|
self._spj_exe = os.path.join(SPJ_EXE_DIR,
|
||||||
|
self._spj_config["exe_name"].format(spj_version=self._spj_version))
|
||||||
if not os.path.exists(self._spj_exe):
|
if not os.path.exists(self._spj_exe):
|
||||||
raise JudgeClientError("spj exe not found")
|
raise JudgeClientError("spj exe not found")
|
||||||
|
|
||||||
def _load_test_case_info(self):
|
def _load_test_case_info(self):
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(self._test_case_dir, "info")) as f:
|
with open(os.path.join(self._test_case_dir, "info")) as f:
|
||||||
return json.loads(f.read())
|
return json.load(f)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise JudgeClientError("Test case not found")
|
raise JudgeClientError("Test case not found")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -60,7 +58,7 @@ class JudgeClient(object):
|
|||||||
user_output_file = os.path.join(self._submission_dir, str(test_case_file_id) + ".out")
|
user_output_file = os.path.join(self._submission_dir, str(test_case_file_id) + ".out")
|
||||||
with open(user_output_file, "r") as f:
|
with open(user_output_file, "r") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
output_md5 = hashlib.md5(content.rstrip()).hexdigest()
|
output_md5 = hashlib.md5(content.rstrip().encode("utf-8")).hexdigest()
|
||||||
result = output_md5 == self._get_test_case_file_info(test_case_file_id)["stripped_output_md5"]
|
result = output_md5 == self._get_test_case_file_info(test_case_file_id)["stripped_output_md5"]
|
||||||
return output_md5, result
|
return output_md5, result
|
||||||
|
|
||||||
@ -68,19 +66,19 @@ class JudgeClient(object):
|
|||||||
command = self._spj_config["command"].format(exe_path=self._spj_exe,
|
command = self._spj_config["command"].format(exe_path=self._spj_exe,
|
||||||
in_file_path=in_file_path,
|
in_file_path=in_file_path,
|
||||||
user_out_file_path=user_out_file_path).split(" ")
|
user_out_file_path=user_out_file_path).split(" ")
|
||||||
seccomp_rule_name = self._spj_config["seccomp_rule"].encode("utf-8") if self._spj_config["seccomp_rule"] else None
|
seccomp_rule_name = self._spj_config["seccomp_rule"]
|
||||||
result = _judger.run(max_cpu_time=self._max_cpu_time * 3,
|
result = _judger.run(max_cpu_time=self._max_cpu_time * 3,
|
||||||
max_real_time=self._max_cpu_time * 9,
|
max_real_time=self._max_cpu_time * 9,
|
||||||
max_memory=self._max_memory * 3,
|
max_memory=self._max_memory * 3,
|
||||||
max_stack=128 * 1024 * 1024,
|
max_stack=128 * 1024 * 1024,
|
||||||
max_output_size=1024 * 1024 * 1024,
|
max_output_size=1024 * 1024 * 1024,
|
||||||
max_process_number=_judger.UNLIMITED,
|
max_process_number=_judger.UNLIMITED,
|
||||||
exe_path=command[0].encode("utf-8"),
|
exe_path=command[0],
|
||||||
input_path=in_file_path.encode("utf-8"),
|
input_path=in_file_path,
|
||||||
output_path="/tmp/spj.out".encode("utf-8"),
|
output_path="/tmp/spj.out",
|
||||||
error_path="/tmp/spj.out".encode("utf-8"),
|
error_path="/tmp/spj.out",
|
||||||
args=[item.encode("utf-8") for item in command[1::]],
|
args=command[1::],
|
||||||
env=[("PATH=" + os.environ.get("PATH", "")).encode("utf-8")],
|
env=["PATH=" + os.environ.get("PATH", "")],
|
||||||
log_path=JUDGER_RUN_LOG_PATH,
|
log_path=JUDGER_RUN_LOG_PATH,
|
||||||
seccomp_rule_name=seccomp_rule_name,
|
seccomp_rule_name=seccomp_rule_name,
|
||||||
uid=RUN_USER_UID,
|
uid=RUN_USER_UID,
|
||||||
@ -94,13 +92,12 @@ class JudgeClient(object):
|
|||||||
return SPJ_ERROR
|
return SPJ_ERROR
|
||||||
|
|
||||||
def _judge_one(self, test_case_file_id):
|
def _judge_one(self, test_case_file_id):
|
||||||
in_file = os.path.join(self._test_case_dir, self._get_test_case_file_info(test_case_file_id)["input_name"]).encode("utf-8")
|
in_file = os.path.join(self._test_case_dir, self._get_test_case_file_info(test_case_file_id)["input_name"])
|
||||||
user_output_file = os.path.join(self._submission_dir, test_case_file_id + ".out").encode("utf-8")
|
user_output_file = os.path.join(self._submission_dir, test_case_file_id + ".out")
|
||||||
|
|
||||||
command = self._run_config["command"].format(exe_path=self._exe_path, exe_dir=os.path.dirname(self._exe_path),
|
command = self._run_config["command"].format(exe_path=self._exe_path, exe_dir=os.path.dirname(self._exe_path),
|
||||||
max_memory=self._max_memory / 1024).split(" ")
|
max_memory=self._max_memory / 1024).split(" ")
|
||||||
seccomp_rule_name = self._run_config["seccomp_rule"].encode("utf-8") if self._run_config["seccomp_rule"] else None
|
env = ["PATH=" + os.environ.get("PATH", "")] + self._run_config.get("env", [])
|
||||||
env = [item.encode("utf-8") for item in ["PATH=" + os.environ.get("PATH", "")] + self._run_config.get("env", [])]
|
|
||||||
|
|
||||||
run_result = _judger.run(max_cpu_time=self._max_cpu_time,
|
run_result = _judger.run(max_cpu_time=self._max_cpu_time,
|
||||||
max_real_time=self._max_real_time,
|
max_real_time=self._max_real_time,
|
||||||
@ -108,14 +105,14 @@ class JudgeClient(object):
|
|||||||
max_stack=128 * 1024 * 1024,
|
max_stack=128 * 1024 * 1024,
|
||||||
max_output_size=1024 * 1024 * 1024,
|
max_output_size=1024 * 1024 * 1024,
|
||||||
max_process_number=_judger.UNLIMITED,
|
max_process_number=_judger.UNLIMITED,
|
||||||
exe_path=command[0].encode("utf-8"),
|
exe_path=command[0],
|
||||||
input_path=in_file,
|
input_path=in_file,
|
||||||
output_path=user_output_file,
|
output_path=user_output_file,
|
||||||
error_path=user_output_file,
|
error_path=user_output_file,
|
||||||
args=[item.encode("utf-8") for item in command[1::]],
|
args=command[1::],
|
||||||
env=env,
|
env=env,
|
||||||
log_path=JUDGER_RUN_LOG_PATH,
|
log_path=JUDGER_RUN_LOG_PATH,
|
||||||
seccomp_rule_name=seccomp_rule_name,
|
seccomp_rule_name=self._run_config["seccomp_rule"],
|
||||||
uid=RUN_USER_UID,
|
uid=RUN_USER_UID,
|
||||||
gid=RUN_GROUP_GID)
|
gid=RUN_GROUP_GID)
|
||||||
run_result["test_case"] = test_case_file_id
|
run_result["test_case"] = test_case_file_id
|
||||||
@ -144,7 +141,7 @@ class JudgeClient(object):
|
|||||||
if self._output:
|
if self._output:
|
||||||
try:
|
try:
|
||||||
with open(user_output_file, "r") as f:
|
with open(user_output_file, "r") as f:
|
||||||
run_result["output"] = f.read().decode("utf-8")
|
run_result["output"] = f.read()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -153,7 +150,7 @@ class JudgeClient(object):
|
|||||||
def run(self):
|
def run(self):
|
||||||
tmp_result = []
|
tmp_result = []
|
||||||
result = []
|
result = []
|
||||||
for test_case_file_id, _ in self._test_case_info["test_cases"].iteritems():
|
for test_case_file_id, _ in self._test_case_info["test_cases"].items():
|
||||||
tmp_result.append(self._pool.apply_async(_run, (self, test_case_file_id)))
|
tmp_result.append(self._pool.apply_async(_run, (self, test_case_file_id)))
|
||||||
self._pool.close()
|
self._pool.close()
|
||||||
self._pool.join()
|
self._pool.join()
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import web
|
from flask import Flask, request, Response
|
||||||
|
|
||||||
from compiler import Compiler
|
from compiler import Compiler
|
||||||
from config import JUDGER_WORKSPACE_BASE, SPJ_SRC_DIR, SPJ_EXE_DIR
|
from config import JUDGER_WORKSPACE_BASE, SPJ_SRC_DIR, SPJ_EXE_DIR
|
||||||
from exception import TokenVerificationFailed, CompileError, SPJCompileError,JudgeClientError
|
from exception import TokenVerificationFailed, CompileError, SPJCompileError, JudgeClientError
|
||||||
from judge_client import JudgeClient
|
from judge_client import JudgeClient
|
||||||
from utils import server_info, logger, token
|
from utils import server_info, logger, token
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
DEBUG = os.environ.get("judger_debug") == "1"
|
DEBUG = os.environ.get("judger_debug") == "1"
|
||||||
|
app.debug = DEBUG
|
||||||
|
|
||||||
|
|
||||||
class InitSubmissionEnv(object):
|
class InitSubmissionEnv(object):
|
||||||
@ -25,7 +23,7 @@ class InitSubmissionEnv(object):
|
|||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
try:
|
try:
|
||||||
os.mkdir(self.path)
|
os.mkdir(self.path)
|
||||||
os.chmod(self.path, 0777)
|
os.chmod(self.path, 0o777)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
raise JudgeClientError("failed to create runtime dir")
|
raise JudgeClientError("failed to create runtime dir")
|
||||||
@ -40,25 +38,27 @@ class InitSubmissionEnv(object):
|
|||||||
raise JudgeClientError("failed to clean runtime dir")
|
raise JudgeClientError("failed to clean runtime dir")
|
||||||
|
|
||||||
|
|
||||||
class JudgeServer(object):
|
class JudgeServer:
|
||||||
def pong(self):
|
@classmethod
|
||||||
|
def ping(cls):
|
||||||
data = server_info()
|
data = server_info()
|
||||||
data["action"] = "pong"
|
data["action"] = "pong"
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def judge(self, language_config, src, max_cpu_time, max_memory, test_case_id,
|
@classmethod
|
||||||
|
def judge(cls, language_config, src, max_cpu_time, max_memory, test_case_id,
|
||||||
spj_version=None, spj_config=None, spj_compile_config=None, spj_src=None, output=False):
|
spj_version=None, spj_config=None, spj_compile_config=None, spj_src=None, output=False):
|
||||||
# init
|
# init
|
||||||
compile_config = language_config.get("compile")
|
compile_config = language_config.get("compile")
|
||||||
run_config = language_config["run"]
|
run_config = language_config["run"]
|
||||||
submission_id = str(uuid.uuid4())
|
submission_id = uuid.uuid4().hex
|
||||||
|
|
||||||
if spj_version and spj_config:
|
if spj_version and spj_config:
|
||||||
spj_exe_path = os.path.join(SPJ_EXE_DIR, spj_config["exe_name"].format(spj_version=spj_version))
|
spj_exe_path = os.path.join(SPJ_EXE_DIR, spj_config["exe_name"].format(spj_version=spj_version))
|
||||||
# spj src has not been compiled
|
# spj src has not been compiled
|
||||||
if not os.path.isfile(spj_exe_path):
|
if not os.path.isfile(spj_exe_path):
|
||||||
logger.warning("%s does not exists, spj src will be recompiled")
|
logger.warning("%s does not exists, spj src will be recompiled")
|
||||||
self.compile_spj(spj_version=spj_version, src=spj_src,
|
cls.compile_spj(spj_version=spj_version, src=spj_src,
|
||||||
spj_compile_config=spj_compile_config)
|
spj_compile_config=spj_compile_config)
|
||||||
|
|
||||||
with InitSubmissionEnv(JUDGER_WORKSPACE_BASE, submission_id=str(submission_id)) as submission_dir:
|
with InitSubmissionEnv(JUDGER_WORKSPACE_BASE, submission_id=str(submission_id)) as submission_dir:
|
||||||
@ -67,7 +67,7 @@ class JudgeServer(object):
|
|||||||
|
|
||||||
# write source code into file
|
# write source code into file
|
||||||
with open(src_path, "w") as f:
|
with open(src_path, "w") as f:
|
||||||
f.write(src.encode("utf-8"))
|
f.write(src)
|
||||||
|
|
||||||
# compile source code, return exe file path
|
# compile source code, return exe file path
|
||||||
exe_path = Compiler().compile(compile_config=compile_config,
|
exe_path = Compiler().compile(compile_config=compile_config,
|
||||||
@ -76,7 +76,7 @@ class JudgeServer(object):
|
|||||||
else:
|
else:
|
||||||
exe_path = os.path.join(submission_dir, run_config["exe_name"])
|
exe_path = os.path.join(submission_dir, run_config["exe_name"])
|
||||||
with open(exe_path, "w") as f:
|
with open(exe_path, "w") as f:
|
||||||
f.write(src.encode("utf-8"))
|
f.write(src)
|
||||||
|
|
||||||
judge_client = JudgeClient(run_config=language_config["run"],
|
judge_client = JudgeClient(run_config=language_config["run"],
|
||||||
exe_path=exe_path,
|
exe_path=exe_path,
|
||||||
@ -91,7 +91,8 @@ class JudgeServer(object):
|
|||||||
|
|
||||||
return run_result
|
return run_result
|
||||||
|
|
||||||
def compile_spj(self, spj_version, src, spj_compile_config):
|
@classmethod
|
||||||
|
def compile_spj(cls, spj_version, src, spj_compile_config):
|
||||||
spj_compile_config["src_name"] = spj_compile_config["src_name"].format(spj_version=spj_version)
|
spj_compile_config["src_name"] = spj_compile_config["src_name"].format(spj_version=spj_version)
|
||||||
spj_compile_config["exe_name"] = spj_compile_config["exe_name"].format(spj_version=spj_version)
|
spj_compile_config["exe_name"] = spj_compile_config["exe_name"].format(spj_version=spj_version)
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ class JudgeServer(object):
|
|||||||
# if spj source code not found, then write it into file
|
# if spj source code not found, then write it into file
|
||||||
if not os.path.exists(spj_src_path):
|
if not os.path.exists(spj_src_path):
|
||||||
with open(spj_src_path, "w") as f:
|
with open(spj_src_path, "w") as f:
|
||||||
f.write(src.encode("utf-8"))
|
f.write(src)
|
||||||
try:
|
try:
|
||||||
Compiler().compile(compile_config=spj_compile_config,
|
Compiler().compile(compile_config=spj_compile_config,
|
||||||
src_path=spj_src_path,
|
src_path=spj_src_path,
|
||||||
@ -110,56 +111,34 @@ class JudgeServer(object):
|
|||||||
raise SPJCompileError(e.message)
|
raise SPJCompileError(e.message)
|
||||||
return "success"
|
return "success"
|
||||||
|
|
||||||
def POST(self):
|
|
||||||
_token = web.ctx.env.get("HTTP_X_JUDGE_SERVER_TOKEN", None)
|
@app.route('/', defaults={'path': ''})
|
||||||
|
@app.route('/<path:path>', methods=["POST"])
|
||||||
|
def server(path):
|
||||||
|
if path in ("judge", "ping", "compile_spj"):
|
||||||
|
_token = request.headers.get("X-Judge-Server-Token")
|
||||||
try:
|
try:
|
||||||
if _token != token:
|
if _token != token:
|
||||||
raise TokenVerificationFailed("invalid token")
|
raise TokenVerificationFailed("invalid token")
|
||||||
if web.data():
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(web.data())
|
data = request.json
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.info(web.data())
|
|
||||||
return {"ret": "ServerError", "data": "invalid json"}
|
|
||||||
else:
|
|
||||||
data = {}
|
data = {}
|
||||||
|
ret = {"err": None, "data": getattr(JudgeServer, path)(**data)}
|
||||||
if web.ctx["path"] == "/judge":
|
|
||||||
callback = self.judge
|
|
||||||
elif web.ctx["path"] == "/ping":
|
|
||||||
callback = self.pong
|
|
||||||
elif web.ctx["path"] == "/compile_spj":
|
|
||||||
callback = self.compile_spj
|
|
||||||
else:
|
|
||||||
return json.dumps({"err": "InvalidMethod", "data": None})
|
|
||||||
return json.dumps({"err": None, "data": callback(**data)})
|
|
||||||
except (CompileError, TokenVerificationFailed, SPJCompileError, JudgeClientError) as e:
|
except (CompileError, TokenVerificationFailed, SPJCompileError, JudgeClientError) as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
ret = dict()
|
ret = {"err": e.__class__.__name__, "data": e.message}
|
||||||
ret["err"] = e.__class__.__name__
|
|
||||||
ret["data"] = e.message
|
|
||||||
return json.dumps(ret)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
ret = dict()
|
ret = {"err": "JudgeClientError", "data": e.__class__.__name__ + " :" + str(e)}
|
||||||
ret["err"] = "JudgeClientError"
|
else:
|
||||||
ret["data"] =e.__class__.__name__ + ":" + e.message
|
ret = {"err": "InvalidRequest", "data": "404"}
|
||||||
return json.dumps(ret)
|
return Response(json.dumps(ret), mimetype='application/json')
|
||||||
|
|
||||||
|
|
||||||
urls = (
|
|
||||||
"/judge", "JudgeServer",
|
|
||||||
"/ping", "JudgeServer",
|
|
||||||
"/compile_spj", "JudgeServer"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
logger.info("DEBUG=ON")
|
logger.info("DEBUG=ON")
|
||||||
|
|
||||||
app = web.application(urls, globals())
|
# gunicorn -w 4 -b 0.0.0.0:8080 server:app
|
||||||
wsgiapp = app.wsgifunc()
|
|
||||||
|
|
||||||
# gunicorn -w 4 -b 0.0.0.0:8080 server:wsgiapp
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run()
|
app.run(debug=DEBUG)
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import hashlib
|
|
||||||
|
|
||||||
from exception import JudgeServiceError
|
from exception import JudgeServiceError
|
||||||
from utils import server_info, logger, token
|
from utils import server_info, logger, token
|
||||||
@ -30,7 +28,6 @@ class JudgeService(object):
|
|||||||
logger.exception("Heartbeat failed, response is {}".format(resp))
|
logger.exception("Heartbeat failed, response is {}".format(resp))
|
||||||
raise JudgeServiceError("Invalid heartbeat response")
|
raise JudgeServiceError("Invalid heartbeat response")
|
||||||
|
|
||||||
|
|
||||||
def heartbeat(self):
|
def heartbeat(self):
|
||||||
data = server_info()
|
data = server_info()
|
||||||
data["action"] = "heartbeat"
|
data["action"] = "heartbeat"
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
# coding=utf-8
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import _judger
|
import _judger
|
||||||
import psutil
|
|
||||||
import socket
|
|
||||||
import logging
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import socket
|
||||||
|
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
from config import SERVER_LOG_PATH
|
||||||
from exception import JudgeClientError
|
from exception import JudgeClientError
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
handler = logging.FileHandler("/log/judge_server.log")
|
handler = logging.FileHandler(SERVER_LOG_PATH)
|
||||||
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
|
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
@ -32,8 +31,7 @@ def get_token():
|
|||||||
if token:
|
if token:
|
||||||
return token
|
return token
|
||||||
else:
|
else:
|
||||||
raise JudgeClientError("env 'token' not found")
|
raise JudgeClientError("env 'TOKEN' not found")
|
||||||
|
|
||||||
|
|
||||||
token = hashlib.sha256(get_token()).hexdigest()
|
token = hashlib.sha256(get_token().encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user