]> review.fuel-infra Code Review - openstack-build/horizon-build.git/commitdiff
Updated to last version of Fix_remaining_Django_1.9_test_failures.patch
authorThomas Goirand <zigo@debian.org>
Mon, 21 Mar 2016 14:08:43 +0000 (15:08 +0100)
committerThomas Goirand <zigo@debian.org>
Mon, 21 Mar 2016 14:08:43 +0000 (15:08 +0100)
Rewritten-From: 0a97594ad3b60a5b0d3c46e70638d6d8bf34d6be

xenial/debian/patches/Fix_remaining_Django_1.9_test_failures.patch

index dce3447752b3d6ec19882915c8365d061cd6322c..39ed60c521e231af81443cd185b70318bb9f46db 100644 (file)
@@ -6,13 +6,13 @@ Co-Authored-By: Itxaka <iserrano@redhat.com>
 Change-Id: Icbc1a3c039de658faa9fba4a2cdd5027345fe94d
 Partially-Implements: blueprint drop-dj17
 Origin: upstream, https://review.openstack.org/#/c/280222/
-Last-Update: 2016-02-19
+Last-Update: 2016-03-21
 
-Index: horizon/horizon/forms/base.py
-===================================================================
---- horizon.orig/horizon/forms/base.py
-+++ horizon/horizon/forms/base.py
-@@ -41,7 +41,7 @@ class SelfHandlingForm(SelfHandlingMixin
+diff --git a/horizon/forms/base.py b/horizon/forms/base.py
+index 5364d38..b54aa63 100644
+--- a/horizon/forms/base.py
++++ b/horizon/forms/base.py
+@@ -41,7 +41,7 @@ class SelfHandlingForm(SelfHandlingMixin, forms.Form):
          wish for API errors to appear as errors on the form rather than
          using the messages framework.
          """
@@ -21,10 +21,26 @@ Index: horizon/horizon/forms/base.py
  
      def set_warning(self, message):
          """Sets a warning on the form.
-Index: horizon/horizon/test/settings.py
-===================================================================
---- horizon.orig/horizon/test/settings.py
-+++ horizon/horizon/test/settings.py
+diff --git a/horizon/forms/views.py b/horizon/forms/views.py
+index f6276e3..ec67cb8 100644
+--- a/horizon/forms/views.py
++++ b/horizon/forms/views.py
+@@ -165,6 +165,11 @@ class ModalFormView(ModalBackdropMixin, ModalFormMixin, views.HorizonFormView):
+         """Returns an instance of the form to be used in this view."""
+         return form_class(self.request, **self.get_form_kwargs())
++    def form_invalid(self, form):
++        context = super(ModalFormView, self).get_context_data()
++        context['form'] = form
++        return self.render_to_response(context)
++
+     def form_valid(self, form):
+         try:
+             handled = form.handle(self.request, form.cleaned_data)
+diff --git a/horizon/test/settings.py b/horizon/test/settings.py
+index e231348..7f5ab99 100644
+--- a/horizon/test/settings.py
++++ b/horizon/test/settings.py
 @@ -59,7 +59,8 @@ INSTALLED_APPS = (
      'horizon',
      'horizon.test',
@@ -35,10 +51,10 @@ Index: horizon/horizon/test/settings.py
  )
  
  MIDDLEWARE_CLASSES = (
-Index: horizon/horizon/test/tests/base.py
-===================================================================
---- horizon.orig/horizon/test/tests/base.py
-+++ horizon/horizon/test/tests/base.py
+diff --git a/horizon/test/tests/base.py b/horizon/test/tests/base.py
+index 12b85e0..53869c1 100644
+--- a/horizon/test/tests/base.py
++++ b/horizon/test/tests/base.py
 @@ -17,6 +17,7 @@
  #    License for the specific language governing permissions and limitations
  #    under the License.
@@ -59,10 +75,10 @@ Index: horizon/horizon/test/tests/base.py
  
          # Set SSL settings for test server
          settings.SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL',
-Index: horizon/horizon/test/tests/forms.py
-===================================================================
---- horizon.orig/horizon/test/tests/forms.py
-+++ horizon/horizon/test/tests/forms.py
+diff --git a/horizon/test/tests/forms.py b/horizon/test/tests/forms.py
+index 16c7cba..7f66415 100644
+--- a/horizon/test/tests/forms.py
++++ b/horizon/test/tests/forms.py
 @@ -27,6 +27,8 @@ class FormMixinTests(test.TestCase):
          view.args = args
          view.kwargs = kwargs
@@ -83,10 +99,10 @@ Index: horizon/horizon/test/tests/forms.py
  
      def _render_form(self):
          return shortcuts.render(self.request, self.template,
-Index: horizon/horizon/test/tests/middleware.py
-===================================================================
---- horizon.orig/horizon/test/tests/middleware.py
-+++ horizon/horizon/test/tests/middleware.py
+diff --git a/horizon/test/tests/middleware.py b/horizon/test/tests/middleware.py
+index 694824b..6328ed5 100644
+--- a/horizon/test/tests/middleware.py
++++ b/horizon/test/tests/middleware.py
 @@ -13,8 +13,8 @@
  #    License for the specific language governing permissions and limitations
  #    under the License.
@@ -109,11 +125,11 @@ Index: horizon/horizon/test/tests/middleware.py
  
      def test_process_response_redirect_on_ajax_request(self):
          url = settings.LOGIN_URL
-Index: horizon/openstack_dashboard/dashboards/admin/networks/tests.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/admin/networks/tests.py
-+++ horizon/openstack_dashboard/dashboards/admin/networks/tests.py
-@@ -390,8 +390,9 @@ class NetworkTests(test.BaseAdminViewTes
+diff --git a/openstack_dashboard/dashboards/admin/networks/tests.py b/openstack_dashboard/dashboards/admin/networks/tests.py
+index 951e22f..e64a4dc 100644
+--- a/openstack_dashboard/dashboards/admin/networks/tests.py
++++ b/openstack_dashboard/dashboards/admin/networks/tests.py
+@@ -390,8 +390,9 @@ class NetworkTests(test.BaseAdminViewTests):
          tenant_id = self.tenants.first().id
          network = self.networks.first()
          extensions = self.api_extensions.list()
@@ -125,7 +141,7 @@ Index: horizon/openstack_dashboard/dashboards/admin/networks/tests.py
          api.neutron.list_extensions(
              IsA(http.HttpRequest)).AndReturn(extensions)
          self.mox.ReplayAll()
-@@ -417,8 +418,11 @@ class NetworkTests(test.BaseAdminViewTes
+@@ -417,8 +418,11 @@ class NetworkTests(test.BaseAdminViewTests):
          tenant_id = self.tenants.first().id
          network = self.networks.first()
          extensions = self.api_extensions.list()
@@ -139,7 +155,7 @@ Index: horizon/openstack_dashboard/dashboards/admin/networks/tests.py
          api.neutron.list_extensions(
              IsA(http.HttpRequest)).AndReturn(extensions)
          self.mox.ReplayAll()
-@@ -447,8 +451,10 @@ class NetworkTests(test.BaseAdminViewTes
+@@ -447,8 +451,10 @@ class NetworkTests(test.BaseAdminViewTests):
          tenant_id = self.tenants.first().id
          network = self.networks.first()
          extensions = self.api_extensions.list()
@@ -152,69 +168,223 @@ Index: horizon/openstack_dashboard/dashboards/admin/networks/tests.py
          api.neutron.list_extensions(
              IsA(http.HttpRequest)).AndReturn(extensions)
          self.mox.ReplayAll()
-Index: horizon/openstack_dashboard/dashboards/admin/volumes/tabs.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/admin/volumes/tabs.py
-+++ horizon/openstack_dashboard/dashboards/admin/volumes/tabs.py
-@@ -35,7 +35,7 @@ class VolumeTab(volumes_tabs.PagedTableM
-     name = _("Volumes")
-     slug = "volumes_tab"
-     template_name = "admin/volumes/volumes/volumes_tables.html"
--    preload = False
-+    preload = True
-     def get_volumes_data(self):
-         volumes = self._get_volumes(search_opts={'all_tenants': True})
-@@ -68,7 +68,7 @@ class VolumeTypesTab(tabs.TableTab, volu
-     name = _("Volume Types")
-     slug = "volume_types_tab"
-     template_name = "admin/volumes/volume_types/volume_types_tables.html"
--    preload = False
-+    preload = True
-     def get_volume_types_data(self):
-         try:
-@@ -115,7 +115,7 @@ class SnapshotTab(volumes_tabs.PagedTabl
-     name = _("Volume Snapshots")
-     slug = "snapshots_tab"
-     template_name = ("horizon/common/_detail_table.html")
--    preload = False
-+    preload = True
-     def get_volume_snapshots_data(self):
-         if cinder.is_volume_service_enabled(self.request):
-Index: horizon/openstack_dashboard/dashboards/admin/volumes/tests.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/admin/volumes/tests.py
-+++ horizon/openstack_dashboard/dashboards/admin/volumes/tests.py
-@@ -180,6 +180,11 @@ class VolumeTests(test.BaseAdminViewTest
-         self.assertItemsEqual(qos_specs, self.cinder_qos_specs.list())
-     @test.create_stubs({cinder: ('volume_list',
-+                                 'volume_list_paged',
-+                                 'volume_snapshot_list',
-+                                 'volume_type_list_with_qos_associations',
-+                                 'volume_encryption_type_list',
-+                                 'qos_spec_list',
-                                  'volume_snapshot_list_paged',),
-                         keystone: ('tenant_list',)})
-     def test_snapshots_tab(self):
-@@ -202,6 +207,11 @@ class VolumeTests(test.BaseAdminViewTest
+diff --git a/openstack_dashboard/dashboards/admin/volumes/tests.py b/openstack_dashboard/dashboards/admin/volumes/tests.py
+index c70d692..c048774 100644
+--- a/openstack_dashboard/dashboards/admin/volumes/tests.py
++++ b/openstack_dashboard/dashboards/admin/volumes/tests.py
+@@ -18,6 +18,7 @@ from django.conf import settings
+ from django.core.urlresolvers import reverse
+ from django import http
+ from django.test.utils import override_settings
++from django.utils.http import urlunquote  # noqa
+ from mox3.mox import IsA  # noqa
+ from openstack_dashboard import api
+@@ -92,7 +93,7 @@ class VolumeTests(test.BaseAdminViewTests):
+         self.mox.ReplayAll()
+-        res = self.client.get(url)
++        res = self.client.get(urlunquote(url))
+         self.assertTemplateUsed(res, 'admin/volumes/index.html')
+         self.assertEqual(res.status_code, 200)
+@@ -190,8 +191,8 @@ class VolumeTests(test.BaseAdminViewTests):
+             .AndReturn(True)
+         self.mox.ReplayAll()
+-        res = self.client.get(reverse(
+-            'horizon:admin:volumes:volume_types_tab'))
++        url = reverse('horizon:admin:volumes:volume_types_tab')
++        res = self.client.get(urlunquote(url))
+         self.assertEqual(res.status_code, 200)
+         self.assertTemplateUsed(
+@@ -216,10 +217,11 @@ class VolumeTests(test.BaseAdminViewTests):
+             AndReturn([self.tenants.list(), False])
+         self.mox.ReplayAll()
+-        res = self.client.get(reverse('horizon:admin:volumes:snapshots_tab'))
++        url = reverse('horizon:admin:volumes:snapshots_tab')
++        res = self.client.get(urlunquote(url))
+         self.assertEqual(res.status_code, 200)
+-        self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
++        self.assertTemplateUsed(res, 'admin/volumes/index.html')
+         snapshots = res.context['volume_snapshots_table'].data
          self.assertItemsEqual(snapshots, self.cinder_volume_snapshots.list())
  
-     @test.create_stubs({cinder: ('volume_list',
-+                                 'volume_list_paged',
-+                                 'volume_snapshot_list',
-+                                 'volume_type_list_with_qos_associations',
-+                                 'volume_encryption_type_list',
-+                                 'qos_spec_list',
-                                  'volume_snapshot_list_paged',),
-                         keystone: ('tenant_list',)})
-     def _test_snapshots_index_paginated(self, marker, sort_dir, snapshots, url,
-Index: horizon/openstack_dashboard/dashboards/project/stacks/forms.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/project/stacks/forms.py
-+++ horizon/openstack_dashboard/dashboards/project/stacks/forms.py
+@@ -240,7 +242,7 @@ class VolumeTests(test.BaseAdminViewTests):
+         self.mox.ReplayAll()
+-        res = self.client.get(url)
++        res = self.client.get(urlunquote(url))
+         self.assertTemplateUsed(res, 'admin/volumes/index.html')
+         self.assertEqual(res.status_code, 200)
+diff --git a/openstack_dashboard/dashboards/identity/ngusers/panel.py b/openstack_dashboard/dashboards/identity/ngusers/panel.py
+index e414284..77c4651 100644
+--- a/openstack_dashboard/dashboards/identity/ngusers/panel.py
++++ b/openstack_dashboard/dashboards/identity/ngusers/panel.py
+@@ -16,14 +16,9 @@ from django.utils.translation import ugettext_lazy as _
+ import horizon
+-from openstack_dashboard.dashboards.identity import dashboard
+-
+ class NGUsers(horizon.Panel):
+     name = _("Users")
+     slug = 'ngusers'
+     policy_rules = (("identity", "identity:get_user"),
+                     ("identity", "identity:list_users"))
+-
+-
+-dashboard.Identity.register(NGUsers)
+diff --git a/openstack_dashboard/dashboards/identity/users/tests.py b/openstack_dashboard/dashboards/identity/users/tests.py
+index 504de15..59356d4 100644
+--- a/openstack_dashboard/dashboards/identity/users/tests.py
++++ b/openstack_dashboard/dashboards/identity/users/tests.py
+@@ -18,6 +18,7 @@
+ from socket import timeout as socket_timeout  # noqa
++import django
+ from django.core.urlresolvers import reverse
+ from django import http
+ from django.test.utils import override_settings
+@@ -228,6 +229,19 @@ class UsersViewTests(test.BaseAdminViewTests):
+         api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+         api.keystone.get_default_role(IgnoreArg()) \
+                     .AndReturn(self.roles.first())
++        if django.VERSION >= (1, 9):
++            if api.keystone.VERSIONS.active >= 3:
++                api.keystone.tenant_list(
++                    IgnoreArg(), domain=domain_id).AndReturn(
++                    [self.tenants.list(), False])
++            else:
++                api.keystone.tenant_list(
++                    IgnoreArg(), user=None).AndReturn(
++                    [self.tenants.list(), False])
++
++            api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
++            api.keystone.get_default_role(IgnoreArg()) \
++                .AndReturn(self.roles.first())
+         self.mox.ReplayAll()
+@@ -268,6 +282,19 @@ class UsersViewTests(test.BaseAdminViewTests):
+         api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+         api.keystone.get_default_role(IgnoreArg()) \
+                     .AndReturn(self.roles.first())
++        if django.VERSION >= (1, 9):
++            if api.keystone.VERSIONS.active >= 3:
++                api.keystone.tenant_list(
++                    IgnoreArg(), domain=domain_id).AndReturn(
++                    [self.tenants.list(), False])
++            else:
++                api.keystone.tenant_list(
++                    IgnoreArg(), user=None).AndReturn(
++                    [self.tenants.list(), False])
++
++            api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
++            api.keystone.get_default_role(IgnoreArg()) \
++                .AndReturn(self.roles.first())
+         self.mox.ReplayAll()
+@@ -311,6 +338,19 @@ class UsersViewTests(test.BaseAdminViewTests):
+         api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+         api.keystone.get_default_role(IgnoreArg()) \
+                     .AndReturn(self.roles.first())
++        if django.VERSION >= (1, 9):
++            if api.keystone.VERSIONS.active >= 3:
++                api.keystone.tenant_list(
++                    IgnoreArg(), domain=domain_id).AndReturn(
++                    [self.tenants.list(), False])
++            else:
++                api.keystone.tenant_list(
++                    IgnoreArg(), user=None).AndReturn(
++                    [self.tenants.list(), False])
++
++            api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
++            api.keystone.get_default_role(IgnoreArg()) \
++                .AndReturn(self.roles.first())
+         self.mox.ReplayAll()
+diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py
+index bef6b3c..bcfe3a8 100644
+--- a/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py
++++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py
+@@ -18,6 +18,7 @@
+ import cgi
++import django
+ from django.conf import settings
+ from django.core.urlresolvers import reverse
+ from django import http
+@@ -410,6 +411,12 @@ class SecurityGroupsViewTests(test.TestCase):
+             IsA(http.HttpRequest)).AndReturn(self.secgroup_backend)
+         api.network.security_group_list(
+             IsA(http.HttpRequest)).AndReturn(sec_group_list)
++        if django.VERSION >= (1, 9):
++            api.network.security_group_backend(
++                IsA(http.HttpRequest)).AndReturn(self.secgroup_backend)
++            api.network.security_group_list(
++                IsA(http.HttpRequest)).AndReturn(sec_group_list)
++
+         self.mox.ReplayAll()
+         formData = {'method': 'AddRule',
+@@ -435,6 +442,13 @@ class SecurityGroupsViewTests(test.TestCase):
+                 IsA(http.HttpRequest)).AndReturn(self.secgroup_backend)
+             api.network.security_group_list(
+                 IsA(http.HttpRequest)).AndReturn(sec_group_list)
++        if django.VERSION >= (1, 9):
++            for i in range(3):
++                api.network.security_group_backend(
++                    IsA(http.HttpRequest)).AndReturn(self.secgroup_backend)
++                api.network.security_group_list(
++                    IsA(http.HttpRequest)).AndReturn(sec_group_list)
++
+         self.mox.ReplayAll()
+         formData = {'method': 'AddRule',
+@@ -490,6 +504,13 @@ class SecurityGroupsViewTests(test.TestCase):
+             api.network.security_group_list(
+                 IsA(http.HttpRequest)).AndReturn(sec_group_list)
++        if django.VERSION >= (1, 9):
++            for i in range(4):
++                api.network.security_group_backend(
++                    IsA(http.HttpRequest)).AndReturn(self.secgroup_backend)
++                api.network.security_group_list(
++                    IsA(http.HttpRequest)).AndReturn(sec_group_list)
++
+         self.mox.ReplayAll()
+         formData = {'method': 'AddRule',
+diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py
+index 11210d6..2598403 100644
+--- a/openstack_dashboard/dashboards/project/instances/tests.py
++++ b/openstack_dashboard/dashboards/project/instances/tests.py
+@@ -4511,7 +4511,8 @@ class InstanceTests(helpers.TestCase):
+                                           confirm_password=pass2,
+                                           disk_config='MANUAL')
+-        self.assertContains(res, "Passwords do not match.")
++        self.assertEqual(res.context['form'].errors['__all__'],
++                         ["Passwords do not match."])
+     @helpers.create_stubs(instance_rebuild_post_stubs)
+     def test_rebuild_instance_post_with_empty_string(self):
+diff --git a/openstack_dashboard/dashboards/project/stacks/forms.py b/openstack_dashboard/dashboards/project/stacks/forms.py
+index a42f079..f7dcf51 100644
+--- a/openstack_dashboard/dashboards/project/stacks/forms.py
++++ b/openstack_dashboard/dashboards/project/stacks/forms.py
 @@ -13,6 +13,7 @@
  import json
  import logging
@@ -223,7 +393,7 @@ Index: horizon/openstack_dashboard/dashboards/project/stacks/forms.py
  from django.conf import settings
  from django.utils import html
  from django.utils.translation import ugettext_lazy as _
-@@ -125,6 +126,13 @@ class TemplateForm(forms.SelfHandlingFor
+@@ -125,6 +126,13 @@ class TemplateForm(forms.SelfHandlingForm):
          widget=forms.widgets.Textarea(attrs=attributes),
          required=False)
  
@@ -237,7 +407,7 @@ Index: horizon/openstack_dashboard/dashboards/project/stacks/forms.py
      def __init__(self, *args, **kwargs):
          self.next_view = kwargs.pop('next_view')
          super(TemplateForm, self).__init__(*args, **kwargs)
-@@ -252,6 +260,12 @@ class CreateStackForm(forms.SelfHandling
+@@ -252,6 +260,12 @@ class CreateStackForm(forms.SelfHandlingForm):
      environment_data = forms.CharField(
          widget=forms.widgets.HiddenInput,
          required=False)
@@ -250,11 +420,22 @@ Index: horizon/openstack_dashboard/dashboards/project/stacks/forms.py
      parameters = forms.CharField(
          widget=forms.widgets.HiddenInput)
      stack_name = forms.RegexField(
-Index: horizon/openstack_dashboard/dashboards/project/volumes/backups/tests.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/project/volumes/backups/tests.py
-+++ horizon/openstack_dashboard/dashboards/project/volumes/backups/tests.py
-@@ -70,21 +70,17 @@ class VolumeBackupsViewTests(test.TestCa
+diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html
+index b418edc..12d131a 100644
+--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html
++++ b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html
+@@ -54,5 +54,5 @@
+ {% endblock %}
+ {% block modal-footer %}
+-  <a href="{% url 'horizon:project:stack:index' %}" class="btn btn-default cancel">{% trans "Close" %}</a>
++  <a href="{% url 'horizon:project:stacks:index' %}" class="btn btn-default cancel">{% trans "Close" %}</a>
+ {% endblock %}
+diff --git a/openstack_dashboard/dashboards/project/volumes/backups/tests.py b/openstack_dashboard/dashboards/project/volumes/backups/tests.py
+index 4e5e357..389e909 100644
+--- a/openstack_dashboard/dashboards/project/volumes/backups/tests.py
++++ b/openstack_dashboard/dashboards/project/volumes/backups/tests.py
+@@ -70,21 +70,17 @@ class VolumeBackupsViewTests(test.TestCase):
              AndReturn(volumes)
          api.cinder.volume_backup_delete(IsA(http.HttpRequest), backup.id)
  
@@ -280,11 +461,11 @@ Index: horizon/openstack_dashboard/dashboards/project/volumes/backups/tests.py
  
      @test.create_stubs({api.cinder: ('volume_backup_get', 'volume_get')})
      def test_volume_backup_detail_get(self):
-Index: horizon/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
-+++ horizon/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
-@@ -108,7 +108,8 @@ class VolumeSnapshotsViewTests(test.Test
+diff --git a/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py b/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
+index a8cc741..d7975b5 100644
+--- a/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
++++ b/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
+@@ -108,7 +108,8 @@ class VolumeSnapshotsViewTests(test.TestCase):
      @test.create_stubs({api.cinder: ('volume_snapshot_list_paged',
                                       'volume_list',
                                       'volume_backup_supported',
@@ -294,7 +475,7 @@ Index: horizon/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
      def test_delete_volume_snapshot(self):
          vol_snapshots = self.cinder_volume_snapshots.list()
          volumes = self.cinder_volumes.list()
-@@ -123,19 +124,14 @@ class VolumeSnapshotsViewTests(test.Test
+@@ -123,19 +124,14 @@ class VolumeSnapshotsViewTests(test.TestCase):
              AndReturn(volumes)
  
          api.cinder.volume_snapshot_delete(IsA(http.HttpRequest), snapshot.id)
@@ -317,87 +498,323 @@ Index: horizon/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py
  
      @test.create_stubs({api.cinder: ('volume_snapshot_get', 'volume_get')})
      def test_volume_snapshot_detail_get(self):
-Index: horizon/openstack_dashboard/dashboards/project/volumes/tabs.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/project/volumes/tabs.py
-+++ horizon/openstack_dashboard/dashboards/project/volumes/tabs.py
-@@ -119,7 +119,7 @@ class VolumeTab(PagedTableMixin, tabs.Ta
-     name = _("Volumes")
-     slug = "volumes_tab"
-     template_name = ("horizon/common/_detail_table.html")
--    preload = False
-+    preload = True
-     def get_volumes_data(self):
-         volumes = self._get_volumes()
-@@ -135,7 +135,7 @@ class SnapshotTab(PagedTableMixin, tabs.
-     name = _("Volume Snapshots")
-     slug = "snapshots_tab"
-     template_name = ("horizon/common/_detail_table.html")
--    preload = False
-+    preload = True
-     def get_volume_snapshots_data(self):
-         snapshots = []
-@@ -156,7 +156,6 @@ class SnapshotTab(PagedTableMixin, tabs.
-         for snapshot in snapshots:
-             volume = volumes.get(snapshot.volume_id)
-             setattr(snapshot, '_volume', volume)
--
-         return snapshots
-@@ -165,7 +164,7 @@ class BackupsTab(PagedTableMixin, tabs.T
-     name = _("Volume Backups")
-     slug = "backups_tab"
-     template_name = ("horizon/common/_detail_table.html")
--    preload = False
-+    preload = True
-     def allowed(self, request):
-         return api.cinder.volume_backup_supported(self.request)
-Index: horizon/openstack_dashboard/dashboards/project/volumes/test.py
-===================================================================
---- horizon.orig/openstack_dashboard/dashboards/project/volumes/test.py
-+++ horizon/openstack_dashboard/dashboards/project/volumes/test.py
-@@ -191,12 +191,22 @@ class VolumeAndSnapshotsAndBackupsTests(
-                                      'volume_snapshot_list_paged',
-                                      'volume_list',
-                                      'volume_backup_supported',
-+                                     'volume_snapshot_list',
-+                                     'volume_type_list_with_qos_associations',
-+                                     'volume_encryption_type_list',
-+                                     'qos_spec_list',
-+                                     'volume_snapshot_list_paged'
-+                                     'volume_snapshot_list',
-+                                     'volume_type_list_with_qos_associations',
-+                                     'volume_encryption_type_list',
-+                                     'qos_spec_list',
-                                      ),
-                         api.nova: ('server_list',)})
-     def _test_snapshots_index_paginated(self, marker, sort_dir, snapshots, url,
-                                         has_more, has_prev):
-         backup_supported = True
--
-+        api.cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
-+            MultipleTimes().AndReturn(self.cinder_limits['absolute'])
-         api.cinder.volume_backup_supported(IsA(http.HttpRequest)).\
-             MultipleTimes().AndReturn(backup_supported)
-         api.cinder.volume_snapshot_list_paged(
-@@ -285,7 +295,8 @@ class VolumeAndSnapshotsAndBackupsTests(
-     def _test_backups_index_paginated(self, marker, sort_dir, backups, url,
-                                       has_more, has_prev):
-         backup_supported = True
+diff --git a/openstack_dashboard/dashboards/project/volumes/test.py b/openstack_dashboard/dashboards/project/volumes/test.py
+index b632fbd..1f3ef4a 100644
+--- a/openstack_dashboard/dashboards/project/volumes/test.py
++++ b/openstack_dashboard/dashboards/project/volumes/test.py
+@@ -18,6 +18,7 @@ from django.conf import settings
+ from django.core.urlresolvers import reverse
+ from django import http
+ from django.test.utils import override_settings
++from django.utils.http import urlunquote  # noqa
+ from mox3.mox import IsA  # noqa
+@@ -32,8 +33,10 @@ from openstack_dashboard.test import helpers as test
+ INDEX_URL = reverse('horizon:project:volumes:index')
+-VOLUME_SNAPSHOTS_TAB_URL = reverse('horizon:project:volumes:snapshots_tab')
+-VOLUME_BACKUPS_TAB_URL = reverse('horizon:project:volumes:backups_tab')
++VOLUME_SNAPSHOTS_TAB_URL = urlunquote(reverse(
++    'horizon:project:volumes:snapshots_tab'))
++VOLUME_BACKUPS_TAB_URL = urlunquote(reverse(
++    'horizon:project:volumes:backups_tab'))
+ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
+@@ -126,7 +129,7 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
+             AndReturn(self.cinder_limits['absolute'])
+         self.mox.ReplayAll()
+-        res = self.client.get(url)
++        res = self.client.get(urlunquote(url))
+         self.assertEqual(res.status_code, 200)
+         self.assertTemplateUsed(res, 'project/volumes/index.html')
+@@ -223,7 +226,7 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
+             self.cinder_volumes.list())
+         self.mox.ReplayAll()
+-        res = self.client.get(url)
++        res = self.client.get(urlunquote(url))
+         self.assertEqual(res.status_code, 200)
+         self.assertTemplateUsed(res, 'project/volumes/index.html')
+@@ -312,7 +315,7 @@ class VolumeAndSnapshotsAndBackupsTests(test.TestCase):
+             self.cinder_volumes.list())
+         self.mox.ReplayAll()
+-        res = self.client.get(url)
++        res = self.client.get(urlunquote(url))
+         self.assertEqual(res.status_code, 200)
+         self.assertTemplateUsed(res, 'project/volumes/index.html')
+diff --git a/openstack_dashboard/dashboards/project/volumes/volumes/tests.py b/openstack_dashboard/dashboards/project/volumes/volumes/tests.py
+index 3eac769..0e07ba8 100644
+--- a/openstack_dashboard/dashboards/project/volumes/volumes/tests.py
++++ b/openstack_dashboard/dashboards/project/volumes/volumes/tests.py
+@@ -16,10 +16,12 @@
+ #    License for the specific language governing permissions and limitations
+ #    under the License.
++import django
+ from django.core.urlresolvers import reverse
+ from django.forms import widgets
+ from django import http
+ from django.test.utils import override_settings
++from django.utils.http import urlunquote  # noqa
+ from mox3.mox import IsA  # noqa
+ import six
+@@ -32,7 +34,8 @@ from openstack_dashboard.usage import quotas
+ VOLUME_INDEX_URL = reverse('horizon:project:volumes:index')
+-VOLUME_VOLUMES_TAB_URL = reverse('horizon:project:volumes:volumes_tab')
++VOLUME_VOLUMES_TAB_URL = urlunquote(reverse(
++    'horizon:project:volumes:volumes_tab'))
+ SEARCH_OPTS = dict(status=api.cinder.VOLUME_STATE_AVAILABLE)
+@@ -472,8 +475,9 @@ class VolumeViewTests(test.TestCase):
+         cinder.volume_type_list(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.list())
+-        cinder.volume_type_list(IsA(http.HttpRequest)).\
+-            AndReturn(self.volume_types.list())
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_list(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.list())
+         cinder.volume_type_default(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.first())
+         quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+@@ -482,9 +486,13 @@ class VolumeViewTests(test.TestCase):
+                                    str(snapshot.id)).AndReturn(snapshot)
+         cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id).\
+             AndReturn(self.cinder_volumes.first())
 -
-+        api.cinder.tenant_absolute_limits(IsA(http.HttpRequest)).\
-+            MultipleTimes().AndReturn(self.cinder_limits['absolute'])
-         api.cinder.volume_backup_supported(IsA(http.HttpRequest)).\
-             MultipleTimes().AndReturn(backup_supported)
-         api.cinder.volume_backup_list_paged(
-Index: horizon/openstack_dashboard/settings.py
-===================================================================
---- horizon.orig/openstack_dashboard/settings.py
-+++ horizon/openstack_dashboard/settings.py
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_default(IsA(http.HttpRequest)). \
++                AndReturn(self.volume_types.first())
++            cinder.volume_snapshot_get(IsA(http.HttpRequest),
++                                       str(snapshot.id)).AndReturn(snapshot)
++            cinder.volume_get(IsA(http.HttpRequest), snapshot.volume_id). \
++                AndReturn(self.cinder_volumes.first())
+         self.mox.ReplayAll()
+@@ -649,8 +657,9 @@ class VolumeViewTests(test.TestCase):
+         cinder.volume_type_list(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.list())
+-        cinder.volume_type_list(IsA(http.HttpRequest)).\
+-            AndReturn(self.volume_types.list())
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_list(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.list())
+         cinder.volume_type_default(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.first())
+         quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+@@ -661,8 +670,15 @@ class VolumeViewTests(test.TestCase):
+             .AndReturn(True)
+         cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
+             self.cinder_availability_zones.list())
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_default(IsA(http.HttpRequest)). \
++                AndReturn(self.volume_types.first())
++            api.glance.image_get(IsA(http.HttpRequest),
++                                 str(image.id)).AndReturn(image)
++            cinder.extension_supported(IsA(http.HttpRequest),
++                                       'AvailabilityZones').AndReturn(True)
++            cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
++                self.cinder_availability_zones.list())
+         self.mox.ReplayAll()
+@@ -696,8 +712,9 @@ class VolumeViewTests(test.TestCase):
+         cinder.volume_type_list(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.list())
+-        cinder.volume_type_list(IsA(http.HttpRequest)).\
+-            AndReturn(self.volume_types.list())
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_list(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.list())
+         cinder.volume_type_default(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.first())
+         quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+@@ -708,8 +725,15 @@ class VolumeViewTests(test.TestCase):
+             .AndReturn(True)
+         cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
+             self.cinder_availability_zones.list())
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_default(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.first())
++            api.glance.image_get(IsA(http.HttpRequest),
++                                 str(image.id)).AndReturn(image)
++            cinder.extension_supported(IsA(http.HttpRequest),
++                                       'AvailabilityZones').AndReturn(True)
++            cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
++                self.cinder_availability_zones.list())
+         self.mox.ReplayAll()
+@@ -753,8 +777,9 @@ class VolumeViewTests(test.TestCase):
+         cinder.volume_type_list(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.list())
+-        cinder.volume_type_list(IsA(http.HttpRequest)).\
+-            AndReturn(self.volume_types.list())
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_list(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.list())
+         cinder.volume_type_default(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.first())
+         quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+@@ -778,8 +803,29 @@ class VolumeViewTests(test.TestCase):
+             .AndReturn(True)
+         cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
+             self.cinder_availability_zones.list())
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_default(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.first())
++            cinder.volume_snapshot_list(IsA(http.HttpRequest),
++                                        search_opts=SEARCH_OPTS). \
++                AndReturn(self.cinder_volume_snapshots.list())
++            api.glance.image_list_detailed(
++                IsA(http.HttpRequest),
++                filters={'is_public': True, 'status': 'active'}) \
++                .AndReturn([self.images.list(), False, False])
++            api.glance.image_list_detailed(
++                IsA(http.HttpRequest),
++                filters={'property-owner_id': self.tenant.id,
++                         'status': 'active'}) \
++                .AndReturn([[], False, False])
++            cinder.volume_list(IsA(
++                http.HttpRequest),
++                search_opts=SEARCH_OPTS).AndReturn(self.cinder_volumes.list())
++            cinder.extension_supported(IsA(http.HttpRequest),
++                                       'AvailabilityZones') \
++                .AndReturn(True)
++            cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
++                self.cinder_availability_zones.list())
+         self.mox.ReplayAll()
+@@ -810,8 +856,9 @@ class VolumeViewTests(test.TestCase):
+         cinder.volume_type_list(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.list())
+-        cinder.volume_type_list(IsA(http.HttpRequest)).\
+-            AndReturn(self.volume_types.list())
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_list(IsA(http.HttpRequest)).\
++                AndReturn(self.volume_types.list())
+         cinder.volume_type_default(IsA(http.HttpRequest)).\
+             AndReturn(self.volume_types.first())
+         quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+@@ -835,8 +882,29 @@ class VolumeViewTests(test.TestCase):
+             .AndReturn(True)
+         cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
+             self.cinder_availability_zones.list())
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
++        if django.VERSION >= (1, 9):
++            cinder.volume_type_default(IsA(http.HttpRequest)). \
++                AndReturn(self.volume_types.first())
++            cinder.volume_snapshot_list(IsA(http.HttpRequest),
++                                        search_opts=SEARCH_OPTS). \
++                AndReturn(self.cinder_volume_snapshots.list())
++            api.glance.image_list_detailed(
++                IsA(http.HttpRequest),
++                filters={'is_public': True, 'status': 'active'}) \
++                .AndReturn([self.images.list(), False, False])
++            api.glance.image_list_detailed(
++                IsA(http.HttpRequest),
++                filters={'property-owner_id': self.tenant.id,
++                         'status': 'active'}) \
++                .AndReturn([[], False, False])
++            cinder.volume_list(IsA(
++                http.HttpRequest),
++                search_opts=SEARCH_OPTS).AndReturn(self.cinder_volumes.list())
++            cinder.extension_supported(IsA(http.HttpRequest),
++                                       'AvailabilityZones') \
++                .AndReturn(True)
++            cinder.availability_zone_list(IsA(http.HttpRequest)).AndReturn(
++                self.cinder_availability_zones.list())
+         self.mox.ReplayAll()
+@@ -1434,18 +1502,12 @@ class VolumeViewTests(test.TestCase):
+                         quotas: ('tenant_limit_usages',)})
+     def test_extend_volume_with_wrong_size(self):
+         volume = self.cinder_volumes.first()
+-        usage_limit = {'maxTotalVolumeGigabytes': 100,
+-                       'gigabytesUsed': 20,
+-                       'volumesUsed': len(self.cinder_volumes.list()),
+-                       'maxTotalVolumes': 6}
+         formData = {'name': u'A Volume I Am Making',
+                     'orig_size': volume.size,
+                     'new_size': 10}
+         cinder.volume_get(IsA(http.HttpRequest), volume.id).\
+             AndReturn(self.cinder_volumes.first())
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
+         self.mox.ReplayAll()
+@@ -1574,8 +1636,6 @@ class VolumeViewTests(test.TestCase):
+             AndReturn(usage_limit)
+         cinder.volume_get(IsA(http.HttpRequest), volume.id).\
+             AndReturn(self.volumes.first())
+-        quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
+-            AndReturn(usage_limit)
+         self.mox.ReplayAll()
+diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py
+index 69ab6d0..3e8a588 100644
+--- a/openstack_dashboard/settings.py
++++ b/openstack_dashboard/settings.py
+@@ -28,6 +28,7 @@ from openstack_dashboard import exceptions
+ from openstack_dashboard.static_settings import find_static_files  # noqa
+ from openstack_dashboard.static_settings import get_staticfiles_dirs  # noqa
+ from openstack_dashboard import theme_settings
++from openstack_dashboard.utils import settings
+ warnings.formatwarning = lambda message, category, *args, **kwargs: \
+@@ -299,10 +300,10 @@ if os.path.exists(LOCAL_SETTINGS_DIR_PATH):
+         for filename in sorted(filenames):
+             if filename.endswith(".py"):
+                 try:
+-                    execfile(os.path.join(dirpath, filename))
++                    settings.execfile_schim(os.path.join(dirpath, filename))
+                 except Exception as e:
+                     logging.exception(
+-                        "Can not exec settings snippet %s" % (filename))
++                        "Can not exec settings snippet %s" % filename)
+ if not WEBROOT.endswith('/'):
+@@ -363,7 +364,6 @@ if not SECRET_KEY:
+ # Load the pluggable dashboard settings
+ import openstack_dashboard.enabled
+ import openstack_dashboard.local.enabled
+-from openstack_dashboard.utils import settings
+ INSTALLED_APPS = list(INSTALLED_APPS)  # Make sure it's mutable
+ settings.update_dashboards(
 @@ -376,8 +376,14 @@ settings.update_dashboards(
  )
  INSTALLED_APPS[0:0] = ADD_INSTALLED_APPS
@@ -415,7 +832,7 @@ Index: horizon/openstack_dashboard/settings.py
  
  # This base context objects gets added to the offline context generator
  # for each theme configured.
-@@ -392,11 +398,14 @@ COMPRESS_OFFLINE_CONTEXT = 'horizon.them
+@@ -392,11 +398,14 @@ COMPRESS_OFFLINE_CONTEXT = 'horizon.themes.offline_context'
  if DEBUG:
      logging.basicConfig(level=logging.DEBUG)
  
@@ -432,10 +849,10 @@ Index: horizon/openstack_dashboard/settings.py
 +# auth_utils.patch_middleware_get_user()
  
  CSRF_COOKIE_AGE = None
-Index: horizon/openstack_dashboard/test/helpers.py
-===================================================================
---- horizon.orig/openstack_dashboard/test/helpers.py
-+++ horizon/openstack_dashboard/test/helpers.py
+diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py
+index dfca1e9..2336bfd 100644
+--- a/openstack_dashboard/test/helpers.py
++++ b/openstack_dashboard/test/helpers.py
 @@ -29,6 +29,7 @@ from django.core.handlers import wsgi
  from django.core import urlresolvers
  from django.test.client import RequestFactory  # noqa
@@ -444,7 +861,7 @@ Index: horizon/openstack_dashboard/test/helpers.py
  
  from ceilometerclient.v2 import client as ceilometer_client
  from cinderclient import client as cinder_client
-@@ -232,8 +233,10 @@ class TestCase(horizon_helpers.TestCase)
+@@ -232,8 +233,10 @@ class TestCase(horizon_helpers.TestCase):
          processing the view which is redirected to.
          """
          if django.VERSION >= (1, 9):
@@ -457,3 +874,20 @@ Index: horizon/openstack_dashboard/test/helpers.py
          else:
              self.assertEqual(response._headers.get('location', None),
                               ('Location', settings.TESTSERVER + expected_url))
+diff --git a/openstack_dashboard/utils/settings.py b/openstack_dashboard/utils/settings.py
+index 8bf9990..d6f8ad7 100644
+--- a/openstack_dashboard/utils/settings.py
++++ b/openstack_dashboard/utils/settings.py
+@@ -168,3 +168,12 @@ def update_dashboards(modules, horizon_config, installed_apps):
+     # so we save the reference to it before we append to installed_apps
+     horizon_config.setdefault('plugins', []).extend(apps)
+     installed_apps[0:0] = apps
++
++
++def execfile_schim(filename):
++    if six.PY3:
++        with open(filename) as f:
++            code = compile(f.read(), os.path.basename(filename), 'exec')
++            exec(code)
++    else:
++        execfile(filename)