Clean up service and role translations
* add documentation for settings * clean up documentation * split role help into own template * remove old debug print statements Change-Id: Id764dca96e37627974c77181e73634f461ab10b1
This commit is contained in:
parent
0c836b1cac
commit
379709c979
61
README.rst
61
README.rst
@ -5,61 +5,14 @@ adjutant-ui
|
||||
Adjutant Dashboard
|
||||
|
||||
* Free software: Apache license
|
||||
* Source: https://github.com/catalyst/adjutant-ui
|
||||
* Source: https://github.com/openstack/adjutant-ui
|
||||
|
||||
Manual Installation
|
||||
-------------------
|
||||
This is the Horizon plugin for the Adjutant service, and provides UI elements
|
||||
to the core features that Adjutant adds.
|
||||
|
||||
Begin by cloning the Horizon and Adjutant UI repositories::
|
||||
|
||||
git clone https://github.com/openstack/horizon
|
||||
git clone https://github.com/catalyst/adjutant-ui
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Create a virtual environment and install Horizon dependencies::
|
||||
|
||||
cd horizon
|
||||
python tools/install_venv.py
|
||||
|
||||
Set up your ``local_settings.py`` file::
|
||||
|
||||
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
|
||||
|
||||
Open up the copied ``local_settings.py`` file in your preferred text
|
||||
editor. You will want to customize several settings:
|
||||
|
||||
- ``OPENSTACK_HOST`` should be configured with the hostname of your
|
||||
OpenStack server. Verify that the ``OPENSTACK_KEYSTONE_URL`` and
|
||||
``OPENSTACK_KEYSTONE_DEFAULT_ROLE`` settings are correct for your
|
||||
environment. (They should be correct unless you modified your
|
||||
OpenStack server to change them.)
|
||||
- ``OPENSTACK_REGISTRATION_URL`` should also be configured to point to
|
||||
you Adjutant server and version.
|
||||
- The example Adjutant conf is set with ``USERNAME_IS_EMAIL = True`` and you
|
||||
will want to add that to your local Horizon settings as well unless you've
|
||||
set that to false in Adjutant itself. If the value isn't there, then
|
||||
adjutant-ui defaults to the false case.
|
||||
|
||||
You will also need to update the ``keystone_policy.json`` file
|
||||
(openstack_dashboard/conf/keystone_policy.json) in horizon with the following
|
||||
lines::
|
||||
|
||||
"project_mod": "role:project_mod",
|
||||
"project_admin": "role:project_admin",
|
||||
"project_mod_or_admin": "rule:admin_required or rule:project_mod or rule:project_admin",
|
||||
"project_admin_only": "rule:admin_required or rule:project_admin",
|
||||
"identity:project_users_access": "rule:project_mod_or_admin",
|
||||
|
||||
Install Adjutant UI with all dependencies in your virtual environment::
|
||||
|
||||
tools/with_venv.sh pip install -e ../adjutant-ui/
|
||||
|
||||
And enable it in Horizon::
|
||||
|
||||
cp ../adjutant-ui/adjutant-ui/enabled/_* openstack_dashboard/local/enabled
|
||||
|
||||
To run horizon with the newly enabled Adjutant UI plugin run::
|
||||
|
||||
./run_tests.sh --runserver 0.0.0.0:8080
|
||||
|
||||
to have the application start on port 8080 and the horizon dashboard will be
|
||||
available in your browser at http://localhost:8080/
|
||||
Documentation is stored in doc/, a sphinx build of the documentation can be
|
||||
generated with the command ``tox -e docs``.
|
||||
|
@ -20,6 +20,7 @@ from six.moves.urllib.parse import urljoin
|
||||
import six
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon.utils import functions as utils
|
||||
from horizon.utils import memoized
|
||||
@ -39,6 +40,10 @@ TASK = collections.namedtuple('Task',
|
||||
'created_on', 'approved_on', 'page',
|
||||
'completed_on', 'actions', 'status'])
|
||||
|
||||
NOTIFICATION = collections.namedtuple('Notification',
|
||||
['uuid', 'notes', 'error', 'created_on',
|
||||
'acknowledged', 'task'])
|
||||
|
||||
QUOTA_SIZE = collections.namedtuple('QuotaSize',
|
||||
['id', 'name', 'cinder',
|
||||
'nova', 'neutron'])
|
||||
@ -67,7 +72,7 @@ QUOTA_TASK = collections.namedtuple(
|
||||
# relevant to customers to be shown initially on the update page.
|
||||
# These can be overriden in the local_settings file:
|
||||
# IMPORTANT_QUOTAS = {<service>: [<quota_name>], }
|
||||
DEFAULT_IMPORTANT_QUOTAS = {
|
||||
IMPORTANT_QUOTAS = {
|
||||
'nova': [
|
||||
'instances', 'cores', 'ram',
|
||||
],
|
||||
@ -77,6 +82,9 @@ DEFAULT_IMPORTANT_QUOTAS = {
|
||||
'neutron': [
|
||||
'network', 'floatingip', 'router', 'security_group',
|
||||
],
|
||||
'octavia': [
|
||||
'load_balancer',
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +92,7 @@ DEFAULT_IMPORTANT_QUOTAS = {
|
||||
# Can be overriden in the local_settings file by setting:
|
||||
# HIDDEN_QUOTAS = {<service>: [<quota_name>], }
|
||||
# or disabled entirely with: HIDDEN_QUOTAS = {}
|
||||
DEFAULT_HIDDEN_QUOTAS = {
|
||||
HIDDEN_QUOTAS = {
|
||||
# these values have long since been deprecated from Nova
|
||||
'nova': [
|
||||
'security_groups', 'security_group_rules',
|
||||
@ -101,9 +109,47 @@ DEFAULT_HIDDEN_QUOTAS = {
|
||||
],
|
||||
}
|
||||
|
||||
NOTIFICATION = collections.namedtuple('Notification',
|
||||
['uuid', 'notes', 'error', 'created_on',
|
||||
'acknowledged', 'task'])
|
||||
|
||||
ROLE_TRANSLATIONS = {
|
||||
'project_admin': _('Project Administrator'),
|
||||
'project_mod': _('Project Moderator'),
|
||||
'_member_': _('Project Member'),
|
||||
'Member': _('Project Member'),
|
||||
'heat_stack_owner': _('Heat Stack Owner'),
|
||||
'project_readonly': _('Project Read-only'),
|
||||
'compute_start_stop': _('Compute Start/Stop'),
|
||||
'object_storage': _('Object Storage')
|
||||
}
|
||||
|
||||
|
||||
def get_role_text(name):
|
||||
# Gets the role text for a given role.
|
||||
# If it doesn't exist will simply return the role name.
|
||||
role_translations = getattr(settings, 'ROLE_TRANSLATIONS', None)
|
||||
if role_translations is None:
|
||||
role_translations = ROLE_TRANSLATIONS
|
||||
if name in role_translations:
|
||||
return role_translations[name].format()
|
||||
return name
|
||||
|
||||
|
||||
SERVICE_TRANSLATIONS = {
|
||||
'cinder': _('Volume'),
|
||||
'neutron': _('Networking'),
|
||||
'nova': _('Compute'),
|
||||
'octavia': _('Load Balancer'),
|
||||
}
|
||||
|
||||
|
||||
def get_service_type(name):
|
||||
# Takes service names and returns a 'nice' name of where they
|
||||
# are from
|
||||
service_translations = getattr(settings, 'SERVICE_TRANSLATIONS', None)
|
||||
if service_translations is None:
|
||||
service_translations = SERVICE_TRANSLATIONS
|
||||
if name in service_translations:
|
||||
return service_translations[name].format()
|
||||
return name
|
||||
|
||||
|
||||
class AdjutantApiError(BaseException):
|
||||
@ -511,14 +557,14 @@ def task_revalidate(request, task_id):
|
||||
def _is_quota_hidden(service, resource):
|
||||
hidden_quotas = getattr(settings, 'HIDDEN_QUOTAS', None)
|
||||
if hidden_quotas is None:
|
||||
hidden_quotas = DEFAULT_HIDDEN_QUOTAS
|
||||
hidden_quotas = HIDDEN_QUOTAS
|
||||
return service in hidden_quotas and resource in hidden_quotas[service]
|
||||
|
||||
|
||||
def _is_quota_important(service, resource):
|
||||
important_quotas = getattr(settings, 'IMPORTANT_QUOTAS', None)
|
||||
if important_quotas is None:
|
||||
important_quotas = DEFAULT_IMPORTANT_QUOTAS
|
||||
important_quotas = IMPORTANT_QUOTAS
|
||||
return (
|
||||
service in important_quotas and resource in important_quotas[service])
|
||||
|
||||
|
@ -21,7 +21,6 @@ from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from adjutant_ui.api import adjutant
|
||||
from adjutant_ui.content.project_users import utils
|
||||
|
||||
|
||||
def get_role_choices(request):
|
||||
@ -31,7 +30,7 @@ def get_role_choices(request):
|
||||
user can manage.
|
||||
"""
|
||||
role_names = adjutant.valid_role_names_get(request)
|
||||
role_tuples = [(r, utils.get_role_text(r)) for r in role_names]
|
||||
role_tuples = [(r, adjutant.get_role_text(r)) for r in role_names]
|
||||
role_tuples = sorted(role_tuples, key=lambda role: role[1])
|
||||
return role_tuples
|
||||
|
||||
|
@ -21,7 +21,6 @@ from horizon import exceptions
|
||||
from horizon import tables
|
||||
|
||||
from adjutant_ui.api import adjutant
|
||||
from adjutant_ui.content.project_users import utils
|
||||
|
||||
|
||||
class InviteUser(tables.LinkAction):
|
||||
@ -155,7 +154,7 @@ class CohortFilter(tables.FixedFilterAction):
|
||||
|
||||
|
||||
def UserRoleDisplayFilter(role_list):
|
||||
roles = [utils.get_role_text(r) for r in role_list]
|
||||
roles = [adjutant.get_role_text(r) for r in role_list]
|
||||
return ', '.join(roles)
|
||||
|
||||
|
||||
|
@ -6,19 +6,17 @@
|
||||
{% block form_action %}{% url 'horizon:management:project_users:invite' %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Invite a person to join your project. If the user does not exist they will be emailed instructions to set up their account then automatically added to your project." %}</p>
|
||||
<h4>{% trans "Roles:" %}</h4>
|
||||
<p>{% trans "The “Project Admin” role allows users to have full control over your project, including adding moderators and inviting other people to join it." %}</p>
|
||||
<p>{% trans "The “Project Moderator” role can invite other people to join your project and update their roles, but cannot change the project admin." %}</p>
|
||||
<p>{% trans "The “Project Member” role gives people access to all services on your project, but does not allow them to invite other people to join the project or update roles." %}</p>
|
||||
</div>
|
||||
|
||||
{% include 'management/project_users/_role_help.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{% load i18n %}
|
||||
|
||||
<h4>{% trans "Roles:" %}</h4>
|
||||
<p>{% trans "The “Project Administrator” role allows users to have full control over your project, including adding moderators and inviting other people to join it." %}</p>
|
||||
<p>{% trans "The “Project Moderator” role can invite other people to join your project and update their roles, but cannot change the project admin." %}</p>
|
||||
<p>{% trans "The “Project Member” role gives people access to all services on your project, but does not allow them to invite other people to join the project or update roles." %}</p>
|
@ -5,19 +5,17 @@
|
||||
{% block modal-header %}{% trans "Update User" %}{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:management:project_users:update' user.id %}{% endblock %}
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Adjust user roles to revoke or grant roles within this project." %}</p>
|
||||
<h4>{% trans "Roles:" %}</h4>
|
||||
<p>{% trans "The “Project Admin” role allows users to have full control over your project, including adding moderators and inviting other people to join it." %}</p>
|
||||
<p>{% trans "The “Project Moderator” role can invite other people to join your project and update their roles, but cannot change the project admin." %}</p>
|
||||
<p>{% trans "The “Project Member” role gives people access to all services on your project, but does not allow them to invite other people to join the project or update roles." %}</p>
|
||||
</div>
|
||||
|
||||
{% include 'management/project_users/_role_help.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
|
@ -1,33 +0,0 @@
|
||||
# Copyright (c) 2016 Catalyst IT Ltd.
|
||||
#
|
||||
# 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 _
|
||||
|
||||
ROLE_TRANSLATIONS = {
|
||||
'project_admin': _('Project Admin'),
|
||||
'project_mod': _('Project Moderator'),
|
||||
'_member_': _('Project Member'),
|
||||
'heat_stack_owner': _('Heat Stack Owner'),
|
||||
'project_readonly': _('Project Read-only'),
|
||||
'compute_start_stop': _('Compute Start/Stop'),
|
||||
'object_storage': _('Object Storage')
|
||||
}
|
||||
|
||||
|
||||
def get_role_text(rname):
|
||||
# Gets the role text for a given role.
|
||||
# If it doesn't exist will simply return the role name.
|
||||
if rname in ROLE_TRANSLATIONS:
|
||||
return ROLE_TRANSLATIONS[rname].format()
|
||||
return rname
|
@ -35,15 +35,6 @@ def display_as_percent(value):
|
||||
return '{:.1%}'.format(value)
|
||||
|
||||
|
||||
def service_name(value):
|
||||
# Takes service names and returns a 'nice' name of where they
|
||||
# are from
|
||||
service_name_dict = {'cinder': 'Volume Storage',
|
||||
'neutron': 'Networking',
|
||||
'nova': 'Compute'}
|
||||
return service_name_dict.get(value, value)
|
||||
|
||||
|
||||
class UpdateQuota(tables.LinkAction):
|
||||
name = "update"
|
||||
verbose_name = _("Update Quota")
|
||||
@ -109,7 +100,7 @@ class UpdateQuotaRow(tables.Row):
|
||||
|
||||
class RegionQuotaDetailTable(tables.DataTable):
|
||||
service = tables.Column("service", verbose_name=_("Service"),
|
||||
filters=(service_name, ))
|
||||
filters=(adjutant.get_service_type, ))
|
||||
name = tables.Column(get_quota_name, verbose_name=_("Resource Name"),)
|
||||
value = tables.Column("current_quota", verbose_name=_("Resource Quota"), )
|
||||
usage = tables.Column("current_usage", verbose_name=_("Current Usage"))
|
||||
@ -119,7 +110,7 @@ class RegionQuotaDetailTable(tables.DataTable):
|
||||
|
||||
class QuotaDetailUsageTable(tables.DataTable):
|
||||
service = tables.Column("service", verbose_name=_("Service"),
|
||||
filters=(service_name, ))
|
||||
filters=(adjutant.get_service_type, ))
|
||||
name = tables.Column(get_quota_name, verbose_name=_("Resource Name"),)
|
||||
value = tables.Column("value", verbose_name=_("Quota Value"), )
|
||||
current_quota = tables.Column("current_quota",
|
||||
@ -176,7 +167,7 @@ class SizeOverviewTable(tables.DataTable):
|
||||
|
||||
class ChangeSizeDisplayTable(tables.DataTable):
|
||||
service = tables.Column("service", verbose_name=_("Service"),
|
||||
filters=(service_name, ),
|
||||
filters=(adjutant.get_service_type, ),
|
||||
hidden=True)
|
||||
name = tables.Column(get_quota_name, verbose_name=_("Resource"),)
|
||||
current_quota = tables.Column("current_quota",
|
||||
|
@ -106,8 +106,6 @@ class TaskOverviewTab(tabs.Tab):
|
||||
template_name = 'management/tasks/_task_detail_overview.html'
|
||||
|
||||
def get_context_data(self, request):
|
||||
print self.tab_group
|
||||
print self.tab_group.kwargs
|
||||
return {"task": self.tab_group.kwargs['task']}
|
||||
|
||||
|
||||
|
@ -1,17 +1,7 @@
|
||||
# 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
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Horizon documentation build configuration file, created by
|
||||
# sphinx-quickstart on Thu Oct 27 11:38:59 2011.
|
||||
# Adjutant documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Jun 21 13:29:33 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
@ -22,420 +12,124 @@
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT = os.path.abspath(os.path.join(BASE_DIR, "..", ".."))
|
||||
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
# This is required for ReadTheDocs.org, but isn't a bad idea anyway.
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
|
||||
'openstack_dashboard.test.settings')
|
||||
|
||||
from adjutant_ui \
|
||||
import version as adjutant_ui_ver
|
||||
|
||||
|
||||
def write_autodoc_index():
|
||||
|
||||
def find_autodoc_modules(module_name, sourcedir):
|
||||
"""returns a list of modules in the SOURCE directory."""
|
||||
modlist = []
|
||||
os.chdir(os.path.join(sourcedir, module_name))
|
||||
print("SEARCHING %s" % sourcedir)
|
||||
for root, dirs, files in os.walk("."):
|
||||
for filename in files:
|
||||
if filename == 'tests.py':
|
||||
continue
|
||||
if filename.endswith(".py"):
|
||||
# remove the pieces of the root
|
||||
elements = root.split(os.path.sep)
|
||||
# replace the leading "." with the module name
|
||||
elements[0] = module_name
|
||||
# and get the base module name
|
||||
base, extension = os.path.splitext(filename)
|
||||
if not (base == "__init__"):
|
||||
elements.append(base)
|
||||
result = ".".join(elements)
|
||||
# print result
|
||||
modlist.append(result)
|
||||
return modlist
|
||||
|
||||
RSTDIR = os.path.abspath(os.path.join(BASE_DIR, "sourcecode"))
|
||||
SRCS = [('adjutant_ui_ver', ROOT), ]
|
||||
|
||||
EXCLUDED_MODULES = ()
|
||||
CURRENT_SOURCES = {}
|
||||
|
||||
if not(os.path.exists(RSTDIR)):
|
||||
os.mkdir(RSTDIR)
|
||||
CURRENT_SOURCES[RSTDIR] = ['autoindex.rst']
|
||||
|
||||
INDEXOUT = open(os.path.join(RSTDIR, "autoindex.rst"), "w")
|
||||
INDEXOUT.write("""
|
||||
=================
|
||||
Source Code Index
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
""")
|
||||
|
||||
for modulename, path in SRCS:
|
||||
sys.stdout.write("Generating source documentation for %s\n" %
|
||||
modulename)
|
||||
INDEXOUT.write("\n%s\n" % modulename.capitalize())
|
||||
INDEXOUT.write("%s\n" % ("=" * len(modulename),))
|
||||
INDEXOUT.write(".. toctree::\n")
|
||||
INDEXOUT.write(" :maxdepth: 1\n")
|
||||
INDEXOUT.write("\n")
|
||||
|
||||
MOD_DIR = os.path.join(RSTDIR, modulename)
|
||||
CURRENT_SOURCES[MOD_DIR] = []
|
||||
if not(os.path.exists(MOD_DIR)):
|
||||
os.mkdir(MOD_DIR)
|
||||
for module in find_autodoc_modules(modulename, path):
|
||||
if any([module.startswith(exclude) for exclude
|
||||
in EXCLUDED_MODULES]):
|
||||
print("Excluded module %s." % module)
|
||||
continue
|
||||
mod_path = os.path.join(path, *module.split("."))
|
||||
generated_file = os.path.join(MOD_DIR, "%s.rst" % module)
|
||||
|
||||
INDEXOUT.write(" %s/%s\n" % (modulename, module))
|
||||
|
||||
# Find the __init__.py module if this is a directory
|
||||
if os.path.isdir(mod_path):
|
||||
source_file = ".".join((os.path.join(mod_path, "__init__"),
|
||||
"py",))
|
||||
else:
|
||||
source_file = ".".join((os.path.join(mod_path), "py"))
|
||||
|
||||
CURRENT_SOURCES[MOD_DIR].append("%s.rst" % module)
|
||||
# Only generate a new file if the source has changed or we don't
|
||||
# have a doc file to begin with.
|
||||
if not os.access(generated_file, os.F_OK) or (
|
||||
os.stat(generated_file).st_mtime <
|
||||
os.stat(source_file).st_mtime):
|
||||
print("Module %s updated, generating new documentation."
|
||||
% module)
|
||||
FILEOUT = open(generated_file, "w")
|
||||
header = "The :mod:`%s` Module" % module
|
||||
FILEOUT.write("%s\n" % ("=" * len(header),))
|
||||
FILEOUT.write("%s\n" % header)
|
||||
FILEOUT.write("%s\n" % ("=" * len(header),))
|
||||
FILEOUT.write(".. automodule:: %s\n" % module)
|
||||
FILEOUT.write(" :members:\n")
|
||||
FILEOUT.write(" :undoc-members:\n")
|
||||
FILEOUT.write(" :show-inheritance:\n")
|
||||
FILEOUT.write(" :noindex:\n")
|
||||
FILEOUT.close()
|
||||
|
||||
INDEXOUT.close()
|
||||
|
||||
# Delete auto-generated .rst files for sources which no longer exist
|
||||
for directory, subdirs, files in list(os.walk(RSTDIR)):
|
||||
for old_file in files:
|
||||
if old_file not in CURRENT_SOURCES.get(directory, []):
|
||||
print("Removing outdated file for %s" % old_file)
|
||||
os.remove(os.path.join(directory, old_file))
|
||||
|
||||
|
||||
write_autodoc_index()
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ----------------------------------------------------
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings.
|
||||
# They can be extensions coming with Sphinx (named 'sphinx.ext.*')
|
||||
# or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.viewcode',
|
||||
'oslosphinx',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Adjutant UI'
|
||||
project = u'Adjutant-UI'
|
||||
copyright = u'2017, Catalyst IT Ltd'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = adjutant_ui_ver.version_info.version_string()
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = adjutant_ui_ver.version_info.release_string()
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
# language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['**/#*', '**~', '**/#*#']
|
||||
|
||||
# The reST default role (used for this markup: `text`)
|
||||
# to use for all documents.
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
show_authors = False
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
||||
primary_domain = 'py'
|
||||
nitpicky = False
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
# html_theme_path = ['.']
|
||||
# html_theme = '_theme'
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
html_theme_options = {
|
||||
"nosidebar": "false"
|
||||
}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
# html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
# html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
# html_favicon = None
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
|
||||
"-n1"]
|
||||
html_last_updated_fmt = subprocess.check_output(git_cmd,
|
||||
stdin=subprocess.PIPE)
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Horizondoc'
|
||||
htmlhelp_basename = 'Adjutant-UI-doc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output -------------------------------------------------
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass
|
||||
# [howto/manual]).
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'Horizon.tex', u'Horizon Documentation',
|
||||
u'OpenStack Foundation', 'manual'),
|
||||
(master_doc, 'Adjutant-UI.tex', u'Adjutant-UI Documentation',
|
||||
u'Catalyst IT Ltd', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output -------------------------------------------
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', u'Adjutant UI Documentation',
|
||||
'Documentation for the Adjutant UI plugin to the OpenStack\
|
||||
Dashboard (Horizon)',
|
||||
[u'OpenStack'], 1)
|
||||
(master_doc, 'adjutant-ui', u'Adjutant-UI Documentation',
|
||||
['Catalyst IT Ltd'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -----------------------------------------------
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Horizon', u'Horizon Documentation', u'OpenStack',
|
||||
'Horizon', 'One line description of project.', 'Miscellaneous'),
|
||||
(master_doc, 'Adjutant-UI', u'Adjutant-UI Documentation',
|
||||
'Catalyst IT Ltd', 'Adjutant', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# -- Options for Epub output --------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'Horizon'
|
||||
epub_author = u'OpenStack'
|
||||
epub_publisher = u'OpenStack'
|
||||
epub_copyright = u'2012, OpenStack'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
# epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
# epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be an ISBN number
|
||||
# or the project homepage.
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
# epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
# epub_cover = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
# epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
# epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
# epub_exclude_files = []
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
# epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
# epub_tocdup = True
|
||||
|
116
doc/source/configuration.rst
Normal file
116
doc/source/configuration.rst
Normal file
@ -0,0 +1,116 @@
|
||||
Configuring Adjutant-UI
|
||||
=======================
|
||||
|
||||
Adjutant-ui relies solely on the ``OPENSTACK_REGISTRATION_URL`` setting, as
|
||||
much like Keystone's url, this is needed before the user is authenticated and a
|
||||
valid catalog has been returned. This url is used for the password reset
|
||||
functionality, and signup if that panel is turned on.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
OPENSTACK_REGISTRATION_URL = "http://127.0.0.1:5050/v1"
|
||||
|
||||
|
||||
Beyond that all the other settings are optional, with reasonably sensible
|
||||
defaults.
|
||||
|
||||
Username is email
|
||||
+++++++++++++++++
|
||||
|
||||
The first major setting to consider, and this needs to match the same one in
|
||||
Adjutant, is ``USERNAME_IS_EMAIL``. This defaults to ``True`` but can be
|
||||
changed. In doing so all the username/email related forms are updated to
|
||||
reflect the change.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
USERNAME_IS_EMAIL = False
|
||||
|
||||
|
||||
Quota settings
|
||||
++++++++++++++
|
||||
|
||||
If you are using or have enabled the quota management in Adjutant and the UI
|
||||
then there are some settings around that which you can tweak.
|
||||
|
||||
``IMPORTANT_QUOTAS`` lets you change which quota values are emphasised in the
|
||||
quota update view. Defaults to:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
IMPORTANT_QUOTAS = {
|
||||
'nova': [
|
||||
'instances', 'cores', 'ram',
|
||||
],
|
||||
'cinder': [
|
||||
'volumes', 'snapshots', 'gigabytes',
|
||||
],
|
||||
'neutron': [
|
||||
'network', 'floatingip', 'router', 'security_group',
|
||||
],
|
||||
'octavia': [
|
||||
'load_balancer',
|
||||
],
|
||||
}
|
||||
|
||||
``HIDDEN_QUOTAS`` lets you hide quotas that you do not want your users to see
|
||||
or that you think are redundant and confusing. Defaults to:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
HIDDEN_QUOTAS = {
|
||||
# these values have long since been deprecated from Nova
|
||||
'nova': [
|
||||
'security_groups', 'security_group_rules',
|
||||
'floating_ips', 'fixed_ips',
|
||||
],
|
||||
# these by default have no limit
|
||||
'cinder': [
|
||||
'per_volume_gigabytes', 'volumes_lvmdriver-1',
|
||||
'gigabytes_lvmdriver-1', 'snapshots_lvmdriver-1',
|
||||
|
||||
],
|
||||
'neutron': [
|
||||
'subnetpool',
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
Role Translation Settings
|
||||
+++++++++++++++++++++++++
|
||||
|
||||
``ROLE_TRANSLATIONS`` lets you control the way we rename roles in the dashboard
|
||||
in the Adjutant panels. This is mostly so that you can give your roles simple
|
||||
names in Keystone, but here in the GUI given them more descriptive or user
|
||||
friendly names. Defaults to:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
ROLE_TRANSLATIONS = {
|
||||
'project_admin': _('Project Administrator'),
|
||||
'project_mod': _('Project Moderator'),
|
||||
'_member_': _('Project Member'),
|
||||
'Member': _('Project Member'),
|
||||
'heat_stack_owner': _('Heat Stack Owner'),
|
||||
'project_readonly': _('Project Read-only'),
|
||||
'compute_start_stop': _('Compute Start/Stop'),
|
||||
'object_storage': _('Object Storage')
|
||||
}
|
||||
|
||||
|
||||
Service Translation Settings
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
``SERVICE_TRANSLATIONS`` lets you control the way we rename services from their
|
||||
service name, to their service type in a friendly manner. This is because most
|
||||
users do not need to know what the name of the service is, just what the
|
||||
service type is. Defaults to:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
SERVICE_TRANSLATIONS = {
|
||||
'cinder': _('Volume'),
|
||||
'neutron': _('Networking'),
|
||||
'nova': _('Compute'),
|
||||
'octavia': _('Load Balancer'),
|
||||
}
|
@ -7,65 +7,11 @@ Adjutant Dashboard
|
||||
* Free software: Apache license
|
||||
* Source: https://github.com/catalyst/adjutant-ui
|
||||
|
||||
Installation instructions
|
||||
=========================
|
||||
|
||||
Begin by cloning the Horizon and Adjutant UI repositories::
|
||||
|
||||
git clone https://github.com/openstack/horizon
|
||||
git clone https://github.com/catalyst/adjutant-ui
|
||||
|
||||
Create a virtual environment and install Horizon dependencies::
|
||||
|
||||
cd horizon
|
||||
python tools/install_venv.py
|
||||
|
||||
Set up your ``local_settings.py`` file::
|
||||
|
||||
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
|
||||
|
||||
Open up the copied ``local_settings.py`` file in your preferred text
|
||||
editor. You will want to customize several settings:
|
||||
|
||||
- ``OPENSTACK_HOST`` should be configured with the hostname of your
|
||||
OpenStack server. Verify that the ``OPENSTACK_KEYSTONE_URL`` and
|
||||
``OPENSTACK_KEYSTONE_DEFAULT_ROLE`` settings are correct for your
|
||||
environment. (They should be correct unless you modified your
|
||||
OpenStack server to change them.)
|
||||
- ``OPENSTACK_REGISTRATION_URL`` should also be configured to point to
|
||||
you Adjutant server and version.
|
||||
|
||||
You will also need to update the ``keystone_policy.json`` file in horizon with
|
||||
the following lines::
|
||||
|
||||
"project_mod": "role:project_mod",
|
||||
"project_admin": "role:project_admin",
|
||||
"project_mod_or_admin": "rule:admin_required or rule:project_mod or rule:project_admin",
|
||||
"project_admin_only": "rule:admin_required or rule:project_admin",
|
||||
"identity:project_users_access": "rule:project_mod_or_admin",
|
||||
|
||||
Install Adjutant UI with all dependencies in your virtual environment::
|
||||
|
||||
tools/with_venv.sh pip install -e ../adjutant-ui/
|
||||
|
||||
And enable it in Horizon::
|
||||
|
||||
cp ../adjutant-ui/enabled/ openstack_dashboard/local/enabled
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
:maxdepth: 1
|
||||
|
||||
releases/*
|
||||
installation
|
||||
configuration
|
||||
|
||||
Source Code Reference
|
||||
=====================
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
sourcecode/autoindex
|
||||
This is the Horizon plugin for the Adjutant service, and provides UI elements
|
||||
to the core features that Adjutant adds.
|
||||
|
40
doc/source/installation.rst
Normal file
40
doc/source/installation.rst
Normal file
@ -0,0 +1,40 @@
|
||||
Installation instructions
|
||||
=========================
|
||||
|
||||
Begin by cloning the Horizon and Adjutant UI repositories::
|
||||
|
||||
git clone https://github.com/openstack/horizon
|
||||
git clone https://github.com/catalyst/adjutant-ui
|
||||
|
||||
Create a virtual environment and install Horizon dependencies::
|
||||
|
||||
cd horizon
|
||||
python tools/install_venv.py
|
||||
|
||||
Set up your ``local_settings.py`` file::
|
||||
|
||||
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
|
||||
|
||||
Open up the copied ``local_settings.py`` file in your preferred text
|
||||
editor. You will want to customize several settings:
|
||||
|
||||
- Verify that the ``OPENSTACK_KEYSTONE_URL`` is correct for your environment.
|
||||
- ``OPENSTACK_REGISTRATION_URL`` should also be configured to point to your
|
||||
Adjutant server and version.
|
||||
|
||||
You will also need to update the ``keystone_policy.json`` file in horizon with
|
||||
the following lines::
|
||||
|
||||
"project_mod": "role:project_mod",
|
||||
"project_admin": "role:project_admin",
|
||||
"project_mod_or_admin": "rule:admin_required or rule:project_mod or rule:project_admin",
|
||||
"project_admin_only": "rule:admin_required or rule:project_admin",
|
||||
"identity:project_users_access": "rule:project_mod_or_admin",
|
||||
|
||||
Install Adjutant UI with all dependencies in your virtual environment::
|
||||
|
||||
tools/with_venv.sh pip install -e ../adjutant-ui/
|
||||
|
||||
And enable it in Horizon::
|
||||
|
||||
cp ../adjutant-ui/enabled/_* openstack_dashboard/local/enabled
|
@ -1,2 +0,0 @@
|
||||
Adjutant UI 0.1.1
|
||||
===============
|
@ -27,3 +27,4 @@ testtools>=1.4.0 # MIT
|
||||
xvfbwrapper>=0.1.3 #license: MIT
|
||||
# Include horizon as test requirement
|
||||
http://tarballs.openstack.org/horizon/horizon-master.tar.gz#egg=horizon
|
||||
sphinx-rtd-theme>=0.2.4
|
||||
|
Loading…
Reference in New Issue
Block a user