OpenStack Horizon Documentation
repository·master·Indexed 23 days ago
https://github.com/openstack/horizonHorizon is a Django-based dashboard providing a web-based interface for OpenStack services. It serves as an extensible framework for building dashboards using reusable components. Documentation covers administrative tasks such as managing roles and compute flavors, customizing the visual appearance (logos, colors, and themes), and configuring the dashboard for HTTP and HTTPS deployments via local_settings.py and Apache.
What's inside OpenStack Horizon
- Horizon is the canonical web-based user interface for OpenStack services. It provides a graphical dashboard to manage various OpenStack components such as Nova (compute), Swift (object storage), Keystone (identity), and others.
Nova feature improvements in Essex
masterThe Essex release includes significant enhancements for managing Nova resources:
- Volume Management: Support for volume creation, management, and snapshots, including realtime AJAX updates for volumes in transition states.
- Instance Management: Improved display and interaction for instances, including launching instances from volumes, pausing/suspending instances, and displaying power states. Realtime AJAX updates are provided for instances in transition states.
- Networking: Support for managing Floating IP address pools.
- Views: New dedicated detail views for both instances and volumes.
Understand the responsibilities of the Horizon Core Reviewer Team
masterThe Horizon core reviewer team manages the project's health, quality, and community. Their responsibilities include:
- Mentorship: Guiding community contributors in solution design, testing, and the review process.
- Patch Review: Evaluating submissions for functionality, alignment with project vision, completeness (testing, documentation, release notes), and upgrade compatibility.
- Bug Management: Assisting in bug triage and the delivery of fixes.
- Quality Assurance: Curating the gate, triaging failures, and ensuring testing levels remain adequate as features are added.
- Documentation: Maintaining accurate and relevant documentation.
- Communication: Answering questions on mailing lists, participating in IRC, and interfacing with other OpenStack teams.
- Plugin Support: Helping horizon plugin maintainers with framework-related changes (e.g., Django version bumps, testing improvements, or plugin interface changes).
Overview of testing types in Horizon
masterHorizon utilizes three main types of testing to ensure stability and quality:
- Unit tests: Isolated, stand-alone tests with no external dependencies. They are fast, lightweight, and written from the perspective of the code's internal logic.
- Functional tests: Written from the perspective of the end user. They focus on inputs and outputs to verify that the code meets functional requirements (the "spec"), regardless of the underlying implementation.
- Integration Tests: Tests all components that the codebase interacts with in a repeatable, "live" manner. These catch bugs that unit and functional tests miss and provide screenshots on failure for easier debugging.
Integration Test Configuration
You can configure the directory where integration test screenshots are saved via the
horizon.conffile. The default value is./integration_tests_screenshots.Overview of Horizon settings categories
masterHorizon settings are organized into four main categories:
- General Settings: Visual configurations (like modal backdrop styles), bug URLs, theme configurations, and settings affecting all services (e.g., API request page sizes).
- Service-specific Settings: Configuration for specific services (like Nova or Neutron) to enable or disable features that are not advertised via their APIs.
- Django Settings: Standard Django application settings. Horizon documents only those it alters by default; for all other options, refer to the official Django documentation.
- Other Settings: Miscellaneous settings that do not fit the above categories.
How switchable fields work in Horizon forms
masterHorizon provides a mechanism to programmatically hide, show, and rename form fields based on the selection in a trigger field. This is achieved using specific CSS classes and HTML data attributes.
The Trigger (Switchable Field)
To create a trigger, use a field with a
selectinput widget that has:- The CSS class
switchable. - A
data-slugattribute (e.g.,data-slug='source').
The Target (Switched Field)
To create a field that reacts to the trigger, use a field that has:
- The CSS class
switched. - A
data-switch-onattribute that matches the trigger'sdata-slug(e.g.,data-switch-on='source'). - State-specific data attributes to define when the field should be visible and what its label should be. The format is
data-<slug>-<value>="<desired label>"(e.g.,data-source-cidr='CIDR').
If the trigger's value does not match any defined state attribute for a switched field, that field is hidden.
Best Practices
Avoid having a single switched field listen to multiple triggers via
data-switch-on. This behavior is unpredictable. Instead, create independent fields for each trigger and merge their results during the form'sclean()orhandle()phase.source = forms.ChoiceField( label=_('Source'), choices=[ ('cidr', _('CIDR')), ('sg', _('Security Group')) ], widget=forms.ThemableSelectWidget(attrs={ 'class': 'switchable', 'data-slug': 'source' }) ) cidr = fields.IPField( label=_("CIDR"), required=False, widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'source', 'data-source-cidr': _('CIDR') }) ) security_group = forms.ChoiceField( label=_('Security Group'), required=False, widget=forms.ThemableSelectWidget(attrs={ 'class': 'switched', 'data-switch-on': 'source', 'data-source-sg': _('Security Group') }) )- The CSS class
Use cached database sessions
masterTo mitigate the performance overhead of database-backed sessions, you can use the
cached_dbback end. This hybrid approach uses both your database and your caching infrastructure (like Memcached or Redis) to perform write-through caching and efficient retrieval.Requirement: You must have both a database and a cache configured in
local_settings.py.SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"Handle exceptions in Horizon UI
masterTo prevent exposing sensitive or obscure data from OpenStack APIs to the end-user, do not propagate direct exception messages to the UI.
Horizon catches API exceptions and normalizes them using
horizon.exceptions.handle. This ensures error messages are clean and potentially translatable (though API messages themselves are not translatable).Use the bootstrap directory for Bootstrap overrides
masterThe
openstack_dashboard/themes/default/bootstrap/directory is used to customize Bootstrap components and variables._variables.scss: Define or alter Bootstrap variables to change the look and feel of the default theme.components/: Contains SCSS overrides for specific Bootstrap components (e.g., tables, navbars)._styles.scss: Imports the SCSS defined for each component in thecomponents/directory.
Map Django settings to oslo.config options
masterDuring the migration to
oslo.config, existing Django settings are mapped to specific INI sections and option names. Prefixes are typically dropped, and dictionary-based settings are broken down into individual options.Mapping Rules:
- Prefix Removal:
OPENSTACK_KEYSTONE_DEFAULT_ROLEmaps to[keystone] default_role. - Dictionary Flattening: A dictionary setting like
OPENSTACK_KEYSTONE_BACKENDis split into multiple options:OPENSTACK_KEYSTONE_BACKEND['name']$\rightarrow$[keystone] backend_nameOPENSTACK_KEYSTONE_BACKEND['can_edit_user']$\rightarrow$[keystone] backend_can_edit_user
- Section Usage: The
[default]section is reserved for common settings likeDEBUGorLOGGING.
- Prefix Removal:
How Horizon Tabs and TabGroups work together
masterHorizon provides a component-based system for building tabbed interfaces. The architecture relies on three main layers:
- TabGroup: The fundamental container that holds all tabs and manages the high-level logic of the tabbed interface.
- Tab: The discrete unit within a group, representing a single view of data. There are specialized versions like
TableTabfor data-heavy views. - TabView: A generic class-based view used to handle the actual rendering and display of a
TabGroupin the dashboard.
This system supports advanced features like dynamic AJAX loading and simplified templating/styling.
How DataTables, Actions, and Class-based Views work together
masterHorizon's
horizon.tablesmodule provides a reusable API for building data-driven interfaces using three core components:- DataTables: The core structure that defines columns and data presentation.
- Actions: Manipulations performed on data or the table itself (e.g., CRUD, linking, filtering).
- Class-based Views: The glue that connects a
DataTableto a web request and provides the data.
When using a
DataTableView, the request follows this lifecycle:- The request enters the view.
- The table class is instantiated without data.
- Preemptive actions (where
preempt=True) are checked. - Data is fetched and loaded into the table.
- All other actions are checked.
- The standard response (usually the rendered table) is returned.
from horizon import tables from .tables import MyTable class MyTableView(tables.DataTableView): table_class = MyTable template_name = "my_app/my_table_view.html" def get_data(self): return my_api.objects.list()