[python-django-horizon/f18] Updated patches from f18-patches
Matthias Runge
mrunge at fedoraproject.org
Mon Jan 21 10:23:50 UTC 2013
commit e4a5087d1e8e897bd071a0f0065d7295967da3d4
Author: Matthias Runge <mrunge at redhat.com>
Date: Mon Jan 21 10:26:37 2013 +0100
Updated patches from f18-patches
...-floating-ips-table-action-column-s-width.patch | 26 +++
...-inherit-from-base.html-in-500-error-page.patch | 221 ++++++++++++++++++
0007-Allow-setting-nova-quotas-to-unlimited.patch | 46 ++++
...d-cinder-calls-when-cinder-is-unavailable.patch | 236 ++++++++++++++++++++
...patch => 0009-disable-debug-move-web-root.patch | 0
0010-Add-a-check-for-unlimited-quotas.patch | 90 ++++++++
...-set-mount-point-as-it-s-unsupported-here.patch | 0
...patch => 0012-disable-debug-move-web-root.patch | 2 +-
0013-take-variables-out-of-compressed-output.patch | 26 +++
python-django-horizon.spec | 18 ++-
10 files changed, 662 insertions(+), 3 deletions(-)
---
diff --git a/0005-Specify-floating-ips-table-action-column-s-width.patch b/0005-Specify-floating-ips-table-action-column-s-width.patch
new file mode 100644
index 0000000..17c08b2
--- /dev/null
+++ b/0005-Specify-floating-ips-table-action-column-s-width.patch
@@ -0,0 +1,26 @@
+From 2f959c6efeffad6f4413335dfd3c9e330c3d8e31 Mon Sep 17 00:00:00 2001
+From: Jiang Yong <jiangyong.hn at gmail.com>
+Date: Wed, 5 Dec 2012 18:15:47 +0800
+Subject: [PATCH] Specify floating ips table action column's width
+
+Fixes bug 1081875
+
+Change-Id: Id92a1c7afa829ef2ff8e973919900cf7cb7c59e9
+---
+ openstack_dashboard/static/dashboard/less/horizon.less | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/openstack_dashboard/static/dashboard/less/horizon.less b/openstack_dashboard/static/dashboard/less/horizon.less
+index 0bfe7d7..db788d2 100644
+--- a/openstack_dashboard/static/dashboard/less/horizon.less
++++ b/openstack_dashboard/static/dashboard/less/horizon.less
+@@ -823,6 +823,9 @@ td.actions_column {
+ min-width: 140px;
+ min-height: 20px;
+ }
++#floating_ips td.actions_column {
++ width: 180px;
++}
+
+ td.actions_column .row_actions a,
+ td.actions_column .row_actions input,
diff --git a/0006-Don-t-inherit-from-base.html-in-500-error-page.patch b/0006-Don-t-inherit-from-base.html-in-500-error-page.patch
new file mode 100644
index 0000000..8dbb0a5
--- /dev/null
+++ b/0006-Don-t-inherit-from-base.html-in-500-error-page.patch
@@ -0,0 +1,221 @@
+From 0b1c5536dfd80f071d8e3e92b71dc7eca0b1d325 Mon Sep 17 00:00:00 2001
+From: Matthias Runge <mrunge at redhat.com>
+Date: Wed, 14 Nov 2012 18:30:39 +1100
+Subject: [PATCH] Don't inherit from base.html in 500 error page
+
+For server errors, the context passed to the template is empty,
+so things like STATIC_URL and context processors don't work.
+
+Fixes bug 1067206 for the folsom branch.
+
+This has been adapted to folsom release and is a backport from master.
+
+Change-Id: I5cd60523360d71b088226e4d0f87d88bac8a8df3
+---
+ horizon/templatetags/horizon.py | 6 ++
+ openstack_dashboard/templates/500.html | 103 ++++++++++++++++++++------
+ openstack_dashboard/test/error_pages_urls.py | 7 ++
+ openstack_dashboard/test/tests/error_pages.py | 34 +++++++++
+ openstack_dashboard/urls.py | 5 ++
+ 5 files changed, 131 insertions(+), 24 deletions(-)
+ create mode 100644 openstack_dashboard/test/error_pages_urls.py
+ create mode 100644 openstack_dashboard/test/tests/error_pages.py
+
+diff --git a/horizon/templatetags/horizon.py b/horizon/templatetags/horizon.py
+index 13169d4..f17a252 100644
+--- a/horizon/templatetags/horizon.py
++++ b/horizon/templatetags/horizon.py
+@@ -21,6 +21,7 @@ from django.utils.datastructures import SortedDict
+ from django.utils.translation import ugettext as _
+
+ from horizon.base import Horizon
++from django.conf import settings
+
+
+ register = template.Library()
+@@ -135,3 +136,8 @@ def jstemplate(parser, token):
+ nodelist = parser.parse(('endjstemplate',))
+ parser.delete_first_token()
+ return JSTemplateNode(nodelist)
++
++
++ at register.assignment_tag
++def load_config():
++ return getattr(settings, 'HORIZON_CONFIG', {})
+diff --git a/openstack_dashboard/templates/500.html b/openstack_dashboard/templates/500.html
+index d4d6747..fb51211 100644
+--- a/openstack_dashboard/templates/500.html
++++ b/openstack_dashboard/templates/500.html
+@@ -1,27 +1,82 @@
+-{% extends "base.html" %}
+-{% load i18n %}
++{% load branding i18n staticfiles %}
++{% load load_config from horizon %}
+
+-{% block title %} - {% trans "Internal Server Error" %}{% endblock %}
++{% load_config as HORIZON_CONFIG %}
+
+-{% block content %}
+- <div id="right_content">
+- <div id="page_head">
+- <h2 id="page_heading">{% trans "Internal Server Error" %}</h2>
+- <p id="page_description">{% trans "An unexpected error occurred while processing your request. Please try your request again." %}</p>
++
++{% comment %}
++
++ NB: The context for 500 pages is an empty dict.
++ Don't add any content here that depends on things from
++ the context.
++
++{% endcomment %}
++
++<!DOCTYPE html>
++<html>
++ <head>
++ <meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
++ <link rel="shortcut icon" href="{% static "dashboard/img/favicon.ico" %}"/>
++ <title>{% trans "Server error" %} - {% site_branding %}</title>
++ {% block css %}
++ <style>
++ a {
++ color: #43a1d6;
++ text-decoration: none;
++ }
++ body {
++ color: rgb(106, 106, 106);
++ text-align: center;
++ font-weight: normal;
++ background: none repeat scroll 0% 0% rgb(250, 250, 250);
++ }
++ div#container {
++ position: absolute;
++ top: 80px;
++ padding-top: 170px;
++ margin: 0px 0px 0px -196px;
++ left: 50%;
++ width: 390px;
++
++ background: url("{% static "dashboard/img/logo.png" %}") no-repeat scroll center 35px padding-box rgb(255, 255, 255);
++ border: 1px solid rgb(225, 225, 225);
++
++ -webkit-border-radius: 6px;
++ -moz-border-radius: 6px;
++ border-radius: 6px;
++
++ box-shadow: 0px 3px 7px rgba(0, 0, 0, 0.3);
++ -webkit-box-shadow: 0px 3px 7px rgba(0, 0, 0, 0.3);
++ -moz-box-shadow: 0px 3px 7px rgba(0, 0, 0, 0.3);
++ }
++ h2 {
++ font-weight: normal;
++ }
++ div#container > div {
++ padding: 25px;
++ }
++ </style>
++ {% endblock %}
++ </head>
++ <body id="{% block body_id %}{% endblock %}">
++ {% block page_header %}{% endblock %}
++ {% block content %}
++ <div id="container">
++ <div id="text">
++ {% block text %}
++ <h2>{% trans "Something went wrong!" %}</h2>
++ <p>{% trans "An unexpected error has occurred. Try refreshing the page. If that doesn't help, contact your local administrator." %}</p>
++ {% endblock %}
++ </div>
++ <div id="links">
++ {% block links %}
++ <p><a href="/">{% trans "Home" %}</a></p>
++ <p><a href="{{ HORIZON_CONFIG.help_url }}">{% trans "Help" %}</a></p>
++ {% endblock %}
++ </div>
+ </div>
+- </div>
+-{% endblock %}
+-
+-{% block sidebar %}
+- <div id="sidebar">
+- <ul id="navigation">
+- {% block nav_home %}
+- <li><h3><a href="{% url index %}">{% trans "Home" %}</a></h3></li>
+- {% endblock %}
+-
+- {% block nav_projects %}
+- <li><h3><a href="{% url index %}">{% trans "Projects" %}</a></h3></li>
+- {% endblock %}
+- </ul>
+- </div> <!-- end sidebar -->
+-{% endblock %}
++ {% endblock %}
++ {% block footer %}{% endblock %}
++ {% block js %}{% endblock %}
++ </body>
++</html>
+diff --git a/openstack_dashboard/test/error_pages_urls.py b/openstack_dashboard/test/error_pages_urls.py
+new file mode 100644
+index 0000000..cc28840
+--- /dev/null
++++ b/openstack_dashboard/test/error_pages_urls.py
+@@ -0,0 +1,7 @@
++from django.conf.urls import patterns, url, include
++
++from openstack_dashboard.urls import urlpatterns
++
++urlpatterns += patterns('',
++ (r'^500/$', 'django.views.defaults.server_error')
++)
+diff --git a/openstack_dashboard/test/tests/error_pages.py b/openstack_dashboard/test/tests/error_pages.py
+new file mode 100644
+index 0000000..44cb8da
+--- /dev/null
++++ b/openstack_dashboard/test/tests/error_pages.py
+@@ -0,0 +1,34 @@
++# vim: tabstop=4 shiftwidth=4 softtabstop=4
++
++# Copyright (c) 2012 OpenStack, LLC.
++# All Rights Reserved.
++#
++# 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 os import path
++
++from django.conf import settings
++
++from horizon import exceptions
++from openstack_dashboard.test import helpers as test
++
++
++class ErrorPageTests(test.TestCase):
++ """ Tests for error pages """
++ urls = 'openstack_dashboard.test.error_pages_urls'
++
++ def test_500_error(self):
++ TEMPLATE_DIRS = (path.join(settings.ROOT_PATH, 'templates'),)
++ with self.settings(TEMPLATE_DIRS=TEMPLATE_DIRS):
++ response = self.client.get('/500/')
++ self.assertTrue('Server error' in response.content)
+diff --git a/openstack_dashboard/urls.py b/openstack_dashboard/urls.py
+index 6d1a55e..aa1654d 100644
+--- a/openstack_dashboard/urls.py
++++ b/openstack_dashboard/urls.py
+@@ -42,3 +42,8 @@ urlpatterns += staticfiles_urlpatterns()
+ # development. Only active if DEBUG==True and the URL prefix is a local
+ # path. Production media should NOT be served by Django.
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
++
++if settings.DEBUG:
++ urlpatterns += patterns('',
++ url(r'^500/$', 'django.views.defaults.server_error')
++ )
diff --git a/0007-Allow-setting-nova-quotas-to-unlimited.patch b/0007-Allow-setting-nova-quotas-to-unlimited.patch
new file mode 100644
index 0000000..1eb93b6
--- /dev/null
+++ b/0007-Allow-setting-nova-quotas-to-unlimited.patch
@@ -0,0 +1,46 @@
+From e19a2189fd8c1ea6413e23049152edcce25c304c Mon Sep 17 00:00:00 2001
+From: Joe Gordon <jogo at cloudscaling.com>
+Date: Wed, 9 Jan 2013 12:15:04 -0800
+Subject: [PATCH] Allow setting nova quotas to unlimited
+
+To set a quota to unlimited it is set to -1
+
+Fix bug 1082489
+
+Change-Id: I2e1e53f6a5a33f2b248decc9d94f5a430f383508
+---
+ horizon/dashboards/syspanel/projects/workflows.py | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/horizon/dashboards/syspanel/projects/workflows.py b/horizon/dashboards/syspanel/projects/workflows.py
+index 6d6e81a..e1c6645 100644
+--- a/horizon/dashboards/syspanel/projects/workflows.py
++++ b/horizon/dashboards/syspanel/projects/workflows.py
+@@ -33,16 +33,18 @@ ADD_USER_URL = "horizon:syspanel:projects:create_user"
+
+ class UpdateProjectQuotaAction(workflows.Action):
+ ifcb_label = _("Injected File Content Bytes")
+- metadata_items = forms.IntegerField(min_value=0, label=_("Metadata Items"))
+- cores = forms.IntegerField(min_value=0, label=_("VCPUs"))
+- instances = forms.IntegerField(min_value=0, label=_("Instances"))
+- injected_files = forms.IntegerField(min_value=0, label=_("Injected Files"))
+- injected_file_content_bytes = forms.IntegerField(min_value=0,
++ metadata_items = forms.IntegerField(min_value=-1,
++ label=_("Metadata Items"))
++ cores = forms.IntegerField(min_value=-1, label=_("VCPUs"))
++ instances = forms.IntegerField(min_value=-1, label=_("Instances"))
++ injected_files = forms.IntegerField(min_value=-1,
++ label=_("Injected Files"))
++ injected_file_content_bytes = forms.IntegerField(min_value=-1,
+ label=ifcb_label)
+- volumes = forms.IntegerField(min_value=0, label=_("Volumes"))
+- gigabytes = forms.IntegerField(min_value=0, label=_("Gigabytes"))
+- ram = forms.IntegerField(min_value=0, label=_("RAM (MB)"))
+- floating_ips = forms.IntegerField(min_value=0, label=_("Floating IPs"))
++ volumes = forms.IntegerField(min_value=-1, label=_("Volumes"))
++ gigabytes = forms.IntegerField(min_value=-1, label=_("Gigabytes"))
++ ram = forms.IntegerField(min_value=-1, label=_("RAM (MB)"))
++ floating_ips = forms.IntegerField(min_value=-1, label=_("Floating IPs"))
+
+ class Meta:
+ name = _("Quota")
diff --git a/0008-Avoid-cinder-calls-when-cinder-is-unavailable.patch b/0008-Avoid-cinder-calls-when-cinder-is-unavailable.patch
new file mode 100644
index 0000000..122e1c8
--- /dev/null
+++ b/0008-Avoid-cinder-calls-when-cinder-is-unavailable.patch
@@ -0,0 +1,236 @@
+From 476072d49a41cd8461aa302591f828627760b67e Mon Sep 17 00:00:00 2001
+From: Matthias Runge <mrunge at redhat.com>
+Date: Tue, 18 Dec 2012 14:00:48 +0100
+Subject: [PATCH] Avoid cinder calls, when cinder is unavailable
+
+When a volume service is not available, then a cinder client can not
+be created. This patch skips the calls, so that dashboard doesn't
+break any more.
+
+This is a backport to Folsom release, as this turned out to be a major
+issue.
+Fixes bug 1084137
+
+Change-Id: I8f2f8b0b131b4bb5319d74f6da48671f146d7e00
+---
+ horizon/api/base.py | 9 ++++
+ horizon/api/nova.py | 22 +++++++--
+ .../dashboards/nova/images_and_snapshots/views.py | 14 ++++--
+ horizon/test.py | 10 ++++
+ horizon/tests/api_tests/cinder_tests.py | 56 ++++++++++++++++++++++
+ 5 files changed, 101 insertions(+), 10 deletions(-)
+ create mode 100644 horizon/tests/api_tests/cinder_tests.py
+
+diff --git a/horizon/api/base.py b/horizon/api/base.py
+index 15f9f9e..929221c 100644
+--- a/horizon/api/base.py
++++ b/horizon/api/base.py
+@@ -116,3 +116,12 @@ def url_for(request, service_type, admin=False, endpoint_type=None):
+ raise exceptions.ServiceCatalogException(service_type)
+ else:
+ raise exceptions.ServiceCatalogException(service_type)
++
++
++def is_service_enabled(request, service_type, service_name=None):
++ service = get_service_from_catalog(request.user.service_catalog,
++ service_type)
++ if service and service_name:
++ return service['name'] == service_name
++ else:
++ return service is not None
+diff --git a/horizon/api/nova.py b/horizon/api/nova.py
+index 3bf209f..6861f5a 100644
+--- a/horizon/api/nova.py
++++ b/horizon/api/nova.py
+@@ -210,15 +210,21 @@ def novaclient(request):
+
+ def cinderclient(request):
+ insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
++ cinder_url = ""
++ try:
++ cinder_url = url_for(request, 'volume')
++ except exceptions.ServiceCatalogException:
++ LOG.debug('no volume service configured.')
++ return None
+ LOG.debug('cinderclient connection created using token "%s" and url "%s"' %
+- (request.user.token.id, url_for(request, 'volume')))
++ (request.user.token.id, cinder_url))
+ c = cinder_client.Client(request.user.username,
+ request.user.token.id,
+ project_id=request.user.tenant_id,
+- auth_url=url_for(request, 'volume'),
++ auth_url=cinder_url,
+ insecure=insecure)
+ c.client.auth_token = request.user.token.id
+- c.client.management_url = url_for(request, 'volume')
++ c.client.management_url = cinder_url
+ return c
+
+
+@@ -513,7 +519,10 @@ def volume_list(request, search_opts=None):
+ To see all volumes in the cloud as an admin you can pass in a special
+ search option: {'all_tenants': 1}
+ """
+- return cinderclient(request).volumes.list(search_opts=search_opts)
++ c_client = cinderclient(request)
++ if c_client is None:
++ return []
++ return c_client.volumes.list(search_opts=search_opts)
+
+
+ def volume_get(request, volume_id):
+@@ -565,7 +574,10 @@ def volume_snapshot_get(request, snapshot_id):
+
+
+ def volume_snapshot_list(request):
+- return cinderclient(request).volume_snapshots.list()
++ c_client = cinderclient(request)
++ if c_client is None:
++ return []
++ return c_client.volume_snapshots.list()
+
+
+ def volume_snapshot_create(request, volume_id, name, description):
+diff --git a/horizon/dashboards/nova/images_and_snapshots/views.py b/horizon/dashboards/nova/images_and_snapshots/views.py
+index bade47e..b382265 100644
+--- a/horizon/dashboards/nova/images_and_snapshots/views.py
++++ b/horizon/dashboards/nova/images_and_snapshots/views.py
+@@ -28,6 +28,7 @@ import logging
+ from django.utils.translation import ugettext_lazy as _
+
+ from horizon import api
++from horizon.api.base import is_service_enabled
+ from horizon import exceptions
+ from horizon import tables
+ from horizon import tabs
+@@ -74,12 +75,15 @@ class IndexView(tables.MultiTableView):
+ return snaps
+
+ def get_volume_snapshots_data(self):
+- try:
+- snapshots = api.volume_snapshot_list(self.request)
+- except:
++ if is_service_enabled(self.request, 'volume'):
++ try:
++ snapshots = api.volume_snapshot_list(self.request)
++ except:
++ snapshots = []
++ exceptions.handle(self.request, _("Unable to retrieve "
++ "volume snapshots."))
++ else:
+ snapshots = []
+- exceptions.handle(self.request, _("Unable to retrieve "
+- "volume snapshots."))
+ return snapshots
+
+
+diff --git a/horizon/test.py b/horizon/test.py
+index f2977b1..d6cfa51 100644
+--- a/horizon/test.py
++++ b/horizon/test.py
+@@ -36,6 +36,7 @@ from keystoneclient.v2_0 import client as keystone_client
+ from novaclient.v1_1 import client as nova_client
+ from quantumclient.v2_0 import client as quantum_client
+ from swiftclient import client as swift_client
++from cinderclient import client as cinder_client
+
+ from selenium.webdriver.firefox.webdriver import WebDriver
+
+@@ -293,12 +294,14 @@ class APITestCase(TestCase):
+ self._original_keystoneclient = api.keystone.keystoneclient
+ self._original_novaclient = api.nova.novaclient
+ self._original_quantumclient = api.quantum.quantumclient
++ self._original_cinderclient = api.nova.cinderclient
+
+ # Replace the clients with our stubs.
+ api.glance.glanceclient = lambda request: self.stub_glanceclient()
+ api.keystone.keystoneclient = fake_keystoneclient
+ api.nova.novaclient = lambda request: self.stub_novaclient()
+ api.quantum.quantumclient = lambda request: self.stub_quantumclient()
++ api.nova.cinderclient = lambda request: self.stub_cinderclient()
+
+ def tearDown(self):
+ super(APITestCase, self).tearDown()
+@@ -306,6 +309,7 @@ class APITestCase(TestCase):
+ api.nova.novaclient = self._original_novaclient
+ api.keystone.keystoneclient = self._original_keystoneclient
+ api.quantum.quantumclient = self._original_quantumclient
++ api.nova.cinderclient = self._original_cinderclient
+
+ def stub_novaclient(self):
+ if not hasattr(self, "novaclient"):
+@@ -313,6 +317,12 @@ class APITestCase(TestCase):
+ self.novaclient = self.mox.CreateMock(nova_client.Client)
+ return self.novaclient
+
++ def stub_cinderclient(self):
++ if not hasattr(self, "cinderclient"):
++ self.mox.StubOutWithMock(cinder_client, 'Client')
++ self.cinderclient = self.mox.CreateMock(cinder_client.Client)
++ return self.cinderclient
++
+ def stub_keystoneclient(self):
+ if not hasattr(self, "keystoneclient"):
+ self.mox.StubOutWithMock(keystone_client, 'Client')
+diff --git a/horizon/tests/api_tests/cinder_tests.py b/horizon/tests/api_tests/cinder_tests.py
+new file mode 100644
+index 0000000..ab3ce75
+--- /dev/null
++++ b/horizon/tests/api_tests/cinder_tests.py
+@@ -0,0 +1,56 @@
++# vim: tabstop=4 shiftwidth=4 softtabstop=4
++
++# Copyright 2012 Red Hat, Inc.
++#
++# 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 horizon import api
++from horizon import test
++
++
++class CinderApiTests(test.APITestCase):
++ def test_volume_list(self):
++ search_opts = {'all_tenants': 1}
++ volumes = self.volumes.list()
++ cinderclient = self.stub_cinderclient()
++ cinderclient.volumes = self.mox.CreateMockAnything()
++ cinderclient.volumes.list(search_opts=search_opts,).AndReturn(volumes)
++ self.mox.ReplayAll()
++
++ # No assertions are necessary. Verification is handled by mox.
++ api.nova.volume_list(self.request, search_opts=search_opts)
++
++ def test_volume_snapshot_list(self):
++ volume_snapshots = self.volume_snapshots.list()
++ cinderclient = self.stub_cinderclient()
++ cinderclient.volume_snapshots = self.mox.CreateMockAnything()
++ cinderclient.volume_snapshots.list().AndReturn(volume_snapshots)
++ self.mox.ReplayAll()
++
++ api.nova.volume_snapshot_list(self.request)
++
++ def test_volume_snapshot_list_no_volume_configured(self):
++ # remove volume from service catalog
++ catalog = self.service_catalog
++ for service in catalog:
++ if service["type"] == "volume":
++ self.service_catalog.remove(service)
++ volume_snapshots = self.volume_snapshots.list()
++
++ cinderclient = self.stub_cinderclient()
++ cinderclient.volume_snapshots = self.mox.CreateMockAnything()
++ cinderclient.volume_snapshots.list().AndReturn(volume_snapshots)
++ self.mox.ReplayAll()
++
++ api.nova.volume_snapshot_list(self.request)
diff --git a/0005-disable-debug-move-web-root.patch b/0009-disable-debug-move-web-root.patch
similarity index 100%
copy from 0005-disable-debug-move-web-root.patch
copy to 0009-disable-debug-move-web-root.patch
diff --git a/0010-Add-a-check-for-unlimited-quotas.patch b/0010-Add-a-check-for-unlimited-quotas.patch
new file mode 100644
index 0000000..68238a6
--- /dev/null
+++ b/0010-Add-a-check-for-unlimited-quotas.patch
@@ -0,0 +1,90 @@
+From ebc5e6db042cbd3ba16fc06ddfb8a785dea238cb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Victoria=20Mart=C3=ADnez=20de=20la=20Cruz?=
+ <vickymsee at gmail.com>
+Date: Fri, 11 Jan 2013 17:43:35 -0300
+Subject: [PATCH] Add a check for unlimited quotas
+
+This extra check will prevent Horizon to
+misunderstand "-1" value when tallying quotas,
+setting the "Available" field to inf
+instead of 0.
+
+Change-Id: Idfeb9a10b8ce8eea1a39b3d48dffe08d6450fadd
+Fixes: bug #1084976
+---
+ horizon/api/nova.py | 2 +-
+ horizon/tests/api_tests/nova_tests.py | 51 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 52 insertions(+), 1 deletion(-)
+
+diff --git a/horizon/api/nova.py b/horizon/api/nova.py
+index 3bf209f..43618e2 100644
+--- a/horizon/api/nova.py
++++ b/horizon/api/nova.py
+@@ -455,7 +455,7 @@ def tenant_quota_usages(request):
+
+ usages[usage]['quota'] = getattr(quotas, usage)
+
+- if usages[usage]['quota'] is None:
++ if usages[usage]['quota'] is None or usages[usage]['quota'] == -1:
+ usages[usage]['quota'] = float("inf")
+ usages[usage]['available'] = float("inf")
+ elif type(usages[usage]['quota']) is str:
+diff --git a/horizon/tests/api_tests/nova_tests.py b/horizon/tests/api_tests/nova_tests.py
+index 1952519..5131a3a 100644
+--- a/horizon/tests/api_tests/nova_tests.py
++++ b/horizon/tests/api_tests/nova_tests.py
+@@ -204,3 +204,54 @@ class ComputeApiTests(test.APITestCase):
+ 'quota': 10}}
+
+ self.assertEquals(quota_usages, expected_output)
++
++ @test.create_stubs({api.nova: ('volume_list',
++ 'server_list',
++ 'flavor_list',
++ 'tenant_floating_ip_list',
++ 'tenant_quota_get',)})
++ def test_tenant_quota_usages_unlimited_quota(self):
++ inf_quota = self.quotas.first()
++ inf_quota.ram = -1
++
++ api.nova.flavor_list(IsA(http.HttpRequest)) \
++ .AndReturn(self.flavors.list())
++ api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
++ .AndReturn(inf_quota)
++ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
++ .AndReturn(self.floating_ips.list())
++ api.nova.server_list(IsA(http.HttpRequest)) \
++ .AndReturn(self.servers.list())
++ api.nova.volume_list(IsA(http.HttpRequest)) \
++ .AndReturn(self.volumes.list())
++
++ self.mox.ReplayAll()
++
++ quota_usages = api.tenant_quota_usages(self.request)
++ expected_output = {'gigabytes': {
++ 'used': 80,
++ 'flavor_fields': [],
++ 'quota': 1000},
++ 'ram': {
++ 'available': float("inf"),
++ 'used': 1024,
++ 'flavor_fields': ['ram'],
++ 'quota': float("inf")},
++ 'floating_ips': {
++ 'used': 2,
++ 'flavor_fields': [],
++ 'quota': 1},
++ 'instances': {
++ 'used': 2,
++ 'flavor_fields': [],
++ 'quota': 10},
++ 'volumes': {
++ 'used': 3,
++ 'flavor_fields': [],
++ 'quota': 1},
++ 'cores': {
++ 'used': 2,
++ 'flavor_fields': ['vcpus'],
++ 'quota': 10}}
++
++ self.assertEquals(quota_usages, expected_output)
diff --git a/0006-disable-to-set-mount-point-as-it-s-unsupported-here.patch b/0011-disable-to-set-mount-point-as-it-s-unsupported-here.patch
similarity index 100%
rename from 0006-disable-to-set-mount-point-as-it-s-unsupported-here.patch
rename to 0011-disable-to-set-mount-point-as-it-s-unsupported-here.patch
diff --git a/0005-disable-debug-move-web-root.patch b/0012-disable-debug-move-web-root.patch
similarity index 97%
rename from 0005-disable-debug-move-web-root.patch
rename to 0012-disable-debug-move-web-root.patch
index a390677..8453d80 100644
--- a/0005-disable-debug-move-web-root.patch
+++ b/0012-disable-debug-move-web-root.patch
@@ -1,4 +1,4 @@
-From 43f98c4d393daefa6b45cd5253699676ef877328 Mon Sep 17 00:00:00 2001
+From e852e4afb29bc04567fe77cf0dfa0871215e6181 Mon Sep 17 00:00:00 2001
From: Matthias Runge <mrunge at redhat.com>
Date: Tue, 4 Dec 2012 13:46:22 +0100
Subject: [PATCH] disable debug, move web root
diff --git a/0013-take-variables-out-of-compressed-output.patch b/0013-take-variables-out-of-compressed-output.patch
new file mode 100644
index 0000000..5daf241
--- /dev/null
+++ b/0013-take-variables-out-of-compressed-output.patch
@@ -0,0 +1,26 @@
+From fcd27175f278caebbdaff92553dc1fe3f8957f66 Mon Sep 17 00:00:00 2001
+From: Matthias Runge <mrunge at redhat.com>
+Date: Mon, 21 Jan 2013 10:19:23 +0100
+Subject: [PATCH] take variables out of compressed output
+
+---
+ horizon/templates/horizon/_conf.html | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/horizon/templates/horizon/_conf.html b/horizon/templates/horizon/_conf.html
+index 2dc70fa..2ed6382 100644
+--- a/horizon/templates/horizon/_conf.html
++++ b/horizon/templates/horizon/_conf.html
+@@ -3,6 +3,7 @@
+ {% compress js %}
+ <script src='{{ STATIC_URL }}horizon/js/horizon.js' type='text/javascript' charset='utf-8'></script>
+ <script src='{{ STATIC_URL }}horizon/js/horizon.conf.js' type='text/javascript' charset='utf-8'></script>
++{% endcompress %}
+ <script type='text/javascript' charset='utf-8'>
+ /* Storage for backend configuration variables which the frontend
+ * should be aware of.
+@@ -13,4 +14,3 @@ horizon.conf.ajax = {
+ queue_limit: {{ HORIZON_CONFIG.ajax_queue_limit|default:"null" }}
+ };
+ </script>
+-{% endcompress %}
diff --git a/python-django-horizon.spec b/python-django-horizon.spec
index 68840a1..6803478 100644
--- a/python-django-horizon.spec
+++ b/python-django-horizon.spec
@@ -20,8 +20,15 @@ Patch0001: 0001-Revert-Temp-fix-for-api-keystone.py.patch
Patch0002: 0002-Fix-bug-1055929-Can-not-display-usage-data-for-Quota.patch
Patch0003: 0003-Bump-next-version-to-2012.2.2.patch
Patch0004: 0004-Pin-docutils-to-0.9.1-fix-pep8-errors.patch
-Patch0005: 0005-disable-debug-move-web-root.patch
-Patch0006: 0006-disable-to-set-mount-point-as-it-s-unsupported-here.patch
+Patch0005: 0005-Specify-floating-ips-table-action-column-s-width.patch
+Patch0006: 0006-Don-t-inherit-from-base.html-in-500-error-page.patch
+Patch0007: 0007-Allow-setting-nova-quotas-to-unlimited.patch
+Patch0008: 0008-Avoid-cinder-calls-when-cinder-is-unavailable.patch
+Patch0009: 0009-disable-debug-move-web-root.patch
+Patch0010: 0010-Add-a-check-for-unlimited-quotas.patch
+Patch0011: 0011-disable-to-set-mount-point-as-it-s-unsupported-here.patch
+Patch0012: 0012-disable-debug-move-web-root.patch
+Patch0013: 0013-take-variables-out-of-compressed-output.patch
%if 0%{?rhel}<7 || 0%{?fedora} < 18
@@ -126,6 +133,13 @@ Documentation for the Django Horizon application for talking with Openstack
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
+%patch0007 -p1
+%patch0008 -p1
+%patch0009 -p1
+%patch0010 -p1
+%patch0011 -p1
+%patch0012 -p1
+%patch0013 -p1
# remove unnecessary .po files
find . -name "django*.po" -exec rm -f '{}' \;
More information about the scm-commits
mailing list