From a25088a606dd50a293d1f6b542af9b8c75e8cd5e Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Mon, 13 Apr 2020 19:10:19 +0530 Subject: [PATCH] chore: show message on migrate when services are not running shows message before migrate if the database or redis service is not running instead of trying to migrate and then failing. Signed-off-by: Chinmay D. Pai --- frappe/migrate.py | 16 +++++++++++++ frappe/utils/connections.py | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 frappe/utils/connections.py diff --git a/frappe/migrate.py b/frappe/migrate.py index 043b6817d7..711f51c57a 100644 --- a/frappe/migrate.py +++ b/frappe/migrate.py @@ -5,11 +5,13 @@ from __future__ import unicode_literals import json import os +import sys import frappe import frappe.translate import frappe.modules.patch_handler import frappe.model.sync from frappe.utils.fixtures import sync_fixtures +from frappe.utils.connections import check_connection from frappe.cache_manager import clear_global_cache from frappe.desk.notifications import clear_notifications from frappe.website import render @@ -18,6 +20,7 @@ from frappe.modules.utils import sync_customizations from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs from frappe.utils import global_search + def migrate(verbose=True, rebuild_website=False, skip_failing=False): '''Migrate all apps to the latest version, will: - run before migrate hooks @@ -30,6 +33,19 @@ def migrate(verbose=True, rebuild_website=False, skip_failing=False): - run after migrate hooks ''' + service_status = check_connection(redis_services=["redis_cache"]) + if False in service_status.values(): + for service in service_status: + if not service_status.get(service, True): + print("{} service is not running.".format(service)) + print("""Cannot run bench migrate without the services running. +If you are running bench in development mode, make sure that bench is running: + +$ bench start + +Otherwise, check the server logs and ensure that all the required services are running.""") + sys.exit(1) + touched_tables_file = frappe.get_site_path('touched_tables.json') if os.path.exists(touched_tables_file): os.remove(touched_tables_file) diff --git a/frappe/utils/connections.py b/frappe/utils/connections.py new file mode 100644 index 0000000000..57b9399986 --- /dev/null +++ b/frappe/utils/connections.py @@ -0,0 +1,48 @@ +import socket + +from six.moves.urllib.parse import urlparse +from frappe import get_conf + +config = get_conf() +REDIS_KEYS = ('redis_cache', 'redis_queue', 'redis_socketio') + + +def is_open(ip, port, timeout=10): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + try: + s.connect((ip, int(port))) + s.shutdown(socket.SHUT_RDWR) + return True + except socket.error: + return False + finally: + s.close() + + +def check_database(): + db_type = config.get("db_type", "mariadb") + if db_type == "mariadb": + db_host = config.get("db_host", "localhost") + db_port = config.get("db_port", 3306) + else: + db_host = "localhost" + db_port = 5342 + return {"db_type": is_open(db_host, db_port)} + + +def check_redis(redis_services=None): + services = redis_services or REDIS_KEYS + status = {} + for conn in services: + redis_url = urlparse(config.get(conn)).netloc + redis_host, redis_port = redis_url.split(":") + status[conn] = is_open(redis_host, redis_port) + return status + + +def check_connection(redis_services=None): + service_status = {} + service_status.update(check_database()) + service_status.update(check_redis(redis_services)) + return service_status