From ef9050bcea6164fda9d407cde40179a3301899d4 Mon Sep 17 00:00:00 2001 From: Lingyi Wang Date: Mon, 5 Mar 2018 17:09:07 -0800 Subject: [PATCH 1/2] check if port is occupied before starting kolibri and show more info for kolibri stop --- kolibri/utils/cli.py | 28 ++++++++++++++++------- kolibri/utils/sanity_checks.py | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 kolibri/utils/sanity_checks.py diff --git a/kolibri/utils/cli.py b/kolibri/utils/cli.py index 3d5fffcde3b..a515a1b35aa 100644 --- a/kolibri/utils/cli.py +++ b/kolibri/utils/cli.py @@ -24,6 +24,7 @@ from . import server # noqa from .system import become_daemon # noqa +from .sanity_checks import check_other_kolibri_running # noqa USAGE = """ Kolibri @@ -262,12 +263,9 @@ def start(port=None, daemon=True): # https://github.com/learningequality/kolibri/issues/1615 update() - if port is None: - try: - port = int(os.environ['KOLIBRI_LISTEN_PORT']) - except ValueError: - logger.error("Invalid KOLIBRI_LISTEN_PORT, must be an integer") - raise + # In case that some tests run start() function only + if not isinstance(port, int): + port = _get_port(port) if not daemon: logger.info("Running 'kolibri start' in foreground...") @@ -314,6 +312,7 @@ def stop(): pid, __, __ = server.get_status() server.stop(pid=pid) stopped = True + logger.info("Kolibri server has been successfully stoppped.") except server.NotRunning as e: verbose_status = "{msg:s} ({code:d})".format( code=e.status_code, @@ -576,6 +575,17 @@ def parse_args(args=None): return docopt(USAGE, **docopt_kwargs), django_args +def _get_port(port): + port = int(port) if port else None + if port is None: + try: + port = int(os.environ['KOLIBRI_LISTEN_PORT']) + except ValueError: + logger.error("Invalid KOLIBRI_LISTEN_PORT, must be an integer") + raise + return port + + def main(args=None): """ Kolibri's main function. Parses arguments and calls utility functions. @@ -589,6 +599,10 @@ def main(args=None): debug = arguments['--debug'] + if arguments['start']: + port = _get_port(arguments['--port']) + check_other_kolibri_running(port) + initialize(debug=debug) # Alias @@ -607,8 +621,6 @@ def main(args=None): return if arguments['start']: - port = arguments['--port'] - port = int(port) if port else None daemon = not arguments['--foreground'] if sys.platform == 'darwin': daemon = False diff --git a/kolibri/utils/sanity_checks.py b/kolibri/utils/sanity_checks.py new file mode 100644 index 00000000000..429112e8aea --- /dev/null +++ b/kolibri/utils/sanity_checks.py @@ -0,0 +1,42 @@ +import logging +import socket +import sys + +from .server import get_status +from .server import NotRunning + +logger = logging.getLogger(__name__) + +def check_other_kolibri_running(port): + try: + # Check if there are other kolibri instances running + # If there are, then we need to stop users from starting kolibri again. + pid, listen_address, listen_port = get_status() + logger.error( + "There is another Kolibri server running. " + "Please use `kolibri stop` and try again.") + sys.exit(1) + + except NotRunning: + # In case that something other than Kolibri occupies the port, + # check the port's availability. + check_port_availability('127.0.0.1', port) + + +def check_port_availability(host, port): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # This is to prevent the previous execution has left the socket + # in a TIME_WAIT start, and can't be immediately reused. + # From the bottom of https://docs.python.org/2/library/socket.html#example + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + s.bind((host, port)) + s.close() + except socket.error: + # Port is occupied + logger.error( + "Port {} is occupied.\n" + "Please check that you do not have other processes " + "running on this port and try again.\n".format(port)) + s.close() + sys.exit(1) From 1a84fae66023718274e45dba597ceb5d0379e8e5 Mon Sep 17 00:00:00 2001 From: Lingyi Wang Date: Wed, 7 Mar 2018 09:27:50 -0800 Subject: [PATCH 2/2] fix indentation style and stop statement's grammar --- kolibri/utils/cli.py | 2 +- kolibri/utils/sanity_checks.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kolibri/utils/cli.py b/kolibri/utils/cli.py index a515a1b35aa..9d949ccee5f 100644 --- a/kolibri/utils/cli.py +++ b/kolibri/utils/cli.py @@ -312,7 +312,7 @@ def stop(): pid, __, __ = server.get_status() server.stop(pid=pid) stopped = True - logger.info("Kolibri server has been successfully stoppped.") + logger.info("Kolibri server has successfully been stoppped.") except server.NotRunning as e: verbose_status = "{msg:s} ({code:d})".format( code=e.status_code, diff --git a/kolibri/utils/sanity_checks.py b/kolibri/utils/sanity_checks.py index 429112e8aea..ad829b9d096 100644 --- a/kolibri/utils/sanity_checks.py +++ b/kolibri/utils/sanity_checks.py @@ -14,7 +14,8 @@ def check_other_kolibri_running(port): pid, listen_address, listen_port = get_status() logger.error( "There is another Kolibri server running. " - "Please use `kolibri stop` and try again.") + "Please use `kolibri stop` and try again." + ) sys.exit(1) except NotRunning: @@ -37,6 +38,7 @@ def check_port_availability(host, port): logger.error( "Port {} is occupied.\n" "Please check that you do not have other processes " - "running on this port and try again.\n".format(port)) + "running on this port and try again.\n".format(port) + ) s.close() sys.exit(1)