7a06040a76
Summary: `JailService` exposes jail API and knows how to start and stop binaries. Every test should be defined as python module with exposed `run` method. Script `master.py` is used for running tests and takes test module name as argument. Machine IP addresses are defined in environment variables. To run test locally use `local_runner` script. Reviewers: mislav.bradac, mferencevic, mtomic Reviewed By: mferencevic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1065
117 lines
3.5 KiB
Python
Executable File
117 lines
3.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import logging
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import traceback
|
|
import uuid
|
|
import xmlrpc.client
|
|
from common import get_absolute_path
|
|
from xmlrpc.server import SimpleXMLRPCServer
|
|
|
|
try:
|
|
import jail
|
|
except:
|
|
import jail_faker as jail
|
|
|
|
|
|
class XMLRPCServer(SimpleXMLRPCServer):
|
|
def _dispatch(self, method, params):
|
|
try:
|
|
return super()._dispatch(method, params)
|
|
except:
|
|
traceback.print_exc()
|
|
raise
|
|
|
|
|
|
class JailService:
|
|
"""
|
|
Knows how to start and stop binaries
|
|
"""
|
|
def __init__(self):
|
|
logging.basicConfig(level=logging.INFO)
|
|
self.log = logging.getLogger("JailService")
|
|
self.log.info("Initializing Jail Service")
|
|
self.processes = {}
|
|
self._generated_filenames = []
|
|
self.tempdir = tempfile.TemporaryDirectory()
|
|
|
|
def start(self, tid, binary_name, binary_args=None):
|
|
self.log.info("Starting Binary: {binary}".format(binary=binary_name))
|
|
self.log.info("With args: {args}".format(args=binary_args))
|
|
# find executable path
|
|
binary = get_absolute_path(binary_name, "build")
|
|
if not os.path.exists(binary):
|
|
# Apollo builds both debug and release binaries on diff
|
|
# so we need to use the release binary if the debug one
|
|
# doesn't exist
|
|
binary = get_absolute_path(binary_name, "build_release")
|
|
|
|
# fetch process
|
|
proc = self.processes[tid]
|
|
|
|
# start binary
|
|
proc.run(binary, args=binary_args, timeout=600)
|
|
|
|
msg = "Binary {binary} successfully started with tid {tid}".format(
|
|
binary=binary_name, tid=proc._tid)
|
|
self.log.info(msg)
|
|
|
|
def stop(self, tid):
|
|
self.log.info("Stopping binary with tid {tid}".format(tid=tid))
|
|
if tid not in self.processes:
|
|
raise Exception(
|
|
"Binary with tid {tid} does not exist".format(tid=tid))
|
|
proc = self.processes[tid]
|
|
proc.send_signal(jail.SIGTERM)
|
|
proc.wait()
|
|
self.log.info("Binary with tid {tid} stopped".format(tid=tid))
|
|
|
|
def allocate_file(self, extension=""):
|
|
if extension != "" and not extension.startswith("."):
|
|
extension = "." + extension
|
|
tmp_name = str(uuid.uuid4())
|
|
while tmp_name in self._generated_filenames:
|
|
tmp_name = str(uuid.uuid4())
|
|
self._generated_filenames.append(tmp_name)
|
|
absolute_path = os.path.join(self.tempdir.name, tmp_name + extension)
|
|
return absolute_path
|
|
|
|
def read_file(self, absolute_path):
|
|
with open(absolute_path, "rb") as handle:
|
|
return xmlrpc.client.Binary(handle.read())
|
|
|
|
def get_jail(self):
|
|
proc = jail.get_process()
|
|
self.processes[proc._tid] = proc
|
|
return proc._tid
|
|
|
|
|
|
def main():
|
|
# set port dynamically
|
|
port = os.environ["CURRENT_MACHINE"][len("MACHINE"):]
|
|
port = 8000 + (int(port) * 100)
|
|
interface = os.environ[os.environ["CURRENT_MACHINE"]]
|
|
|
|
# init server
|
|
server = XMLRPCServer((interface, port), allow_none=True, logRequests=False)
|
|
server.register_introspection_functions()
|
|
server.register_instance(JailService())
|
|
|
|
# signal handler
|
|
def signal_sigterm(signum, frame):
|
|
server.server_close()
|
|
sys.exit()
|
|
|
|
try:
|
|
signal.signal(signal.SIGTERM, signal_sigterm)
|
|
server.serve_forever()
|
|
except KeyboardInterrupt:
|
|
server.server_close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|