summaryrefslogtreecommitdiff
path: root/yaksh/old_code_server.py
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh/old_code_server.py')
-rwxr-xr-xyaksh/old_code_server.py221
1 files changed, 0 insertions, 221 deletions
diff --git a/yaksh/old_code_server.py b/yaksh/old_code_server.py
deleted file mode 100755
index b3c9c30..0000000
--- a/yaksh/old_code_server.py
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/env python
-
-"""This server runs an HTTP server (using tornado) and several code servers
-using XMLRPC that can be submitted code
-and tests and returns the output. It *should* be run as root and will run as
-the user 'nobody' so as to minimize any damange by errant code. This can be
-configured by editing settings.py to run as many servers as desired. One can
-also specify the ports on the command line. Here are examples::
-
- $ sudo ./code_server.py
- # Runs servers based on settings.py:SERVER_PORTS one server per port given.
-
-or::
-
- $ sudo ./code_server.py 8001 8002 8003 8004 8005
- # Runs 5 servers on ports specified.
-
-All these servers should be running as nobody. This will also start a server
-pool that defaults to port 50000 and is configurable in
-settings.py:SERVER_POOL_PORT. This port exposes a `get_server_port` function
-that returns an available server.
-
-"""
-
-# Standard library imports
-from __future__ import unicode_literals
-import json
-from multiprocessing import Process, Queue
-import os
-from os.path import isdir, dirname, abspath, join, isfile
-import pwd
-import re
-import signal
-import stat
-import subprocess
-import sys
-
-try:
- from SimpleXMLRPCServer import SimpleXMLRPCServer
-except ImportError:
- # The above import will not work on Python-3.x.
- from xmlrpc.server import SimpleXMLRPCServer
-
-try:
- from urllib import unquote
-except ImportError:
- # The above import will not work on Python-3.x.
- from urllib.parse import unquote
-
-# Library imports
-from tornado.ioloop import IOLoop
-from tornado.web import Application, RequestHandler
-
-# Local imports
-from .settings import SERVER_PORTS, SERVER_POOL_PORT
-from .language_registry import create_evaluator_instance, unpack_json
-
-
-MY_DIR = abspath(dirname(__file__))
-
-
-# Private Protocol ##########
-def run_as_nobody():
- """Runs the current process as nobody."""
- # Set the effective uid and to that of nobody.
- nobody = pwd.getpwnam('nobody')
- os.setegid(nobody.pw_gid)
- os.seteuid(nobody.pw_uid)
-
-
-###############################################################################
-# `CodeServer` class.
-###############################################################################
-class CodeServer(object):
- """A code server that executes user submitted test code, tests it and
- reports if the code was correct or not.
- """
- def __init__(self, port, queue):
- self.port = port
- self.queue = queue
-
- # Public Protocol ##########
- def check_code(self, language, test_case_type, json_data, in_dir=None):
- """Calls relevant EvaluateCode class based on language to check the
- answer code
- """
- code_evaluator = create_evaluator_instance(language,
- test_case_type,
- json_data,
- in_dir
- )
- data = unpack_json(json_data)
- result = code_evaluator.evaluate(**data)
-
- # Put us back into the server pool queue since we are free now.
- self.queue.put(self.port)
-
- return json.dumps(result)
-
- def run(self):
- """Run XMLRPC server, serving our methods."""
- server = SimpleXMLRPCServer(("0.0.0.0", self.port))
- self.server = server
- server.register_instance(self)
- self.queue.put(self.port)
- server.serve_forever()
-
-
-###############################################################################
-# `ServerPool` class.
-###############################################################################
-class ServerPool(object):
- """Manages a pool of CodeServer objects."""
- def __init__(self, ports, pool_port=50000):
- """Create a pool of servers. Uses a shared Queue to get available
- servers.
-
- Parameters
- ----------
-
- ports : list(int)
- List of ports at which the CodeServer's should run.
-
- pool_port : int
- Port at which the server pool should serve.
- """
- self.my_port = pool_port
- self.ports = ports
- queue = Queue(maxsize=len(self.ports))
- self.queue = queue
- servers = []
- processes = []
- for port in self.ports:
- server = CodeServer(port, queue)
- servers.append(server)
- p = Process(target=server.run)
- processes.append(p)
- self.servers = servers
- self.processes = processes
- self.app = self._make_app()
-
- def _make_app(self):
- app = Application([
- (r"/.*", MainHandler, dict(server=self)),
- ])
- app.listen(self.my_port)
- return app
-
- def _start_code_servers(self):
- for proc in self.processes:
- if proc.pid is None:
- proc.start()
-
- # Public Protocol ##########
-
- def get_server_port(self):
- """Get available server port from ones in the pool. This will block
- till it gets an available server.
- """
- return self.queue.get()
-
- def get_status(self):
- """Returns current queue size and total number of ports used."""
- try:
- qs = self.queue.qsize()
- except NotImplementedError:
- # May not work on OS X so we return a dummy.
- qs = len(self.ports)
-
- return qs, len(self.ports)
-
- def run(self):
- """Run server which returns an available server port where code
- can be executed.
- """
- # We start the code servers here to ensure they are run as nobody.
- self._start_code_servers()
- IOLoop.current().start()
-
- def stop(self):
- """Stop all the code server processes.
- """
- for proc in self.processes:
- proc.terminate()
- IOLoop.current().stop()
-
-
-class MainHandler(RequestHandler):
- def initialize(self, server):
- self.server = server
-
- def get(self):
- path = self.request.path[1:]
- if len(path) == 0:
- port = self.server.get_server_port()
- self.write(str(port))
- elif path == "status":
- q_size, total = self.server.get_status()
- result = "%d servers out of %d are free.\n"%(q_size, total)
- load = float(total - q_size)/total*100
- result += "Load: %s%%\n"%load
- self.write(result)
-
-
-###############################################################################
-def main(args=None):
- if args:
- ports = [int(x) for x in args]
- else:
- ports = SERVER_PORTS
-
- server_pool = ServerPool(ports=ports, pool_port=SERVER_POOL_PORT)
- # This is done *after* the server pool is created because when the tornado
- # app calls listen(), it cannot be nobody.
- run_as_nobody()
-
- server_pool.run()
-
-if __name__ == '__main__':
- args = sys.argv[1:]
- main(args)