diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index b49dbfbe15..1b79eac59f 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -123,6 +123,11 @@ LOGGING = { 'handlers': ['console'], 'level': log_level, }, + 'filters': { + 'require_not_maintenance_mode_503': { + '()': 'maintenance_mode.logging.RequireNotMaintenanceMode503', + }, + }, } # Get a logger instance for this setup file @@ -252,6 +257,9 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'django.contrib.sites', + # Maintenance + 'maintenance_mode', + # InvenTree apps 'build.apps.BuildConfig', 'common.apps.CommonConfig', @@ -298,7 +306,8 @@ MIDDLEWARE = CONFIG.get('middleware', [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'InvenTree.middleware.AuthRequiredMiddleware' + 'InvenTree.middleware.AuthRequiredMiddleware', + 'maintenance_mode.middleware.MaintenanceModeMiddleware' ]) # Error reporting middleware @@ -848,6 +857,10 @@ MARKDOWNIFY_WHITELIST_ATTRS = [ MARKDOWNIFY_BLEACH = False +# Maintenance mode +MAINTENANCE_MODE_RETRY_AFTER = 60 + + # Plugins PLUGIN_URL = 'plugin' diff --git a/InvenTree/plugin/apps.py b/InvenTree/plugin/apps.py index 89ce89ae88..d944c50137 100644 --- a/InvenTree/plugin/apps.py +++ b/InvenTree/plugin/apps.py @@ -17,6 +17,9 @@ try: except: import importlib_metadata as metadata +from maintenance_mode.core import maintenance_mode_on +from maintenance_mode.core import get_maintenance_mode, set_maintenance_mode + from plugin import plugins as inventree_plugins from plugin.integration import IntegrationPluginBase @@ -35,6 +38,11 @@ class PluginAppConfig(AppConfig): def load_plugins(self): """load and activate all IntegrationPlugins""" logger.info('Start loading plugins') + # set maintanace mode + _maintenance = get_maintenance_mode() + if not _maintenance: + set_maintenance_mode(True) + try: # we are using the db so for migrations etc we need to try this block self._init_plugins() @@ -42,11 +50,20 @@ class PluginAppConfig(AppConfig): except (OperationalError, ProgrammingError): # Exception if the database has not been migrated yet logger.info('Database not accessible while loading plugins') + + # remove maintenance + if not _maintenance: + set_maintenance_mode(False) logger.info('Finished loading plugins') def unload_plugins(self): """unload and deactivate all IntegrationPlugins""" logger.info('Start unloading plugins') + # set maintanace mode + _maintenance = get_maintenance_mode() + if not _maintenance: + set_maintenance_mode(True) + # remove all plugins from registry # plugins = settings.INTEGRATION_PLUGINS settings.INTEGRATION_PLUGINS = {} @@ -55,14 +72,18 @@ class PluginAppConfig(AppConfig): # deactivate all integrations self._deactivate_plugins() + + # remove maintenance + if not _maintenance: + set_maintenance_mode(False) logger.info('Finished unloading plugins') def reload_plugins(self): """safely reload IntegrationPlugins""" - # TODO check if the system is in maintainance mode before reloading logger.info('Start reloading plugins') - self.unload_plugins() - self.load_plugins() + with maintenance_mode_on(): + self.unload_plugins() + self.load_plugins() logger.info('Finished reloading plugins') # endregion diff --git a/InvenTree/templates/503.html b/InvenTree/templates/503.html new file mode 100644 index 0000000000..f7381aeb69 --- /dev/null +++ b/InvenTree/templates/503.html @@ -0,0 +1,14 @@ +{% extends "account/base.html" %} +{% load i18n %} + +{% block head_title %} +{% trans "Page is in Maintenance" %} +{% endblock %} + +{% block content %} +

{% trans "The Page is in currently in maintenance mode" %}

+ +
+ {% trans "This page will reload each minute until the page becomes available again." %} +
+{% endblock %} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 155cd49e14..573705b78e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,6 +15,7 @@ django-error-report==0.2.0 # Error report viewer for the admin interface django-filter==2.4.0 # Extended filtering options django-formtools==2.3 # Form wizard tools django-import-export==2.5.0 # Data import / export for admin interface +django-maintenance-mode==0.16.1 # Shut down application while reloading etc. django-markdownify==0.8.0 # Markdown rendering django-markdownx==3.0.1 # Markdown form fields django-money==1.1 # Django app for currency management