[openstack-dev] [Horizon][Sahara] Question about PanelGroups and Panels in subdirectories of a given dashboard

Chad Roberts croberts at redhat.com
Wed Jun 25 20:51:53 UTC 2014

Here is the scenario:  We are looking to merge the Sahara (Data Processing) dashboard into horizon.  The 9 panels will live in a PanelGroup under "Project" called "Data Processing".  In the spirit of code organization, it was suggested that I put all 9 of the data processing panels into a subdirectory under "project".  The following patch shows you what we currently have (https://review.openstack.org/#/c/91118/ ).

Organizing the code this way has lead me to create a couple of bugs.
1) https://bugs.launchpad.net/horizon/+bug/1329050  (The panelGroup shows up as "Other" rather than "Data Processing")
2) https://bugs.launchpad.net/horizon/+bug/1333739  (The panels within the group show-up in a random order each time I launch horizon)

A bit more looking around lead me to discover that if I change the slugs of each of the panels to "data_processing.<panel name>" that I do wind-up eliminating the symptoms in each of the bugs I describe above.  That's a good thing, right? (But is it the intent of the current code to work this way?)

It turns out that while the panels show up in the correct order in the "Data Processing" panel group, none of the templates were found.  Doh!  That's a problem.  So, I did some digging there as well and here is what I found....spoiler alert, I came up with a workaround, but I'm afraid it might be viewed as ugly.

A little background:
When we register a panel, the following code gets called (in horizon/base.py)....

   def register(cls, panel):
        """Registers a :class:`~horizon.Panel` with this dashboard."""
        panel_class = Horizon.register_panel(cls, panel)
        # Support template loading from panel template directories.
        panel_mod = import_module(panel.__module__)
        panel_dir = os.path.dirname(panel_mod.__file__)
        template_dir = os.path.join(panel_dir, "templates")
        if os.path.exists(template_dir):
            key = os.path.join(cls.slug, panel.slug)
            loaders.panel_template_dirs[key] = template_dir
        return panel_class

That sets up our loader.panel_template_dirs with the following key/value pair (using my data_processing.plugins panel as the example here).
key:  project/data_processing.plugins
value: /home/croberts/src/horizon/openstack_dashboard/dashboards/project/data_processing/plugins/templates

When we go to render the template, we eventually call the following (from horizon/loaders.py)...
    def get_template_sources(self, template_name):
        bits = template_name.split(os.path.sep, 2)
        if len(bits) == 3:
            dash_name, panel_name, remainder = bits
            key = os.path.join(dash_name, panel_name)
            if key in panel_template_dirs:
                template_dir = panel_template_dirs[key]
                    yield safe_join(template_dir, panel_name, remainder)

In order for that function to be able to find the correct value that we stored in loader.panel_template_dirs earlier, we need to reference our template like this (from my panel's views.py)...
template_name = 'project/data_processing.plugins/plugins.html'

That gives us (inside of get_template_sources)...
dash_name = project
panel_name = data_processing.plugins
remainder = plugins.html

Nothing too bad so far really.
The slightly ugly part (to me) is when we eventually join template_dir (which is the value from loader.panel_template_dirs) with panel_name and remainder.
Doing so, gives us a template location of "/home/croberts/src/horizon/openstack_dashboard/dashboards/project/data_processing/plugins/templates/data_processing.plugins/plugins.html"

The part that seems ugly to me is that we need a "data_processing.plugins" subdirectory rather than just "plugins".  Is that really the desired directory name, or should some changes be made to eliminate the "data_processing." from that directory name [ie:  the directory structure would look like every other panel that is defined (none of them are in a subdirectory like this one)]

Please give me your thoughts on this.  

Are there one or more bugs in play here?
Is there something that needs enhancement in order to work better with "nested" panel groups/panels?
Should I just work within the current code and create my template/data_processing.<panel_name> template directories?


More information about the OpenStack-dev mailing list