horizon/openstack_dashboard/settings.py

372 lines
12 KiB
Python
Raw Normal View History

# Copyright 2012 United States Government as represented by the
2011-07-04 04:10:53 +00:00
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 Nebula, Inc.
2011-07-04 04:10:53 +00:00
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import glob
2011-01-12 21:43:31 +00:00
import logging
import os
import sys
import warnings
2011-01-12 21:43:31 +00:00
from django.utils.translation import ugettext_lazy as _
from horizon.utils.escape import monkeypatch_escape
from openstack_dashboard import enabled
from openstack_dashboard import exceptions
from openstack_dashboard.local import enabled as local_enabled
Dynamic Themes Horizon themes are now configurable at a user level, through the use of cookies. The themes that can be set are configurable at a deployment level through settings.py. Horizon can be configured to run with multiple themes, and allow users to choose which themes they wish to run. Django Compressor: In order to support dynamic themes, each theme configuration must be pre-compiled through the Django compressor. By making use of its built in COMPRESS_OFFLINE_CONTEXT, we now return a generator to create each of the theme's necessary offline contexts. Templates: Horizon themes allowed template overrides via their 'templates' subfolder. In order to maintain this parity, a custom theme template loader was created. It is run before the other loads, and simply looks for a Django template in the current theme (cookie driven) before diverting to the previous template loaders. Static Files: Horizon themes allowed static overrides of the images in 'dashboard/img' folder. A template tag, 'themable_asset' was created to maintain this parity. Any asset that is wished to be made themable, given that it is located in Horizon's 'static/dashboard' folder, can now be made ot be themable. By making this a template tag, this gives the developers more granular control over what branders can customize. Angular and Plugins: By far, the trickiest part of this task, Angular and Plugins are dynamic in the files that they 'discover'. SCSS is not flexible in this manner at ALL. SCSS disallows the importation of a variable name. To get around this, themes.scss was created as a Django template. This template is the top level import file for all styles within Horizon, and therefore, allows ALL the scss files to share a common namespace and thus, can use shared variables as well as extend shared styles. Other: This change is fundamental, in that it changes the method by which Horizon ingests its SCSS files. Many problems existing in the previous implementation, in an effort to make Horizon flexible, its SCSS was made very inflexible. This patch corrects those problems. Change-Id: Ic48b4b5c1d1a41f1e01a8d52784c9d38d192c8f1 Implements: blueprint horizon-dynamic-theme Closes-Bug: #1480427
2016-01-30 16:42:15 +00:00
from openstack_dashboard import theme_settings
from openstack_dashboard.utils import config
from openstack_dashboard.utils import settings as settings_utils
monkeypatch_escape()
# Load default values
# pylint: disable=wrong-import-position
from openstack_dashboard.defaults import * # noqa: E402,F403,H303
_LOG = logging.getLogger(__name__)
warnings.filterwarnings("default", category=DeprecationWarning)
2011-01-12 21:43:31 +00:00
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
if ROOT_PATH not in sys.path:
sys.path.append(ROOT_PATH)
2011-01-12 21:43:31 +00:00
DEBUG = False
ROOT_URLCONF = 'openstack_dashboard.urls'
HORIZON_CONFIG = {
'user_home': 'openstack_dashboard.views.get_user_home',
'ajax_queue_limit': 10,
'auto_fade_alerts': {
'delay': 3000,
'fade_duration': 1500,
'types': ['alert-success', 'alert-info']
},
'bug_url': None,
'help_url': "https://docs.openstack.org/",
'exceptions': {'recoverable': exceptions.RECOVERABLE,
'not_found': exceptions.NOT_FOUND,
'unauthorized': exceptions.UNAUTHORIZED},
'modal_backdrop': 'static',
'angular_modules': [],
'js_files': [],
'js_spec_files': [],
'external_templates': [],
'plugins': [],
'integration_tests_support': INTEGRATION_TESTS_SUPPORT
}
2011-01-12 21:43:31 +00:00
MIDDLEWARE = (
Fix django.contrib.auth.middleware monkey patching The "request" attribute is not available in openstack_auth.backend.KeystoneBackend.get_user when session data is restored and it's the first request to happen after a server restart. As stated by the function document, the "request" attribute needs to be monkey-patched by openstack_auth.utils.patch_middleware_get_user for this function to work properly. This should happen in openstack_auth.urls at import time. But there is nowhere in Horizon where this module is imported at startup. It's only introspected by openstack_dashboard.urls due to AUTHENTICATION_URLS setting. Without this monkey-patching, the whole authentication mechanism falls back to "AnonymousUser" and you will get redirected to the login page due to horizon.exceptions.NotAuthenticated being raised by horizon.decorators.require_auth as request.user.is_authenticated will be False. But if a user requests a page under auth/, it will have the side-effect of monkey-patching django.contrib.auth.middleware as expected. This means that once this request is completed, all following requests to pages other than the ones under auth/ will have there sessions properly restored and you will be properly authenticated. Therefore this change introduces a dummy middleware which sole purpose is to perform this monkey-patching as early as possible. There is also some cleanup to get rid of the previous attempts at monkeypatching. Closes-bug: #1764622 Change-Id: Ib9912090a87b716e7f5710f6f360b0df168ec2e3
2018-11-01 02:24:31 +00:00
'openstack_auth.middleware.OpenstackAuthMonkeyPatchMiddleware',
'debreach.middleware.RandomCommentMiddleware',
2011-01-12 21:43:31 +00:00
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'horizon.middleware.OperationLogMiddleware',
2011-01-12 21:43:31 +00:00
'django.contrib.messages.middleware.MessageMiddleware',
'horizon.middleware.HorizonMiddleware',
Dynamic Themes Horizon themes are now configurable at a user level, through the use of cookies. The themes that can be set are configurable at a deployment level through settings.py. Horizon can be configured to run with multiple themes, and allow users to choose which themes they wish to run. Django Compressor: In order to support dynamic themes, each theme configuration must be pre-compiled through the Django compressor. By making use of its built in COMPRESS_OFFLINE_CONTEXT, we now return a generator to create each of the theme's necessary offline contexts. Templates: Horizon themes allowed template overrides via their 'templates' subfolder. In order to maintain this parity, a custom theme template loader was created. It is run before the other loads, and simply looks for a Django template in the current theme (cookie driven) before diverting to the previous template loaders. Static Files: Horizon themes allowed static overrides of the images in 'dashboard/img' folder. A template tag, 'themable_asset' was created to maintain this parity. Any asset that is wished to be made themable, given that it is located in Horizon's 'static/dashboard' folder, can now be made ot be themable. By making this a template tag, this gives the developers more granular control over what branders can customize. Angular and Plugins: By far, the trickiest part of this task, Angular and Plugins are dynamic in the files that they 'discover'. SCSS is not flexible in this manner at ALL. SCSS disallows the importation of a variable name. To get around this, themes.scss was created as a Django template. This template is the top level import file for all styles within Horizon, and therefore, allows ALL the scss files to share a common namespace and thus, can use shared variables as well as extend shared styles. Other: This change is fundamental, in that it changes the method by which Horizon ingests its SCSS files. Many problems existing in the previous implementation, in an effort to make Horizon flexible, its SCSS was made very inflexible. This patch corrects those problems. Change-Id: Ic48b4b5c1d1a41f1e01a8d52784c9d38d192c8f1 Implements: blueprint horizon-dynamic-theme Closes-Bug: #1480427
2016-01-30 16:42:15 +00:00
'horizon.themes.ThemeMiddleware',
2011-06-03 05:23:25 +00:00
'django.middleware.locale.LocaleMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'openstack_dashboard.contrib.developer.profiler.middleware.'
'ProfilerClientMiddleware',
'openstack_dashboard.contrib.developer.profiler.middleware.'
'ProfilerMiddleware',
2011-01-12 21:43:31 +00:00
)
CACHED_TEMPLATE_LOADERS = [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'horizon.loaders.TemplateLoader'
]
ADD_TEMPLATE_LOADERS = []
ADD_TEMPLATE_DIRS = []
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(ROOT_PATH, 'templates')],
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.request',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.contrib.messages.context_processors.messages',
'horizon.context_processors.horizon',
'openstack_dashboard.context_processors.openstack',
],
'loaders': [
'horizon.themes.ThemeTemplateLoader'
],
},
},
]
2011-01-12 21:43:31 +00:00
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'horizon.contrib.staticfiles.finders.HorizonStaticFinder',
'compressor.finders.CompressorFinder',
)
COMPRESS_PRECOMPILERS = (
('text/scss', 'horizon.utils.scss_filter.HorizonScssFilter'),
)
COMPRESS_CSS_FILTERS = (
'compressor.filters.css_default.CssAbsoluteFilter',
)
COMPRESS_ENABLED = True
COMPRESS_OUTPUT_DIR = 'dashboard'
COMPRESS_CSS_HASHING_METHOD = 'hash'
COMPRESS_PARSER = 'compressor.parser.HtmlParser'
INSTALLED_APPS = [
'openstack_dashboard',
'django.contrib.contenttypes',
'django.contrib.auth',
2011-01-12 21:43:31 +00:00
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'django_pyscss',
'debreach',
'openstack_dashboard.django_pyscss_fix',
'compressor',
'horizon',
'openstack_auth',
]
2011-01-12 21:43:31 +00:00
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
AUTH_USER_MODEL = 'openstack_auth.User'
MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
2011-01-12 21:43:31 +00:00
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
},
}
SESSION_COOKIE_HTTPONLY = True
2011-01-12 21:43:31 +00:00
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_SECURE = False
# when doing upgrades, it may be wise to stick to PickleSerializer
# NOTE(berendt): Check during the K-cycle if this variable can be removed.
# https://bugs.launchpad.net/horizon/+bug/1349463
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
CSRF_FAILURE_VIEW = 'openstack_dashboard.views.csrf_failure'
LANGUAGES = (
('cs', 'Czech'),
('de', 'German'),
('en', 'English'),
('en-au', 'Australian English'),
('en-gb', 'British English'),
('eo', 'Esperanto'),
('es', 'Spanish'),
('fr', 'French'),
('id', 'Indonesian'),
('it', 'Italian'),
('ja', 'Japanese'),
('ko', 'Korean (Korea)'),
('pl', 'Polish'),
('pt-br', 'Portuguese (Brazil)'),
('ru', 'Russian'),
('tr', 'Turkish'),
('zh-cn', 'Simplified Chinese'),
('zh-tw', 'Chinese (Taiwan)'),
)
2011-06-03 05:23:25 +00:00
LANGUAGE_CODE = 'en'
LANGUAGE_COOKIE_NAME = 'horizon_language'
USE_I18N = True
USE_L10N = True
USE_TZ = True
2011-01-12 21:43:31 +00:00
DEFAULT_EXCEPTION_REPORTER_FILTER = 'horizon.exceptions.HorizonReporterFilter'
SECRET_KEY = None
LOCAL_PATH = None
ADD_INSTALLED_APPS = []
CSRF_COOKIE_AGE = None
COMPRESS_OFFLINE_CONTEXT = 'horizon.themes.offline_context'
# Notice all customizable configurations should be above this line
XSTATIC_MODULES = settings_utils.BASE_XSTATIC_MODULES
if not LOCAL_PATH:
LOCAL_PATH = os.path.join(ROOT_PATH, 'local')
LOCAL_SETTINGS_DIR_PATH = os.path.join(LOCAL_PATH, "local_settings.d")
_files = glob.glob(os.path.join(LOCAL_PATH, 'local_settings.conf'))
_files.extend(
sorted(glob.glob(os.path.join(LOCAL_SETTINGS_DIR_PATH, '*.conf'))))
_config = config.load_config(_files, ROOT_PATH, LOCAL_PATH)
# Apply the general configuration.
config.apply_config(_config, globals())
2011-01-12 21:43:31 +00:00
try:
from local.local_settings import * # noqa: F403,H303
except ImportError:
_LOG.warning("No local_settings file found.")
2011-01-12 21:43:31 +00:00
# configure templates
if not TEMPLATES[0]['DIRS']:
TEMPLATES[0]['DIRS'] = [os.path.join(ROOT_PATH, 'templates')]
TEMPLATES[0]['DIRS'] += ADD_TEMPLATE_DIRS
# configure template debugging
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
Pre-populate the Angular template cache and allow template overrides This patch populates the Angular template cache from Django. This eliminates the need for Angular to do an http get for every HTML fragment. In addition, now that we are filling the template cache, this patch introduces the logic needed to override any Angular template HTML from the current theme. How it works: A new template tag is created called "template_cache_preloads". This tag is used in _scripts.html to generate a list of text/javascript script tags, each one containing an Angular "run" method that loads a template contents into the Angular template cache. The first time any Horizon page is loaded after server start, the template cache preloads are computed for the current theme. The output of this tag is cached for 30 days in Django using the "cache" tag. Further, that cached result is wrapped in a "compress js" tag to collapse the individual <script> tags into 1 block of javascript, and compress like all other javascript Horizon serves to the client. Finally, when using offline compression, the compressor evaluates the nodelist (HTML content) of _scripts.html, notices the compress tag and builds the template cache preloads for each possible theme. Later, at runtime, when the preloads are generated for the current theme, the compressor gets the result from the Django cache, and hashes the contents to determine which manifest file to serve to the client. Since the preloads generated at run-time are identical to those generated off-line, the compressor hash matches an existing manifest which is served to the client. Notice that even though the template cache pre-loads are generated off-line...the template_cache_preloads tag will be executed once every 30 days anyway. However, since the result matches the off-line compression, the existing manifest continues to be served to the client. Finally, this patch ALSO watches for 'post_compress' signals. If it detects that the angular template preloads have been re-compressed, it clears the old version from the Django cache. To test the template caching: - Run horizon - View page source - Notice the new <script type="text/javascript"> tags contained in the body (only visible if COMPRESS_ENABLED=False - Open the javascript inspector - Load launch instance - Notice there are no longer http calls to load each HTML fragment used by the Angular launch instance To test the override: - Set the DEFAULT_THEME='material' - Create /horizon/openstack_dashboard/themes/material/\ static/templates/framework/widgets/help-panel/help-panel.html - Set the content to <h1>TEST</h1> - Run Horizon and open launch instance. - The help content should contain "TEST" To test the new template tag: - set a breakpoint or print in angular.py:template_cache_preloads and observe when it is called during off-line or run-time use Co-Authored-By: Diana Whitten <hurgleburgler@gmail.com> Implements: blueprint angular-template-overrides Change-Id: I0e4e2623be58abbc68c6e02b2e9c5d7cdaba8e4d
2016-05-31 18:52:14 +00:00
# Template loaders
if DEBUG:
TEMPLATES[0]['OPTIONS']['loaders'].extend(
CACHED_TEMPLATE_LOADERS + ADD_TEMPLATE_LOADERS
)
else:
TEMPLATES[0]['OPTIONS']['loaders'].extend(
[('django.template.loaders.cached.Loader', CACHED_TEMPLATE_LOADERS)] +
ADD_TEMPLATE_LOADERS
)
# allow to drop settings snippets into a local_settings_dir
LOCAL_SETTINGS_DIR_PATH = os.path.join(ROOT_PATH, "local", "local_settings.d")
if os.path.exists(LOCAL_SETTINGS_DIR_PATH):
for (dirpath, dirnames, filenames) in os.walk(LOCAL_SETTINGS_DIR_PATH):
for filename in sorted(filenames):
if filename.endswith(".py"):
try:
with open(os.path.join(dirpath, filename)) as f:
pylint: fix several warnings openstack_dashboard/theme_settings.py:63:8: W1201: Specify string format arguments as logging function parameters (logging-not-lazy) openstack_dashboard/settings.py:412:24: W0122: Use of exec (exec-used) openstack_dashboard/dashboards/identity/domains/workflows.py:476:44: W0640: Cell variable group_id defined in loop (cell-var-from-loop) openstack_dashboard/dashboards/identity/projects/workflows.py:906:49: W0640: Cell variable group_id defined in loop (cell-var-from-loop) openstack_dashboard/dashboards/admin/networks/views.py:42:0: W0404: Reimport 'views' (imported line 28) (reimported) openstack_dashboard/api/swift.py:204:0: W0102: Dangerous default value {} as argument (dangerous-default-value) openstack_dashboard/api/swift.py:214:0: W0102: Dangerous default value {} as argument (dangerous-default-value) openstack_dashboard/api/cinder.py:248:30: W0631: Using possibly undefined loop variable 'cinder_url' (undefined-loop-variable) openstack_auth/backend.py:123:28: W0631: Using possibly undefined loop variable 'plugin' (undefined-loop-variable) openstack_auth/backend.py:129:39: W0631: Using possibly undefined loop variable 'plugin' (undefined-loop-variable) openstack_auth/backend.py:131:39: W0631: Using possibly undefined loop variable 'plugin' (undefined-loop-variable) openstack_auth/views.py:39:0: W0611: Unused Login imported from openstack_auth.forms (unused-import) horizon/exceptions.py:348:8: W0125: Using a conditional statement with a constant value (using-constant-test) horizon/tables/base.py:353:12: W0715: Exception arguments suggest string formatting might be intended (raising-format-tuple) Change-Id: Icf4f22abda77c9dbf98c780de876b7836c31d669
2018-12-01 20:48:03 +00:00
# pylint: disable=exec-used
exec(f.read())
except Exception:
_LOG.exception(
"Can not exec settings snippet %s", filename)
if USER_MENU_LINKS is None:
USER_MENU_LINKS = []
if SHOW_OPENRC_FILE:
USER_MENU_LINKS.append({
'name': _('OpenStack RC File'),
'icon_classes': ['fa-download', ],
'url': 'horizon:project:api_access:openrc',
})
if not WEBROOT.endswith('/'):
WEBROOT += '/'
if LOGIN_URL is None:
LOGIN_URL = WEBROOT + 'auth/login/'
if LOGOUT_URL is None:
LOGOUT_URL = WEBROOT + 'auth/logout/'
if LOGIN_ERROR is None:
LOGIN_ERROR = WEBROOT + 'auth/error/'
if LOGIN_REDIRECT_URL is None:
LOGIN_REDIRECT_URL = WEBROOT
if MEDIA_ROOT is None:
MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media'))
if MEDIA_URL is None:
MEDIA_URL = WEBROOT + 'media/'
if STATIC_ROOT is None:
STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static'))
if STATIC_URL is None:
STATIC_URL = WEBROOT + 'static/'
AVAILABLE_THEMES, SELECTABLE_THEMES, DEFAULT_THEME = (
theme_settings.get_available_themes(
AVAILABLE_THEMES,
DEFAULT_THEME,
SELECTABLE_THEMES
)
Dynamic Themes Horizon themes are now configurable at a user level, through the use of cookies. The themes that can be set are configurable at a deployment level through settings.py. Horizon can be configured to run with multiple themes, and allow users to choose which themes they wish to run. Django Compressor: In order to support dynamic themes, each theme configuration must be pre-compiled through the Django compressor. By making use of its built in COMPRESS_OFFLINE_CONTEXT, we now return a generator to create each of the theme's necessary offline contexts. Templates: Horizon themes allowed template overrides via their 'templates' subfolder. In order to maintain this parity, a custom theme template loader was created. It is run before the other loads, and simply looks for a Django template in the current theme (cookie driven) before diverting to the previous template loaders. Static Files: Horizon themes allowed static overrides of the images in 'dashboard/img' folder. A template tag, 'themable_asset' was created to maintain this parity. Any asset that is wished to be made themable, given that it is located in Horizon's 'static/dashboard' folder, can now be made ot be themable. By making this a template tag, this gives the developers more granular control over what branders can customize. Angular and Plugins: By far, the trickiest part of this task, Angular and Plugins are dynamic in the files that they 'discover'. SCSS is not flexible in this manner at ALL. SCSS disallows the importation of a variable name. To get around this, themes.scss was created as a Django template. This template is the top level import file for all styles within Horizon, and therefore, allows ALL the scss files to share a common namespace and thus, can use shared variables as well as extend shared styles. Other: This change is fundamental, in that it changes the method by which Horizon ingests its SCSS files. Many problems existing in the previous implementation, in an effort to make Horizon flexible, its SCSS was made very inflexible. This patch corrects those problems. Change-Id: Ic48b4b5c1d1a41f1e01a8d52784c9d38d192c8f1 Implements: blueprint horizon-dynamic-theme Closes-Bug: #1480427
2016-01-30 16:42:15 +00:00
)
# Discover all the directories that contain static files
STATICFILES_DIRS = theme_settings.get_theme_static_dirs(
AVAILABLE_THEMES, THEME_COLLECTION_DIR, ROOT_PATH)
# Ensure that we always have a SECRET_KEY set, even when no local_settings.py
# file is present. See local_settings.py.example for full documentation on the
# horizon.utils.secret_key module and its use.
if not SECRET_KEY:
if not LOCAL_PATH:
LOCAL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
'local')
pylint: fix several coding convention violations openstack_dashboard/context_processors.py:94:15: C0122: Comparison should be link['url'] != 'horizon:project:api_access:openrcv2' (misplaced-comparison-constant) openstack_dashboard/settings.py:467:4: C0412: Imports from package horizon are not grouped (ungrouped-imports) openstack_dashboard/enabled/_1370_project_vg_snapshots.py:9:0: C0301: Line too long (86/80) (line-too-long) openstack_dashboard/enabled/_1360_project_volume_groups.py:9:0: C0301: Line too long (85/80) (line-too-long) openstack_dashboard/usage/base.py:62:8: W0106: Expression "[instance_list.extend(u.server_usages) for u in self.usage_list]" is assigned to nothing (expression-not-assigned) openstack_dashboard/dashboards/project/images/utils.py:43:12: W0106: Expression "[public_images.append(image) for image in images]" is assigned to nothing (expression-not-assigned) openstack_dashboard/dashboards/project/images/utils.py:75:12: W0106: Expression "[community_images.append(image) for image in images]" is assigned to nothing (expression-not-assigned) openstack_dashboard/api/glance.py:47:4: C0412: Imports from package glanceclient are not grouped (ungrouped-imports) openstack_dashboard/api/cinder.py:60:4: C0412: Imports from package cinderclient are not grouped (ungrouped-imports) openstack_auth/user.py:358:4: E0211: Method has no argument (no-method-argument) openstack_auth/user.py:362:4: E0211: Method has no argument (no-method-argument) openstack_dashboard/api/keystone.py:75:4: C0412: Imports from package keystoneclient are not grouped (ungrouped-imports) horizon/loaders.py:43:16: W0706: The except handler raises immediately (try-except-raise) horizon/themes.py:174:8: W0706: The except handler raises immediately (try-except-raise) Change-Id: I40cf3ffbc4519657e11180d2e2fe7401387c5556
2018-12-01 21:21:02 +00:00
# pylint: disable=ungrouped-imports
from horizon.utils import secret_key
SECRET_KEY = secret_key.generate_or_read_from_file(os.path.join(LOCAL_PATH,
'.secret_key_store'))
# populate HORIZON_CONFIG with auto-discovered JavaScript sources, mock files,
# specs files and external templates.
settings_utils.find_static_files(HORIZON_CONFIG, AVAILABLE_THEMES,
THEME_COLLECTION_DIR, ROOT_PATH)
INSTALLED_APPS = list(INSTALLED_APPS) # Make sure it's mutable
settings_utils.update_dashboards(
[
enabled,
local_enabled,
],
HORIZON_CONFIG,
INSTALLED_APPS,
)
INSTALLED_APPS[0:0] = ADD_INSTALLED_APPS
# Include xstatic_modules specified in plugin
XSTATIC_MODULES += HORIZON_CONFIG['xstatic_modules']
# Discover all the xstatic module entry points to embed in our HTML
STATICFILES_DIRS += settings_utils.get_xstatic_dirs(
XSTATIC_MODULES, HORIZON_CONFIG)
Dynamic Themes Horizon themes are now configurable at a user level, through the use of cookies. The themes that can be set are configurable at a deployment level through settings.py. Horizon can be configured to run with multiple themes, and allow users to choose which themes they wish to run. Django Compressor: In order to support dynamic themes, each theme configuration must be pre-compiled through the Django compressor. By making use of its built in COMPRESS_OFFLINE_CONTEXT, we now return a generator to create each of the theme's necessary offline contexts. Templates: Horizon themes allowed template overrides via their 'templates' subfolder. In order to maintain this parity, a custom theme template loader was created. It is run before the other loads, and simply looks for a Django template in the current theme (cookie driven) before diverting to the previous template loaders. Static Files: Horizon themes allowed static overrides of the images in 'dashboard/img' folder. A template tag, 'themable_asset' was created to maintain this parity. Any asset that is wished to be made themable, given that it is located in Horizon's 'static/dashboard' folder, can now be made ot be themable. By making this a template tag, this gives the developers more granular control over what branders can customize. Angular and Plugins: By far, the trickiest part of this task, Angular and Plugins are dynamic in the files that they 'discover'. SCSS is not flexible in this manner at ALL. SCSS disallows the importation of a variable name. To get around this, themes.scss was created as a Django template. This template is the top level import file for all styles within Horizon, and therefore, allows ALL the scss files to share a common namespace and thus, can use shared variables as well as extend shared styles. Other: This change is fundamental, in that it changes the method by which Horizon ingests its SCSS files. Many problems existing in the previous implementation, in an effort to make Horizon flexible, its SCSS was made very inflexible. This patch corrects those problems. Change-Id: Ic48b4b5c1d1a41f1e01a8d52784c9d38d192c8f1 Implements: blueprint horizon-dynamic-theme Closes-Bug: #1480427
2016-01-30 16:42:15 +00:00
# This base context objects gets added to the offline context generator
# for each theme configured.
HORIZON_COMPRESS_OFFLINE_CONTEXT_BASE = {
'WEBROOT': WEBROOT,
'STATIC_URL': STATIC_URL,
Pre-populate the Angular template cache and allow template overrides This patch populates the Angular template cache from Django. This eliminates the need for Angular to do an http get for every HTML fragment. In addition, now that we are filling the template cache, this patch introduces the logic needed to override any Angular template HTML from the current theme. How it works: A new template tag is created called "template_cache_preloads". This tag is used in _scripts.html to generate a list of text/javascript script tags, each one containing an Angular "run" method that loads a template contents into the Angular template cache. The first time any Horizon page is loaded after server start, the template cache preloads are computed for the current theme. The output of this tag is cached for 30 days in Django using the "cache" tag. Further, that cached result is wrapped in a "compress js" tag to collapse the individual <script> tags into 1 block of javascript, and compress like all other javascript Horizon serves to the client. Finally, when using offline compression, the compressor evaluates the nodelist (HTML content) of _scripts.html, notices the compress tag and builds the template cache preloads for each possible theme. Later, at runtime, when the preloads are generated for the current theme, the compressor gets the result from the Django cache, and hashes the contents to determine which manifest file to serve to the client. Since the preloads generated at run-time are identical to those generated off-line, the compressor hash matches an existing manifest which is served to the client. Notice that even though the template cache pre-loads are generated off-line...the template_cache_preloads tag will be executed once every 30 days anyway. However, since the result matches the off-line compression, the existing manifest continues to be served to the client. Finally, this patch ALSO watches for 'post_compress' signals. If it detects that the angular template preloads have been re-compressed, it clears the old version from the Django cache. To test the template caching: - Run horizon - View page source - Notice the new <script type="text/javascript"> tags contained in the body (only visible if COMPRESS_ENABLED=False - Open the javascript inspector - Load launch instance - Notice there are no longer http calls to load each HTML fragment used by the Angular launch instance To test the override: - Set the DEFAULT_THEME='material' - Create /horizon/openstack_dashboard/themes/material/\ static/templates/framework/widgets/help-panel/help-panel.html - Set the content to <h1>TEST</h1> - Run Horizon and open launch instance. - The help content should contain "TEST" To test the new template tag: - set a breakpoint or print in angular.py:template_cache_preloads and observe when it is called during off-line or run-time use Co-Authored-By: Diana Whitten <hurgleburgler@gmail.com> Implements: blueprint angular-template-overrides Change-Id: I0e4e2623be58abbc68c6e02b2e9c5d7cdaba8e4d
2016-05-31 18:52:14 +00:00
'HORIZON_CONFIG': HORIZON_CONFIG,
'NG_TEMPLATE_CACHE_AGE': NG_TEMPLATE_CACHE_AGE if not DEBUG else 0,
}
if DEBUG:
logging.basicConfig(level=logging.DEBUG)
# Here comes the Django settings deprecation section. Being at the very end
# of settings.py allows it to catch the settings defined in local_settings.py
# or inside one of local_settings.d/ snippets.