memgraph/tests/distributed/jail_service.py
Marko Culinovic 7a06040a76 Setup RAFT test infrastructure
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
2018-01-05 09:59:42 +01:00

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()