Skip to content

Commit

Permalink
Merge pull request #27 from gregoil/feature/server_daemon
Browse files Browse the repository at this point in the history
Feature/server daemon
  • Loading branch information
osherdp committed Nov 9, 2017
2 parents a722ebc + 5721076 commit 59bf19a
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 25 deletions.
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,5 @@ Following, those are the options exposed when running the test:
-F, --failfast Stop the run on first failure
-D, --debug Enter ipdb debug mode upon any test exception
-S, --skip-init Skip initialization and validation of resources
-r RESOURCES, --resources=RESOURCES
Specific resources to request by name
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ constantly==15.1.0
coverage==4.4.1
decorator==4.1.2
Django==1.7.11
docopt==0.6.2
docutils==0.14
enum34==1.1.6
flake8==3.4.1
funcsigs==1.0.2
Expand All @@ -25,6 +27,7 @@ ipython-genutils==0.2.0
isort==4.2.15
jsonschema==2.6.0
lazy-object-proxy==1.3.1
lockfile==0.12.2
lxml==3.8.0
mccabe==0.6.1
mock==2.0.0
Expand All @@ -43,6 +46,7 @@ pylint==1.7.2
pytest==3.2.2
pytest-cov==2.5.1
pytest-django==3.1.2
python-daemon==2.1.2
PyYAML==3.12
scandir==1.5
simplegeneric==0.8.1
Expand Down
8 changes: 7 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@
install_requires=['django>=1.7,<1.8',
'ipdb',
'ipdbugger>=1.1.2',
'docopt',
'lxml<4.0.0',
'xlwt',
'attrdict',
'pyyaml',
'twisted',
'psutil',
'python-daemon',
'colorama',
'termcolor',
'xmltodict',
'jsonschema',
'basicstruct'],
entry_points={"rotest.result_handlers": result_handlers},
entry_points={
"console_scripts": [
"rotest-server = rotest.management.server.main:main"
],
"rotest.result_handlers": result_handlers},
packages=find_packages("src"),
package_dir={"": "src"},
package_data={'': ['*.xls', '*.xsd', '*.json', '*.css', '*.xml', '*.rst']},
Expand Down
5 changes: 5 additions & 0 deletions src/rotest/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ def get_configuration(configuration_schema,
"RESOURCE_MANAGER_HOST"],
config_file_options=["host"],
default_value="localhost"),
"port": Option(
environment_variables=["ROTEST_SERVER_PORT"],
config_file_options=["port"],
default_value="7777"),
"resource_request_timeout": Option(
command_line_options=["--resource-request-timeout"],
environment_variables=["ROTEST_RESOURCE_REQUEST_TIMEOUT",
Expand Down Expand Up @@ -244,6 +248,7 @@ def get_configuration(configuration_schema,

ROTEST_WORK_DIR = os.path.expanduser(CONFIGURATION.workdir)
RESOURCE_MANAGER_HOST = CONFIGURATION.host
RESOURCE_MANAGER_PORT = int(CONFIGURATION.port)
RESOURCE_REQUEST_TIMEOUT = int(CONFIGURATION.resource_request_timeout)
DJANGO_SETTINGS_MODULE = CONFIGURATION.django_settings
ARTIFACTS_DIR = os.path.expanduser(CONFIGURATION.artifacts_dir)
Expand Down
2 changes: 1 addition & 1 deletion src/rotest/core/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def update_requests(test_element, identifiers_dict):
"""
requests_found = set()

if issubclass(test_element, (TestSuite, TestFlow)):
if issubclass(test_element, TestSuite):
for component in test_element.components:
requests_found.update(
update_requests(component, identifiers_dict))
Expand Down
8 changes: 4 additions & 4 deletions src/rotest/management/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from rotest.common import core_log
from rotest.management.common import messages
from rotest.management.common.errors import ErrorFactory
from rotest.common.config import RESOURCE_REQUEST_TIMEOUT
from rotest.management.common.parsers import DEFAULT_PARSER
from rotest.management.common.parsers.abstract_parser import ParsingError
from rotest.common.config import (RESOURCE_REQUEST_TIMEOUT,
RESOURCE_MANAGER_PORT)
from rotest.management.common.utils import (MESSAGE_DELIMITER,
MESSAGE_MAX_LENGTH,
DEFAULT_SERVER_PORT)
MESSAGE_MAX_LENGTH)


class AbstractClient(object):
Expand All @@ -30,7 +30,7 @@ class AbstractClient(object):
REPLY_OVERHEAD_TIME = 2
_DEFAULT_REPLY_TIMEOUT = 18

def __init__(self, host, port=DEFAULT_SERVER_PORT,
def __init__(self, host, port=RESOURCE_MANAGER_PORT,
parser=DEFAULT_PARSER(),
lock_timeout=RESOURCE_REQUEST_TIMEOUT,
logger=core_log):
Expand Down
1 change: 0 additions & 1 deletion src/rotest/management/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from errors import ResourceTypeError

HOST_PORT_SEPARATOR = ':'
DEFAULT_SERVER_PORT = 7777

MESSAGE_DELIMITER = '\r\n'
MESSAGE_MAX_LENGTH = 240000
Expand Down
93 changes: 75 additions & 18 deletions src/rotest/management/server/main.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
"""Resource manager server runner.
Note:
By default, resource manager server supports only the basic resources
defined under Rotest. In order to extend the resources, set the
"DJANGO_SETTINGS_MODULE" environment variable to point to the extended
package's settings module.
"""Run resource manager server.
Usage:
rotest-server [--server-port <port>] [--run-django-server]
[--django-port <port>] [-D | --daemon]
Options:
-h --help
show this help message and exit
--server-port <port>
port for communicating with the client
--run-django-server
run the Django frontend as well
--django-port <port>
set Django's port [default: 8000]
-D --daemon
run as a daemon
"""
# pylint: disable=redefined-outer-name
import sys
import logging
import argparse
import subprocess

import docopt
import django
from twisted.internet.protocol import ServerFactory
from twisted.internet.selectreactor import SelectReactor

from worker import Worker
from manager import ManagerThread
from rotest.common.config import RESOURCE_MANAGER_PORT
from rotest.management.common.parsers import DEFAULT_PARSER
from rotest.management.common.utils import DEFAULT_SERVER_PORT
from rotest.common.log import (ROTEST_WORK_DIR, LOG_FORMAT, ColoredFormatter,
get_test_logger)

if sys.platform != "win32":
import daemon


LOG_NAME = 'resource_manager'

Expand All @@ -48,7 +62,7 @@ def get_logger(log_to_screen):
class ResourceManagerServer(object):
"""Resource manager server."""

def __init__(self, port=DEFAULT_SERVER_PORT,
def __init__(self, port=RESOURCE_MANAGER_PORT,
parser=DEFAULT_PARSER, log_to_screen=True):
"""Initialize the resource manager server.
Expand Down Expand Up @@ -88,20 +102,63 @@ def stop(self):
self._reactor.callFromThread(self._reactor.stop)


def start_server(server_port, run_django_server, django_port):
"""Run the resource management server, and optionally the Django frontend.
Args:
server_port (number): port for the resource management server.
run_django_server (bool): whether to run the Django frontend as well,
or not.
django_port (number): port for the Django frontend.
"""
django_process = None
try:
if run_django_server:
print "Running the Django server as well"
django_process = subprocess.Popen(
["django-admin",
"runserver",
"0.0.0.0:{}".format(django_port)])

ResourceManagerServer(port=server_port).start()

finally:
if django_process is not None:
django_process.kill()


def main():
"""Resource manager main method.
Loads the Django models if needed and starts a manager server.
"""
django.setup()

parser = argparse.ArgumentParser()
parser.add_argument("-p", dest="port", help="Server's listener port",
type=int, action='store', default=DEFAULT_SERVER_PORT)

args = parser.parse_args()

ResourceManagerServer(port=args.port).start()
args = docopt.docopt(__doc__)
server_port = args["--server-port"]
if server_port is None:
server_port = RESOURCE_MANAGER_PORT
else:
server_port = int(server_port)

run_django_server = args["--run-django-server"]
django_port = int(args["--django-port"])
run_as_daemon = args["--daemon"]

if run_as_daemon:
if sys.platform == "win32":
raise ValueError("Cannot run as daemon on Windows")

print "Running in detached mode (as daemon)"
with daemon.DaemonContext(stdout=None):
start_server(server_port=server_port,
run_django_server=run_django_server,
django_port=django_port)

else:
print "Running in attached mode"
start_server(server_port=server_port,
run_django_server=run_django_server,
django_port=django_port)


if __name__ == '__main__':
Expand Down

0 comments on commit 59bf19a

Please sign in to comment.