Plugin-based panel configuration
This is an extension to the plugin-based dashboard configuration. It adds support processing panel configuration configuration file in the openstack_dashboard/enabled/ directory. Panels can be added, removed to/from the panel group of a dashboard. It also provide the ability to update the default panel of the dashboard. Change-Id: I2d7adfb8045c244ec063a6741e3b9fe21c188525 Implements: blueprint plugin-panel-config
This commit is contained in:

committed by
Lin Hua Cheng

parent
5be0a3e950
commit
f169ee58ab
@@ -434,7 +434,7 @@ settings.
|
|||||||
|
|
||||||
The default location for the dashboard configuration files is
|
The default location for the dashboard configuration files is
|
||||||
``openstack_dashboard/enabled``, with another directory,
|
``openstack_dashboard/enabled``, with another directory,
|
||||||
``openstack_dashboarrd/local/enabled`` for local overrides. Both sets of files
|
``openstack_dashboard/local/enabled`` for local overrides. Both sets of files
|
||||||
will be loaded, but the settings in ``openstack_dashboard/local/enabled`` will
|
will be loaded, but the settings in ``openstack_dashboard/local/enabled`` will
|
||||||
overwrite the default ones. The settings are applied in alphabetical order of
|
overwrite the default ones. The settings are applied in alphabetical order of
|
||||||
the filenames. If the same dashboard has configuration files in ``enabled`` and
|
the filenames. If the same dashboard has configuration files in ``enabled`` and
|
||||||
@@ -493,3 +493,91 @@ create a file ``openstack_dashboard/local/enabled/_50_tuskar.py`` with::
|
|||||||
'not_found': exceptions.NOT_FOUND,
|
'not_found': exceptions.NOT_FOUND,
|
||||||
'unauthorized': exceptions.UNAUTHORIZED,
|
'unauthorized': exceptions.UNAUTHORIZED,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pluggable Settings for Panels
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Panels customization can be made by providing a custom python module that
|
||||||
|
contains python code to add or remove panel to/from the dashboard. This
|
||||||
|
requires altering the settings file. For panels provided by third-party,
|
||||||
|
making this changes to add the panel is challenging. Panel configuration
|
||||||
|
files can now be dropped to a specified location and it will be read at startup
|
||||||
|
to alter the dashboard configuration.
|
||||||
|
|
||||||
|
The default location for the panel configuration files is
|
||||||
|
``openstack_dashboard/enabled``, with another directory,
|
||||||
|
``openstack_dashboard/local/enabled`` for local overrides. Both sets of files
|
||||||
|
will be loaded, but the settings in ``openstack_dashboard/local/enabled`` will
|
||||||
|
overwrite the default ones. The settings are applied in alphabetical order of
|
||||||
|
the filenames. If the same panel has configuration files in ``enabled`` and
|
||||||
|
``local/enabled``, the local name will be used. Note, that since names of
|
||||||
|
python modules can't start with a digit, the files are usually named with a
|
||||||
|
leading underscore and a number, so that you can control their order easily.
|
||||||
|
|
||||||
|
The files contain following keys:
|
||||||
|
|
||||||
|
``PANEL``
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The name of the panel to be added to ``HORIZON_CONFIG``. Required.
|
||||||
|
|
||||||
|
``PANEL_DASHBOARD``
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The name of the dashboard the ``PANEL`` associated with. Required.
|
||||||
|
|
||||||
|
|
||||||
|
``PANEL_GROUP``
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The name of the panel group the ``PANEL`` is associated with.
|
||||||
|
|
||||||
|
``DEFAULT_PANEL``
|
||||||
|
-----------
|
||||||
|
|
||||||
|
If set, it will update the default panel of the ``PANEL_DASHBOARD``.
|
||||||
|
|
||||||
|
``ADD_PANEL``
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Python panel class of the ``PANEL`` to be added.
|
||||||
|
|
||||||
|
``REMOVE_PANEL``
|
||||||
|
------------
|
||||||
|
|
||||||
|
If set to ``True``, the PANEL will be removed from PANEL_DASHBOARD/PANEL_GROUP.
|
||||||
|
|
||||||
|
``DISABLED``
|
||||||
|
------------
|
||||||
|
|
||||||
|
If set to ``True``, this panel configuration will be skipped.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
To add a new panel to the Admin panel group in Admin dashboard, create a file
|
||||||
|
``openstack_dashboard/local/enabled/_60_admin_add_panel.py`` with the follwing
|
||||||
|
content::
|
||||||
|
|
||||||
|
PANEL = 'plugin_panel'
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
ADD_PANEL = 'test_panels.plugin_panel.panel.PluginPanel'
|
||||||
|
|
||||||
|
To remove Info panel from Admin panel group in Admin dashboard locally, create
|
||||||
|
a file ``openstack_dashboard/local/enabled/_70_admin_remove_panel.py`` with
|
||||||
|
the following content::
|
||||||
|
|
||||||
|
PANEL = 'info'
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
REMOVE_PANEL = True
|
||||||
|
|
||||||
|
To change the default panel of Admin dashboard to Defaults panel, create a file
|
||||||
|
``openstack_dashboard/local/enabled/_80_admin_default_panel.py`` with the
|
||||||
|
following content::
|
||||||
|
|
||||||
|
PANEL = 'defaults'
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
DEFAULT_PANEL = 'defaults'
|
||||||
|
@@ -740,6 +740,9 @@ class Site(Registry, HorizonComponent):
|
|||||||
for dash in self._registry.values():
|
for dash in self._registry.values():
|
||||||
dash._autodiscover()
|
dash._autodiscover()
|
||||||
|
|
||||||
|
# Load the plugin-based panel configuration
|
||||||
|
self._load_panel_customization()
|
||||||
|
|
||||||
# Allow for override modules
|
# Allow for override modules
|
||||||
if self._conf.get("customization_module", None):
|
if self._conf.get("customization_module", None):
|
||||||
customization_module = self._conf["customization_module"]
|
customization_module = self._conf["customization_module"]
|
||||||
@@ -785,6 +788,61 @@ class Site(Registry, HorizonComponent):
|
|||||||
if module_has_submodule(mod, mod_name):
|
if module_has_submodule(mod, mod_name):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def _load_panel_customization(self):
|
||||||
|
"""Applies the plugin-based panel configurations.
|
||||||
|
|
||||||
|
This method parses the panel customization from the ``HORIZON_CONFIG``
|
||||||
|
and make changes to the dashboard accordingly.
|
||||||
|
|
||||||
|
It supports adding, removing and setting default panels on the
|
||||||
|
dashboard.
|
||||||
|
"""
|
||||||
|
panel_customization = self._conf.get("panel_customization", [])
|
||||||
|
|
||||||
|
for config in panel_customization:
|
||||||
|
dashboard = config.get('PANEL_DASHBOARD')
|
||||||
|
if not dashboard:
|
||||||
|
LOG.warning("Skipping %s because it doesn't have "
|
||||||
|
"PANEL_DASHBOARD defined.", config.__name__)
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
panel_slug = config.get('PANEL')
|
||||||
|
dashboard_cls = self.get_dashboard(dashboard)
|
||||||
|
panel_group = config.get('PANEL_GROUP')
|
||||||
|
default_panel = config.get('DEFAULT_PANEL')
|
||||||
|
|
||||||
|
# Set the default panel
|
||||||
|
if default_panel:
|
||||||
|
dashboard_cls.default_panel = default_panel
|
||||||
|
|
||||||
|
# Remove the panel
|
||||||
|
if config.get('REMOVE_PANEL', False):
|
||||||
|
for panel in dashboard_cls.get_panels():
|
||||||
|
if panel_slug == panel.slug:
|
||||||
|
dashboard_cls.unregister(panel.__class__)
|
||||||
|
elif config.get('ADD_PANEL', None):
|
||||||
|
# Add the panel to the dashboard
|
||||||
|
panel_path = config['ADD_PANEL']
|
||||||
|
mod_path, panel_cls = panel_path.rsplit(".", 1)
|
||||||
|
try:
|
||||||
|
mod = import_module(mod_path)
|
||||||
|
except ImportError:
|
||||||
|
LOG.warning("Could not load panel: %s", mod_path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
panel = getattr(mod, panel_cls)
|
||||||
|
dashboard_cls.register(panel)
|
||||||
|
if panel_group:
|
||||||
|
dashboard_cls.get_panel_group(panel_group).\
|
||||||
|
panels.append(panel.slug)
|
||||||
|
else:
|
||||||
|
panels = list(dashboard_cls.panels)
|
||||||
|
panels.append(panel)
|
||||||
|
dashboard_cls.panels = tuple(panels)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.warning('Could not process panel %(panel)s: %(exc)s',
|
||||||
|
{'panel': panel_slug, 'exc': e})
|
||||||
|
|
||||||
|
|
||||||
class HorizonSite(Site):
|
class HorizonSite(Site):
|
||||||
"""A singleton implementation of Site such that all dealings with horizon
|
"""A singleton implementation of Site such that all dealings with horizon
|
||||||
|
10
openstack_dashboard/enabled/_50_admin_add_panel.py.example
Normal file
10
openstack_dashboard/enabled/_50_admin_add_panel.py.example
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||||
|
PANEL = 'plugin_panel'
|
||||||
|
# The name of the dashboard the PANEL associated with. Required.
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
# The name of the panel group the PANEL is associated with.
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
|
||||||
|
# Python panel class of the PANEL to be added.
|
||||||
|
ADD_PANEL = \
|
||||||
|
'openstack_dashboard.test.test_panels.plugin_panel.panel.PluginPanel'
|
@@ -0,0 +1,9 @@
|
|||||||
|
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||||
|
PANEL = 'info'
|
||||||
|
# The name of the dashboard the PANEL associated with. Required.
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
# The name of the panel group the PANEL is associated with.
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
|
||||||
|
# If set to True, the panel will be removed from PANEL_DASHBOARD/PANEL_GROUP.
|
||||||
|
REMOVE_PANEL = True
|
@@ -0,0 +1,9 @@
|
|||||||
|
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||||
|
PANEL = 'defaults'
|
||||||
|
# The name of the dashboard the PANEL associated with. Required.
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
# The name of the panel group the PANEL is associated with.
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
|
||||||
|
# If set, it will update the default panel of the PANEL_DASHBOARD.
|
||||||
|
DEFAULT_PANEL = 'defaults'
|
0
openstack_dashboard/test/test_panels/__init__.py
Normal file
0
openstack_dashboard/test/test_panels/__init__.py
Normal file
22
openstack_dashboard/test/test_panels/plugin_panel/panel.py
Normal file
22
openstack_dashboard/test/test_panels/plugin_panel/panel.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
import horizon
|
||||||
|
|
||||||
|
|
||||||
|
class PluginPanel(horizon.Panel):
|
||||||
|
name = _("Plugin Panel")
|
||||||
|
slug = 'plugin_panel'
|
@@ -0,0 +1,15 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Plugin-based Panel" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block page_header %}
|
||||||
|
{% include "horizon/common/_page_header.html" with title=_("Plugin-based Panel")%}
|
||||||
|
{% endblock page_header %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span12">
|
||||||
|
Plugin-based Panel
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
22
openstack_dashboard/test/test_panels/plugin_panel/urls.py
Normal file
22
openstack_dashboard/test/test_panels/plugin_panel/urls.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from django.conf.urls import patterns # noqa
|
||||||
|
from django.conf.urls import url # noqa
|
||||||
|
|
||||||
|
from openstack_dashboard.test.test_panels.plugin_panel import views
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||||
|
)
|
19
openstack_dashboard/test/test_panels/plugin_panel/views.py
Normal file
19
openstack_dashboard/test/test_panels/plugin_panel/views.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from django.views.generic import TemplateView # noqa
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(TemplateView):
|
||||||
|
template_name = 'admin/plugin_panel/index.html'
|
0
openstack_dashboard/test/test_plugins/__init__.py
Normal file
0
openstack_dashboard/test/test_plugins/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||||
|
PANEL = 'plugin_panel'
|
||||||
|
# The name of the dashboard the PANEL associated with. Required.
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
# The name of the panel group the PANEL is associated with.
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
|
||||||
|
# Python panel class of the PANEL to be added.
|
||||||
|
ADD_PANEL = \
|
||||||
|
'openstack_dashboard.test.test_panels.plugin_panel.panel.PluginPanel'
|
@@ -0,0 +1,9 @@
|
|||||||
|
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||||
|
PANEL = 'info'
|
||||||
|
# The name of the dashboard the PANEL associated with. Required.
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
# The name of the panel group the PANEL is associated with.
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
|
||||||
|
# If set to True, the panel will be removed from PANEL_DASHBOARD/PANEL_GROUP.
|
||||||
|
REMOVE_PANEL = True
|
@@ -0,0 +1,9 @@
|
|||||||
|
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||||
|
PANEL = 'defaults'
|
||||||
|
# The name of the dashboard the PANEL associated with. Required.
|
||||||
|
PANEL_DASHBOARD = 'admin'
|
||||||
|
# The name of the panel group the PANEL is associated with.
|
||||||
|
PANEL_GROUP = 'admin'
|
||||||
|
|
||||||
|
# If set, it will update the default panel of the PANEL_DASHBOARD.
|
||||||
|
DEFAULT_PANEL = 'defaults'
|
86
openstack_dashboard/test/test_plugins/panel_tests.py
Normal file
86
openstack_dashboard/test/test_plugins/panel_tests.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# 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 copy
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core import urlresolvers
|
||||||
|
from django.test.utils import override_settings
|
||||||
|
from django.utils.importlib import import_module # noqa
|
||||||
|
|
||||||
|
import horizon
|
||||||
|
from horizon import base
|
||||||
|
from horizon import conf
|
||||||
|
|
||||||
|
from openstack_dashboard.dashboards.admin.info import panel as info_panel
|
||||||
|
from openstack_dashboard.test import helpers as test
|
||||||
|
from openstack_dashboard.test.test_panels.plugin_panel \
|
||||||
|
import panel as plugin_panel
|
||||||
|
import openstack_dashboard.test.test_plugins.panel_config
|
||||||
|
from openstack_dashboard.utils import settings as util_settings
|
||||||
|
|
||||||
|
|
||||||
|
HORIZON_CONFIG = copy.copy(settings.HORIZON_CONFIG)
|
||||||
|
INSTALLED_APPS = list(settings.INSTALLED_APPS)
|
||||||
|
|
||||||
|
util_settings.update_dashboards([
|
||||||
|
openstack_dashboard.test.test_plugins.panel_config,
|
||||||
|
], HORIZON_CONFIG, INSTALLED_APPS)
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(HORIZON_CONFIG=HORIZON_CONFIG,
|
||||||
|
INSTALLED_APPS=INSTALLED_APPS)
|
||||||
|
class PanelPluginTests(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(PanelPluginTests, self).setUp()
|
||||||
|
self.old_horizon_config = conf.HORIZON_CONFIG
|
||||||
|
conf.HORIZON_CONFIG = conf.LazySettings()
|
||||||
|
base.Horizon._urls()
|
||||||
|
# Trigger discovery, registration, and URLconf generation if it
|
||||||
|
# hasn't happened yet.
|
||||||
|
self.client.get(settings.LOGIN_URL)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(PanelPluginTests, self).tearDown()
|
||||||
|
conf.HORIZON_CONFIG = self.old_horizon_config
|
||||||
|
# Destroy our singleton and re-create it.
|
||||||
|
base.HorizonSite._instance = None
|
||||||
|
del base.Horizon
|
||||||
|
base.Horizon = base.HorizonSite()
|
||||||
|
self._reload_urls()
|
||||||
|
|
||||||
|
def _reload_urls(self):
|
||||||
|
"""Clears out the URL caches, reloads the root urls module, and
|
||||||
|
re-triggers the autodiscovery mechanism for Horizon. Allows URLs
|
||||||
|
to be re-calculated after registering new dashboards. Useful
|
||||||
|
only for testing and should never be used on a live site.
|
||||||
|
"""
|
||||||
|
urlresolvers.clear_url_caches()
|
||||||
|
reload(import_module(settings.ROOT_URLCONF))
|
||||||
|
base.Horizon._urls()
|
||||||
|
|
||||||
|
def test_add_panel(self):
|
||||||
|
dashboard = horizon.get_dashboard("admin")
|
||||||
|
self.assertIn(plugin_panel.PluginPanel,
|
||||||
|
[p.__class__ for p in dashboard.get_panels()])
|
||||||
|
|
||||||
|
def test_remove_panel(self):
|
||||||
|
dashboard = horizon.get_dashboard("admin")
|
||||||
|
self.assertNotIn(info_panel.Info,
|
||||||
|
[p.__class__ for p in dashboard.get_panels()])
|
||||||
|
|
||||||
|
def test_default_panel(self):
|
||||||
|
dashboard = horizon.get_dashboard("admin")
|
||||||
|
self.assertEqual(dashboard.default_panel, 'defaults')
|
@@ -41,19 +41,21 @@ def import_dashboard_config(modules):
|
|||||||
config = collections.defaultdict(dict)
|
config = collections.defaultdict(dict)
|
||||||
for module in modules:
|
for module in modules:
|
||||||
for key, submodule in import_submodules(module).iteritems():
|
for key, submodule in import_submodules(module).iteritems():
|
||||||
try:
|
if hasattr(submodule, 'DASHBOARD'):
|
||||||
dashboard = submodule.DASHBOARD
|
dashboard = submodule.DASHBOARD
|
||||||
except AttributeError:
|
|
||||||
logging.warning("Skipping %s because it doesn't "
|
|
||||||
"have DASHBOARD defined." % submodule.__name__)
|
|
||||||
else:
|
|
||||||
config[dashboard].update(submodule.__dict__)
|
config[dashboard].update(submodule.__dict__)
|
||||||
|
elif hasattr(submodule, 'PANEL'):
|
||||||
|
config[submodule.__name__] = submodule.__dict__
|
||||||
|
#_update_panels(config, submodule)
|
||||||
|
else:
|
||||||
|
logging.warning("Skipping %s because it doesn't have DASHBOARD"
|
||||||
|
" or PANEL defined.", submodule.__name__)
|
||||||
return sorted(config.iteritems(),
|
return sorted(config.iteritems(),
|
||||||
key=lambda c: c[1]['__name__'].rsplit('.', 1))
|
key=lambda c: c[1]['__name__'].rsplit('.', 1))
|
||||||
|
|
||||||
|
|
||||||
def update_dashboards(modules, horizon_config, installed_apps):
|
def update_dashboards(modules, horizon_config, installed_apps):
|
||||||
"""Imports dashboard configuration from modules and applies it.
|
"""Imports dashboard and panel configuration from modules and applies it.
|
||||||
|
|
||||||
The submodules from specified modules are imported, and the configuration
|
The submodules from specified modules are imported, and the configuration
|
||||||
for the specific dashboards is merged, with the later modules overriding
|
for the specific dashboards is merged, with the later modules overriding
|
||||||
@@ -75,18 +77,30 @@ def update_dashboards(modules, horizon_config, installed_apps):
|
|||||||
configurations will be applied in order ``qux``, ``baz`` (``baz`` is
|
configurations will be applied in order ``qux``, ``baz`` (``baz`` is
|
||||||
second, because the most recent file which contributed to it, ``_30_baz``,
|
second, because the most recent file which contributed to it, ``_30_baz``,
|
||||||
comes after ``_20_qux``).
|
comes after ``_20_qux``).
|
||||||
|
|
||||||
|
Panel specific configurations are stored in horizon_config. Dashboards
|
||||||
|
from both plugin-based and openstack_dashboard must be registered before
|
||||||
|
the panel configuration can be applied. Making changes to the panel is
|
||||||
|
deferred until the horizon autodiscover is completed, configurations are
|
||||||
|
applied in alphabetical order of files where it was imported.
|
||||||
"""
|
"""
|
||||||
dashboards = []
|
dashboards = []
|
||||||
exceptions = {}
|
exceptions = {}
|
||||||
apps = []
|
apps = []
|
||||||
for dashboard, config in import_dashboard_config(modules):
|
panel_customization = []
|
||||||
|
for key, config in import_dashboard_config(modules):
|
||||||
if config.get('DISABLED', False):
|
if config.get('DISABLED', False):
|
||||||
continue
|
continue
|
||||||
|
if config.get('DASHBOARD'):
|
||||||
|
dashboard = key
|
||||||
dashboards.append(dashboard)
|
dashboards.append(dashboard)
|
||||||
exceptions.update(config.get('ADD_EXCEPTIONS', {}))
|
exceptions.update(config.get('ADD_EXCEPTIONS', {}))
|
||||||
apps.extend(config.get('ADD_INSTALLED_APPS', []))
|
apps.extend(config.get('ADD_INSTALLED_APPS', []))
|
||||||
if config.get('DEFAULT', False):
|
if config.get('DEFAULT', False):
|
||||||
horizon_config['default_dashboard'] = dashboard
|
horizon_config['default_dashboard'] = dashboard
|
||||||
|
elif config.get('PANEL'):
|
||||||
|
panel_customization.append(config)
|
||||||
|
horizon_config['panel_customization'] = panel_customization
|
||||||
horizon_config['dashboards'] = tuple(dashboards)
|
horizon_config['dashboards'] = tuple(dashboards)
|
||||||
horizon_config['exceptions'].update(exceptions)
|
horizon_config['exceptions'].update(exceptions)
|
||||||
installed_apps.extend(apps)
|
installed_apps.extend(apps)
|
||||||
|
Reference in New Issue
Block a user