From: Thomas Goirand Date: Mon, 21 Mar 2016 14:08:43 +0000 (+0100) Subject: Updated to last version of Fix_remaining_Django_1.9_test_failures.patch X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=4bd53bc470710f406eede17ac733c3593c9aca6a;p=openstack-build%2Fhorizon-build.git Updated to last version of Fix_remaining_Django_1.9_test_failures.patch Rewritten-From: 0a97594ad3b60a5b0d3c46e70638d6d8bf34d6be --- diff --git a/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch b/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch index dce3447..39ed60c 100644 --- a/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch +++ b/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch @@ -6,13 +6,13 @@ Co-Authored-By: Itxaka 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 %} +- {% trans "Close" %} ++ {% trans "Close" %} + {% 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)