summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dev_env.sh56
-rw-r--r--setup.py2
-rw-r--r--test-requirements.txt3
-rw-r--r--tuskar_ui/api/heat.py15
-rw-r--r--tuskar_ui/api/node.py10
-rw-r--r--tuskar_ui/api/tuskar.py2
-rw-r--r--tuskar_ui/infrastructure/overview/forms.py105
-rw-r--r--tuskar_ui/infrastructure/overview/tests.py33
-rw-r--r--tuskar_ui/infrastructure/overview/urls.py3
-rw-r--r--tuskar_ui/infrastructure/overview/views.py44
-rw-r--r--tuskar_ui/infrastructure/parameters/forms.py6
-rw-r--r--tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_live.js17
-rw-r--r--tuskar_ui/infrastructure/templates/infrastructure/_scripts.html1
-rw-r--r--tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_base.html2
-rw-r--r--tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_live.html55
-rw-r--r--tuskar_ui/infrastructure/templates/infrastructure/overview/overcloudrc.sh.template9
-rw-r--r--tuskar_ui/infrastructure/templatetags/context_selection.py41
-rw-r--r--tuskar_ui/utils/utils.py12
18 files changed, 282 insertions, 134 deletions
diff --git a/dev_env.sh b/dev_env.sh
new file mode 100644
index 00000000..020cc2a5
--- /dev/null
+++ b/dev_env.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+set -ex
+
+USAGE="Usage: `basename $0` <undercloud_ip> <undercloud_admin_password>"
+
+if [ "$#" -ne 2 ]; then
+ echo $USAGE
+ exit 1
+fi
+
+UNDERCLOUD_IP=$1
+UNDERCLOUD_ADMIN_PASSWORD=$2
+
+echo "Copying SSH key..."
+cp /home/stack/.ssh/id_rsa /root/.ssh/
+
+echo "Installing system requirements..."
+yum install -y git python-devel swig openssl-devel mysql-devel libxml2-devel libxslt-devel gcc gcc-c++
+easy_install pip nose
+
+echo "Cloning repos..."
+mkdir /opt/stack
+cd /opt/stack
+git clone git://github.com/openstack/horizon.git
+git clone git://github.com/openstack/python-tuskarclient.git
+git clone git://github.com/openstack/tuskar-ui.git
+git clone git://github.com/rdo-management/tuskar-ui-extras.git
+
+echo "Setting up repos..."
+cd horizon
+python tools/install_venv.py
+./run_tests.sh -V
+cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
+tools/with_venv.sh pip install -e ../python-tuskarclient/
+tools/with_venv.sh pip install -e ../tuskar-ui/
+tools/with_venv.sh pip install -e ../tuskar-ui-extras/
+cp ../tuskar-ui/_50_tuskar.py.example openstack_dashboard/local/enabled/_50_tuskar.py
+cp ../tuskar-ui-extras/_60_tuskar_boxes.py.example openstack_dashboard/local/enabled/_60_tuskar_boxes.py
+cp ../tuskar-ui/_10_admin.py.example openstack_dashboard/local/enabled/_10_admin.py
+cp ../tuskar-ui/_20_project.py.example openstack_dashboard/local/enabled/_20_project.py
+cp ../tuskar-ui/_30_identity.py.example openstack_dashboard/local/enabled/_30_identity.py
+sed -i s/'OPENSTACK_HOST = "127.0.0.1"'/'OPENSTACK_HOST = "192.0.2.1"'/ openstack_dashboard/local/local_settings.py
+echo 'IRONIC_DISCOVERD_URL = "http://%s:5050" % OPENSTACK_HOST' >> openstack_dashboard/local/local_settings.py
+echo 'UNDERCLOUD_ADMIN_PASSWORD = "'$UNDERCLOUD_ADMIN_PASSWORD'"' >> openstack_dashboard/local/local_settings.py
+echo 'DEPLOYMENT_MODE = "scale"' >> openstack_dashboard/local/local_settings.py
+
+echo "Setting up networking..."
+sudo ip route replace 192.0.2.0/24 dev virbr0 via $UNDERCLOUD_IP
+
+echo "Setting up iptables on the undercloud..."
+RULE_1="-A INPUT -p tcp -m tcp --dport 8585 -j ACCEPT"
+RULE_2="-A INPUT -p tcp -m tcp --dport 9696 -j ACCEPT"
+RULE_3="-A INPUT -p tcp -m tcp --dport 8777 -j ACCEPT"
+ssh $UNDERCLOUD_IP "sed -i '/$RULE_1/a $RULE_2' /etc/sysconfig/iptables"
+ssh $UNDERCLOUD_IP "sed -i '/$RULE_2/a $RULE_3' /etc/sysconfig/iptables"
+ssh $UNDERCLOUD_IP "service iptables restart"
diff --git a/setup.py b/setup.py
index 056c16c2..d8080d05 100644
--- a/setup.py
+++ b/setup.py
@@ -25,5 +25,5 @@ except ImportError:
pass
setuptools.setup(
- setup_requires=['pbr'],
+ setup_requires=['pbr>=1.3'],
pbr=True)
diff --git a/test-requirements.txt b/test-requirements.txt
index 0eed3c78..bc873bfc 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -20,8 +20,9 @@ http://tarballs.openstack.org/python-tuskarclient/python-tuskarclient-master.tar
coverage>=3.6
django-nose>=1.2
-mock>=1.0
+mock>=1.2
mox>=0.5.3
+mox3>=0.7.0
nodeenv>=0.9.4 # BSD License
nose
nose-exclude
diff --git a/tuskar_ui/api/heat.py b/tuskar_ui/api/heat.py
index 3054ad0d..923565ec 100644
--- a/tuskar_ui/api/heat.py
+++ b/tuskar_ui/api/heat.py
@@ -34,6 +34,7 @@ from tuskar_ui.utils import utils
LOG = logging.getLogger(__name__)
+@memoized.memoized
def overcloud_keystoneclient(request, endpoint, password):
"""Returns a client connected to the Keystone backend.
@@ -428,12 +429,14 @@ class Stack(base.APIResourceWrapper):
if not client:
return []
- services = client.services.list()
-
- for service in services:
- if service.name == 'horizon':
- break
- else:
+ try:
+ services = client.services.list()
+ for service in services:
+ if service.name == 'horizon':
+ break
+ else:
+ return []
+ except Exception:
return []
admin_urls = [endpoint.adminurl for endpoint
diff --git a/tuskar_ui/api/node.py b/tuskar_ui/api/node.py
index 12b037b4..2ad65195 100644
--- a/tuskar_ui/api/node.py
+++ b/tuskar_ui/api/node.py
@@ -11,6 +11,7 @@
# under the License.
import logging
+import time
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
@@ -56,6 +57,7 @@ IRONIC_DISCOVERD_URL = getattr(settings, 'IRONIC_DISCOVERD_URL', None)
LOG = logging.getLogger(__name__)
+@memoized.memoized
def ironicclient(request):
api_version = 1
kwargs = {'os_auth_token': request.user.token.id,
@@ -156,6 +158,7 @@ class Node(base.APIResourceWrapper):
return cls(node, request)
@classmethod
+ @memoized.memoized
@handle_errors(_("Unable to retrieve node"))
def get(cls, request, uuid):
"""Return the Node that matches the ID
@@ -199,6 +202,7 @@ class Node(base.APIResourceWrapper):
return cls(node, request, server)
@classmethod
+ @memoized.memoized
@handle_errors(_("Unable to retrieve nodes"), [])
def list(cls, request, associated=None, maintenance=None):
"""Return a list of Nodes
@@ -263,6 +267,11 @@ class Node(base.APIResourceWrapper):
for uuid in uuids:
discoverd_client.introspect(uuid, IRONIC_DISCOVERD_URL,
request.user.token.id)
+ # NOTE(dtantsur): PXE firmware on virtual machines misbehaves when
+ # a lot of nodes start DHCPing simultaneously: it ignores NACK from
+ # DHCP server, tries to get the same address, then times out. Work
+ # around it by using sleep, anyway introspection takes much longer.
+ time.sleep(5)
@classmethod
def set_maintenance(cls, request, uuid, maintenance):
@@ -302,6 +311,7 @@ class Node(base.APIResourceWrapper):
return cls(node, request)
@classmethod
+ @memoized.memoized
def list_ports(cls, request, uuid):
"""Return a list of ports associated with this Node
diff --git a/tuskar_ui/api/tuskar.py b/tuskar_ui/api/tuskar.py
index 36773340..89244591 100644
--- a/tuskar_ui/api/tuskar.py
+++ b/tuskar_ui/api/tuskar.py
@@ -352,6 +352,7 @@ class Role(base.APIResourceWrapper):
self._request = request
@classmethod
+ @memoized.memoized
@handle_errors(_("Unable to retrieve overcloud roles"), [])
def list(cls, request):
"""Return a list of Overcloud Roles in Tuskar
@@ -367,6 +368,7 @@ class Role(base.APIResourceWrapper):
return [cls(role, request=request) for role in roles]
@classmethod
+ @memoized.memoized
@handle_errors(_("Unable to retrieve overcloud role"))
def get(cls, request, role_id):
"""Return the Tuskar Role that matches the ID
diff --git a/tuskar_ui/infrastructure/overview/forms.py b/tuskar_ui/infrastructure/overview/forms.py
index 115d4064..77ff8c37 100644
--- a/tuskar_ui/infrastructure/overview/forms.py
+++ b/tuskar_ui/infrastructure/overview/forms.py
@@ -13,6 +13,8 @@
# under the License.
import logging
+import six
+import uuid
from django.conf import settings
import django.forms
@@ -20,9 +22,7 @@ from django.utils.translation import ugettext_lazy as _
import horizon.exceptions
import horizon.forms
import horizon.messages
-from neutronclient.common import exceptions as neutron_exceptions
from os_cloud_config import keystone as keystone_config
-from os_cloud_config import neutron as neutron_config
from os_cloud_config.utils import clients
from tuskar_ui import api
@@ -30,6 +30,7 @@ import tuskar_ui.api.heat
import tuskar_ui.api.tuskar
import tuskar_ui.forms
import tuskar_ui.infrastructure.flavors.utils as flavors_utils
+import tuskar_ui.utils.utils as tuskar_utils
MATCHING_DEPLOYMENT_MODE = flavors_utils.matching_deployment_mode()
LOG = logging.getLogger(__name__)
@@ -234,12 +235,54 @@ class EditPlan(horizon.forms.SelfHandlingForm):
# Controllers is > 1
try:
controller_role = self.plan.get_role_by_name('Controller')
+ compute_role = self.plan.get_role_by_name('Compute')
except Exception as e:
- LOG.warning('Unable to find role: %s', 'Controller')
+ LOG.warning('Unable to find a required role: %s', e.message)
else:
- if parameters[controller_role.node_count_parameter_name] > 1:
- l3ha_param = controller_role.parameter_prefix + 'NeutronL3HA'
- parameters[l3ha_param] = 'True'
+ number_controllers = parameters[
+ controller_role.node_count_parameter_name]
+ if number_controllers > 1:
+ for role in [controller_role, compute_role]:
+ l3ha_param = role.parameter_prefix + 'NeutronL3HA'
+ parameters[l3ha_param] = 'True'
+ l3agent_param = (role.parameter_prefix +
+ 'NeutronAllowL3AgentFailover')
+ parameters[l3agent_param] = 'True'
+ dhcp_agents_per_net = (number_controllers if number_controllers and
+ number_controllers > 3 else 3)
+ dhcp_agents_param = (controller_role.parameter_prefix +
+ 'NeutronDhcpAgentsPerNetwork')
+ parameters[dhcp_agents_param] = dhcp_agents_per_net
+
+ try:
+ ceph_storage_role = self.plan.get_role_by_name('Ceph-Storage')
+ except Exception as e:
+ LOG.warning('Unable to find role: %s', 'Ceph-Storage')
+ else:
+ if parameters[ceph_storage_role.node_count_parameter_name] > 0:
+ parameters.update({
+ 'CephClusterFSID': six.text_type(uuid.uuid4()),
+ 'CephMonKey': tuskar_utils.create_cephx_key(),
+ 'CephAdminKey': tuskar_utils.create_cephx_key()
+ })
+
+ cinder_enable_rbd_param = (controller_role.parameter_prefix
+ + 'CinderEnableRbdBackend')
+ glance_backend_param = (controller_role.parameter_prefix +
+ 'GlanceBackend')
+ nova_enable_rbd_param = (compute_role.parameter_prefix +
+ 'NovaEnableRbdBackend')
+ cinder_enable_iscsi_param = (
+ controller_role.parameter_prefix +
+ 'CinderEnableIscsiBackend')
+
+ parameters.update({
+ cinder_enable_rbd_param: True,
+ glance_backend_param: 'rbd',
+ nova_enable_rbd_param: True,
+ cinder_enable_iscsi_param: False
+ })
+
try:
self.plan = self.plan.patch(request, self.plan.uuid, parameters)
except Exception as e:
@@ -360,22 +403,6 @@ class PostDeployInit(horizon.forms.SelfHandlingForm):
label=_("Public Host"), initial="", required=False)
region = horizon.forms.CharField(
label=_("Region"), initial="regionOne")
- float_allocation_start = horizon.forms.CharField(
- label=_("Float Allocation Start"), initial="10.0.0.2")
- float_allocation_end = horizon.forms.CharField(
- label=_("Float Allocation End"), initial="10.255.255.254")
- float_cidr = horizon.forms.CharField(
- label=_("Float CIDR"), initial="10.0.0.0/8")
- overcloud_nameserver = horizon.forms.CharField(
- label=_("Overcloud Nameserver"), initial="8.8.8.8")
- external_allocation_start = horizon.forms.CharField(
- label=_("External Allocation Start"), initial="172.17.0.45")
- external_allocation_end = horizon.forms.CharField(
- label=_("External Allocation End"), initial="172.17.0.64")
- external_cidr = horizon.forms.CharField(
- label=_("External CIDR"), initial="172.17.0.0/16")
- bm_network_gateway = horizon.forms.CharField(
- label=_("Network Gateway"), initial="192.0.2.1")
def build_endpoints(self, plan, controller_role):
return {
@@ -385,6 +412,9 @@ class PostDeployInit(horizon.forms.SelfHandlingForm):
"cinder": {
"password": plan.parameter_value(
controller_role.parameter_prefix + 'CinderPassword')},
+ "cinderv2": {
+ "password": plan.parameter_value(
+ controller_role.parameter_prefix + 'CinderPassword')},
"ec2": {
"password": plan.parameter_value(
controller_role.parameter_prefix + 'GlancePassword')},
@@ -413,25 +443,6 @@ class PostDeployInit(horizon.forms.SelfHandlingForm):
'path': WEBROOT,
'admin_path': '%sadmin' % WEBROOT}}
- def build_neutron_setup(self, data):
- # TODO(lsmola) this is default devtest params, this should probably
- # go from Tuskar parameters in the future.
- return {
- "float": {
- "cidr": data['float_cidr'],
- "name": "default-net",
- "nameserver": data['overcloud_nameserver'],
- "allocation_start": data['float_allocation_start'],
- "allocation_end": data['float_allocation_end']
- },
- "external": {
- "name": "ext-net",
- "allocation_start": data['external_allocation_start'],
- "allocation_end": data['external_allocation_end'],
- "cidr": data['external_cidr'],
- "gateway": data['bm_network_gateway']
- }}
-
def handle(self, request, data):
try:
plan = api.tuskar.Plan.get_the_plan(request)
@@ -457,8 +468,6 @@ class PostDeployInit(horizon.forms.SelfHandlingForm):
# retrieve needed Overcloud clients
keystone_client = clients.get_keystone_client(
auth_user, admin_password, auth_tenant, auth_url)
- neutron_client = clients.get_neutron_client(
- auth_user, admin_password, auth_tenant, auth_url)
# do the setup endpoints
keystone_config.setup_endpoints(
@@ -468,16 +477,6 @@ class PostDeployInit(horizon.forms.SelfHandlingForm):
os_auth_url=auth_url,
client=keystone_client)
- # do the neutron init
- try:
- neutron_config.initialize_neutron(
- self.build_neutron_setup(data),
- neutron_client=neutron_client,
- keystone_client=keystone_client)
- except neutron_exceptions.BadRequest as e:
- LOG.info('Neutron has been already initialized.')
- LOG.info(e.message)
-
except Exception as e:
LOG.exception(e)
horizon.exceptions.handle(request,
diff --git a/tuskar_ui/infrastructure/overview/tests.py b/tuskar_ui/infrastructure/overview/tests.py
index 72697671..20155c86 100644
--- a/tuskar_ui/infrastructure/overview/tests.py
+++ b/tuskar_ui/infrastructure/overview/tests.py
@@ -243,14 +243,6 @@ class OverviewTests(test.BaseAdminViewTests):
'admin_email': "example@example.org",
'public_host': '',
'region': 'regionOne',
- 'float_allocation_start': '10.0.0.2',
- 'float_allocation_end': '10.255.255.254',
- 'float_cidr': '10.0.0.0/8',
- 'external_allocation_start': '192.0.2.45',
- 'external_allocation_end': '192.0.2.64',
- 'external_cidr': '192.0.2.0/24',
- "overcloud_nameserver": '8.8.8.8',
- "bm_network_gateway": '192.0.2.1'
}
with contextlib.nested(
@@ -262,15 +254,10 @@ class OverviewTests(test.BaseAdminViewTests):
return_value=None),
patch('os_cloud_config.keystone.setup_endpoints',
return_value=None),
- patch('os_cloud_config.neutron.initialize_neutron',
- return_value=None),
patch('os_cloud_config.utils.clients.get_keystone_client',
return_value='keystone_client'),
- patch('os_cloud_config.utils.clients.get_neutron_client',
- return_value='neutron_client'),
) as (mock_plan, mock_get_by_plan, mock_initialize,
- mock_setup_endpoints, mock_initialize_neutron,
- mock_get_keystone_client, mock_get_neutron_client):
+ mock_setup_endpoints, mock_get_keystone_client):
res = self.client.post(POST_DEPLOY_INIT_URL, data)
self.assertNoFormErrors(res)
@@ -291,6 +278,7 @@ class OverviewTests(test.BaseAdminViewTests):
'path': '/',
'admin_path': '/admin'},
'cinder': {'password': None},
+ 'cinderv2': {'password': None},
'glance': {'password': None},
'swift': {'password': None,
'path': '/v1/AUTH_%(tenant_id)s',
@@ -301,25 +289,8 @@ class OverviewTests(test.BaseAdminViewTests):
client='keystone_client',
region='regionOne',
public_host='')
- mock_initialize_neutron.assert_called_once_with(
- {'float':
- {'cidr': '10.0.0.0/8',
- 'allocation_start': '10.0.0.2',
- 'name': 'default-net',
- 'allocation_end': '10.255.255.254',
- 'nameserver': '8.8.8.8'},
- 'external':
- {'cidr': '192.0.2.0/24',
- 'allocation_start': '192.0.2.45',
- 'name': 'ext-net',
- 'allocation_end': '192.0.2.64',
- 'gateway': '192.0.2.1'}},
- keystone_client='keystone_client',
- neutron_client='neutron_client')
mock_get_keystone_client.assert_called_once_with(
'admin', None, 'admin', stack.keystone_auth_url)
- mock_get_neutron_client.assert_called_once_with(
- 'admin', None, 'admin', stack.keystone_auth_url)
def test_get_role_data(self):
plan = api.tuskar.Plan(self.tuskarclient_plans.first())
diff --git a/tuskar_ui/infrastructure/overview/urls.py b/tuskar_ui/infrastructure/overview/urls.py
index 6e409a6b..35410d5d 100644
--- a/tuskar_ui/infrastructure/overview/urls.py
+++ b/tuskar_ui/infrastructure/overview/urls.py
@@ -32,4 +32,7 @@ urlpatterns = urls.patterns(
urls.url(r'^scale-out$',
views.ScaleOutView.as_view(),
name='scale_out'),
+ urls.url(r'^download-overcloudrc$',
+ views.download_overcloudrc_file,
+ name='download_overcloudrc'),
)
diff --git a/tuskar_ui/infrastructure/overview/views.py b/tuskar_ui/infrastructure/overview/views.py
index 970725c8..90f9fa37 100644
--- a/tuskar_ui/infrastructure/overview/views.py
+++ b/tuskar_ui/infrastructure/overview/views.py
@@ -13,14 +13,18 @@
# under the License.
import json
+import logging
+import urlparse
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django import http
+from django import shortcuts
import django.utils.text
from django.utils.translation import ugettext_lazy as _
import heatclient
import horizon.forms
+from horizon import messages
from tuskar_ui import api
from tuskar_ui.infrastructure.overview import forms
@@ -29,6 +33,8 @@ from tuskar_ui.infrastructure import views
INDEX_URL = 'horizon:infrastructure:overview:index'
+LOG = logging.getLogger(__name__)
+
def _steps_message(messages):
total_steps = len(messages)
@@ -218,6 +224,10 @@ class IndexView(horizon.forms.ModalFormView, views.StackMixin):
controller_role.parameter_prefix + 'AdminPassword')
context['dashboard_urls'] = stack.dashboard_urls
+ no_proxy = [urlparse.urlparse(url).hostname
+ for url in stack.dashboard_urls]
+ context['no_proxy'] = ",".join(no_proxy)
+ context['auth_url'] = stack.keystone_auth_url
else:
messages = forms.validate_plan(request, plan)
context['plan_messages'] = messages
@@ -344,3 +354,37 @@ class ScaleOutView(horizon.forms.ModalFormView, views.StackMixin):
'plan': plan,
})
return context
+
+
+def _get_openrc_credentials(request):
+ plan = api.tuskar.Plan.get_the_plan(request)
+ stack = api.heat.Stack.get_by_plan(request, plan)
+ no_proxy = [urlparse.urlparse(url).hostname
+ for url in stack.dashboard_urls]
+ controller_role = plan.get_role_by_name("Controller")
+ credentials = dict(tenant_name='admin',
+ auth_url=stack.keystone_auth_url,
+ admin_password=plan.parameter_value(
+ controller_role.parameter_prefix + 'AdminPassword'),
+ no_proxy=",".join(no_proxy))
+ return credentials
+
+
+def download_overcloudrc_file(request):
+ template = 'infrastructure/overview/overcloudrc.sh.template'
+ try:
+ context = _get_openrc_credentials(request)
+
+ response = shortcuts.render(request,
+ template,
+ context,
+ content_type="text/plain")
+ response['Content-Disposition'] = ('attachment; '
+ 'filename="overcloudrc"')
+ response['Content-Length'] = str(len(response.content))
+ return response
+
+ except Exception as e:
+ LOG.exception("Exception in DownloadOvercloudrcForm.")
+ messages.error(request, _('Error Downloading RC File: %s') % e)
+ return shortcuts.redirect(request.build_absolute_uri())
diff --git a/tuskar_ui/infrastructure/parameters/forms.py b/tuskar_ui/infrastructure/parameters/forms.py
index cc31df57..e0c0609d 100644
--- a/tuskar_ui/infrastructure/parameters/forms.py
+++ b/tuskar_ui/infrastructure/parameters/forms.py
@@ -136,7 +136,11 @@ class AdvancedEditServiceConfig(ServiceConfig):
def handle(self, request, data):
plan = api.tuskar.Plan.get_the_plan(self.request)
- data = self._sync_common_params_across_roles(plan, data)
+
+ # TODO(bcrochet): Commenting this out.
+ # For advanced config, we should have a whitelist of which params
+ # must be synced across roles.
+ # data = self._sync_common_params_across_roles(plan, data)
try:
plan.patch(request, plan.uuid, data)
diff --git a/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_live.js b/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_live.js
new file mode 100644
index 00000000..22e4f2f5
--- /dev/null
+++ b/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_live.js
@@ -0,0 +1,17 @@
+tuskar.deployment_live = (function () {
+ 'use strict';
+
+ var module = {};
+
+ module.init = function () {
+ $("#overcloudrc").on("hide.bs.collapse", function(){
+ $("span.overcloudrc").html('Show <i class="fa fa-angle-down"></i>');
+ });
+ $("#overcloudrc").on("show.bs.collapse", function(){
+ $("span.overcloudrc").html('Hide <i class="fa fa-angle-up"></i>');
+ });
+ };
+
+ horizon.addInitFunction(module.init);
+ return module;
+} ());
diff --git a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html
index 61d91811..ff190f01 100644
--- a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html
+++ b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html
@@ -10,6 +10,7 @@
<script src='{{ STATIC_URL }}infrastructure/js/tuskar.edit_plan.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}infrastructure/js/tuskar.deployment_progress.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}infrastructure/js/tuskar.performance.js' type='text/javascript' charset='utf-8'></script>
+ <script src='{{ STATIC_URL }}infrastructure/js/tuskar.deployment_live.js' type='text/javascript' charset='utf-8'></script>
{% endblock %}
{% comment %} Tuskar-UI Client-side Templates (These should *not* be inside the "compress" tag.) {% endcomment %}
diff --git a/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_base.html b/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_base.html
index b8065a6d..04bf8eef 100644
--- a/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_base.html
+++ b/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_base.html
@@ -22,4 +22,6 @@
</div>
</div>
+{% block deployment-overcloudrc %}{% endblock %}
+
{% block templates %}{% endblock %}
diff --git a/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_live.html b/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_live.html
index 9d371641..af6dfa81 100644
--- a/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_live.html
+++ b/tuskar_ui/infrastructure/templates/infrastructure/overview/deployment_live.html
@@ -56,3 +56,58 @@
</a>
{% endblock %}
+
+{% block deployment-overcloudrc %}
+ <div class="clear"></div>
+ <div class="deployment-icon">
+ <i class="fa fa-key fa-3x fa-fw"></i>
+ </div>
+ <div class="deployment-box clearfix">
+ <h4>{% trans "Overcloudrc Information" %}</h4><a data-toggle="collapse" href="#overcloudrc" aria-expanded="false" aria-controls="overcloudrc" id="collapse-rc"><span class='overcloudrc'>{% trans "Show" %}<i class="fa fa-angle-down"></i></span></a>
+ <div class="collapse" id="overcloudrc">
+ <div class="row">
+ <div class="col-xs-4">NOVA_VERSION:</div>
+ <div class="col-xs-8">1.1</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">OS_USERNAME:</div>
+ <div class="col-xs-8">admin</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">OS_PASSWORD:</div>
+ <div class="col-xs-8">{{ admin_password }}</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">OS_AUTH_URL:</div>
+ <div class="col-xs-8">{{ auth_url }}</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">OS_TENANT_NAME:</div>
+ <div class="col-xs-8">admin</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">COMPUTE_API_VERSION:</div>
+ <div class="col-xs-8">1.1</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">OS_NO_CACHE:</div>
+ <div class="col-xs-8">True</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">no_proxy:</div>
+ <div class="col-xs-8">{{ no_proxy }}</div>
+ </div>
+ <div class="row">
+ <div class="col-xs-4">{% trans "Download" %}</div>
+ <div class="col-xs-8">
+ <a
+ href="{% url 'horizon:infrastructure:overview:download_overcloudrc' %}"
+ class="btn btn-default"
+ >
+ <i class="fa fa-lg fa-download"></i> {% trans "Download" %}
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+{% endblock %}
diff --git a/tuskar_ui/infrastructure/templates/infrastructure/overview/overcloudrc.sh.template b/tuskar_ui/infrastructure/templates/infrastructure/overview/overcloudrc.sh.template
new file mode 100644
index 00000000..5977bb37
--- /dev/null
+++ b/tuskar_ui/infrastructure/templates/infrastructure/overview/overcloudrc.sh.template
@@ -0,0 +1,9 @@
+#!/bin/bash
+export NOVA_VERSION=1.1
+export OS_AUTH_URL={{ auth_url }}
+export OS_TENANT_NAME="admin"
+export OS_USERNAME="admin"
+export OS_PASSWORD={{ admin_password }}
+export COMPUTE_API_VERSION=1.1
+export OS_NO_CACHE=True
+export no_proxy={{ no_proxy }}
diff --git a/tuskar_ui/infrastructure/templatetags/context_selection.py b/tuskar_ui/infrastructure/templatetags/context_selection.py
deleted file mode 100644
index 8b29d805..00000000
--- a/tuskar_ui/infrastructure/templatetags/context_selection.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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 __future__ import absolute_import
-
-from django import template
-
-
-register = template.Library()
-
-# Overwrite the selector code from OpenStack Dashboard, so that the
-# selector doesn't appear.
-
-
-@register.simple_tag()
-def show_overview(*args, **kwargs):
- return '<span class="context-overview"></span>'
-
-
-@register.simple_tag()
-def show_domain_list(*args, **kwargs):
- return ''
-
-
-@register.simple_tag()
-def show_project_list(*args, **kwargs):
- return ''
-
-
-@register.simple_tag()
-def show_region_list(*args, **kwargs):
- return ''
diff --git a/tuskar_ui/utils/utils.py b/tuskar_ui/utils/utils.py
index f99d9fda..8921d09b 100644
--- a/tuskar_ui/utils/utils.py
+++ b/tuskar_ui/utils/utils.py
@@ -11,9 +11,13 @@
# 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 base64
import csv
from itertools import izip
+import os
import re
+import struct
+import time
from django.utils.translation import ugettext_lazy as _
@@ -138,3 +142,11 @@ def parse_csv_file(csv_file):
raise ValueError(_("Unknown driver: %s.") % driver)
return parsed_data
+
+
+def create_cephx_key():
+ # NOTE(gfidente): Taken from
+ # https://github.com/ceph/ceph-deploy/blob/master/ceph_deploy/new.py#L21
+ key = os.urandom(16)
+ header = struct.pack("<hiih", 1, int(time.time()), 0, len(key))
+ return base64.b64encode(header + key)