From 502dba692c8503076cfde6e1ddc7951622e673a6 Mon Sep 17 00:00:00 2001 From: Thomas Goirand Date: Fri, 10 Jun 2016 16:39:56 +0200 Subject: [PATCH] Removed Fix_remaining_Django_1.9_test_failures.patch applied upstream. Rewritten-From: 1c14f418ae6e9a84eddb459cb23050910dbada34 --- xenial/debian/changelog | 6 +- ...x_remaining_Django_1.9_test_failures.patch | 930 ------------------ xenial/debian/patches/series | 1 - 3 files changed, 5 insertions(+), 932 deletions(-) delete mode 100644 xenial/debian/patches/Fix_remaining_Django_1.9_test_failures.patch diff --git a/xenial/debian/changelog b/xenial/debian/changelog index 6c947ad..ee4cad7 100644 --- a/xenial/debian/changelog +++ b/xenial/debian/changelog @@ -1,9 +1,13 @@ horizon (2:10.0.0~b1-1) UNRELEASED; urgency=medium + [ Ivan Udovichenko ] * New upstream release. * Fix (build-)dependencies. - -- Ivan Udovichenko Wed, 08 Jun 2016 00:51:25 +0300 + [ Thomas Goirand ] + * Removed Fix_remaining_Django_1.9_test_failures.patch applied upstream. + + -- Thomas Goirand Fri, 10 Jun 2016 16:39:20 +0200 horizon (2:9.0.0-3) unstable; urgency=medium diff --git a/xenial/debian/patches/Fix_remaining_Django_1.9_test_failures.patch b/xenial/debian/patches/Fix_remaining_Django_1.9_test_failures.patch deleted file mode 100644 index 0bd022e..0000000 --- a/xenial/debian/patches/Fix_remaining_Django_1.9_test_failures.patch +++ /dev/null @@ -1,930 +0,0 @@ -Subject: [PATCH] [WIP] Fix remaining Django 1.9 test failures - This patch gets Horizon to a passing state in the Django 1.9 tests -Author: Rob Cresswell -Date: Thu, 11 Feb 2016 14:45:32 +0000 -Co-Authored-By: Itxaka -Change-Id: Icbc1a3c039de658faa9fba4a2cdd5027345fe94d -Partially-Implements: blueprint drop-dj17 -Origin: upstream, https://review.openstack.org/#/c/280222/ -Last-Update: 2016-03-21 - -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. - """ -- self._errors[NON_FIELD_ERRORS] = self.error_class([message]) -+ self.add_error(NON_FIELD_ERRORS, message) - - def set_warning(self, message): - """Sets a warning on the form. -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', - 'horizon.test.test_dashboards.cats', -- 'horizon.test.test_dashboards.dogs' -+ 'horizon.test.test_dashboards.dogs', -+ 'openstack_auth' - ) - - MIDDLEWARE_CLASSES = ( -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. - -+import django - from django.conf import settings - from django.contrib.auth.models import User # noqa - from django.core.exceptions import ImproperlyConfigured # noqa -@@ -308,7 +309,10 @@ class HorizonTests(BaseHorizonTests): - - self.client.logout() - resp = self.client.get(url) -- self.assertRedirects(resp, redirect_url) -+ if django.VERSION >= (1, 9): -+ self.assertRedirects(resp, settings.TESTSERVER + redirect_url) -+ else: -+ self.assertRedirects(resp, redirect_url) - - # Set SSL settings for test server - settings.SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', -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 - view.template_name = 'test_template' -+ # Note(Itxaka): ModalFormView requires a form_class to behave properly -+ view.form_class = TestForm - return view - - def test_modal_form_mixin_hide_true_if_ajax(self): -@@ -80,7 +82,9 @@ class FormErrorTests(test.TestCase): - - def setUp(self): - super(FormErrorTests, self).setUp() -- self.form = TestForm(self.request) -+ # Note(Itxaka): We pass data to the form so its bound and has the -+ # proper cleaned_data fields -+ self.form = TestForm(self.request, data={'fake': 'data'}) - - def _render_form(self): - return shortcuts.render(self.request, self.template, -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. - -+import django - from django.conf import settings -- - from django.http import HttpResponseRedirect # noqa - from django.utils import timezone - -@@ -41,7 +41,10 @@ class MiddlewareTests(test.TestCase): - resp = mw.process_exception(request, exceptions.NotAuthorized()) - resp.client = self.client - -- self.assertRedirects(resp, url) -+ if django.VERSION >= (1, 9): -+ self.assertRedirects(resp, settings.TESTSERVER + url) -+ else: -+ self.assertRedirects(resp, url) - - def test_process_response_redirect_on_ajax_request(self): - url = settings.LOGIN_URL -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() -- api.keystone.tenant_list(IsA(http.HttpRequest)).AndReturn([tenants, -- False]) -+ api.keystone.tenant_list( -+ IsA(http.HttpRequest) -+ ).MultipleTimes().AndReturn([tenants, False]) - api.neutron.list_extensions( - IsA(http.HttpRequest)).AndReturn(extensions) - self.mox.ReplayAll() -@@ -417,8 +418,11 @@ class NetworkTests(test.BaseAdminViewTests): - tenant_id = self.tenants.first().id - network = self.networks.first() - extensions = self.api_extensions.list() -- api.keystone.tenant_list(IsA(http.HttpRequest)).AndReturn([tenants, -- False]) -+ -+ api.keystone.tenant_list( -+ IsA(http.HttpRequest) -+ ).MultipleTimes().AndReturn([tenants, False]) -+ - api.neutron.list_extensions( - IsA(http.HttpRequest)).AndReturn(extensions) - self.mox.ReplayAll() -@@ -447,8 +451,10 @@ class NetworkTests(test.BaseAdminViewTests): - tenant_id = self.tenants.first().id - network = self.networks.first() - extensions = self.api_extensions.list() -- api.keystone.tenant_list(IsA(http.HttpRequest)).AndReturn([tenants, -- False]) -+ api.keystone.tenant_list( -+ IsA(http.HttpRequest) -+ ).MultipleTimes().AndReturn([tenants, False]) -+ - api.neutron.list_extensions( - IsA(http.HttpRequest)).AndReturn(extensions) - self.mox.ReplayAll() -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()) - -@@ -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 - -+import django - 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.SelfHandlingForm): - widget=forms.widgets.Textarea(attrs=attributes), - required=False) - -+ if django.VERSION >= (1, 9): -+ # Note(Itxaka): On django>=1.9 Charfield has an strip option that -+ # we need to set to False as to not hit -+ # https://bugs.launchpad.net/python-heatclient/+bug/1546166 -+ environment_data.strip = False -+ template_data.strip = False -+ - 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.SelfHandlingForm): - environment_data = forms.CharField( - widget=forms.widgets.HiddenInput, - required=False) -+ if django.VERSION >= (1, 9): -+ # Note(Itxaka): On django>=1.9 Charfield has an strip option that -+ # we need to set to False as to not hit -+ # https://bugs.launchpad.net/python-heatclient/+bug/1546166 -+ environment_data.strip = False -+ - parameters = forms.CharField( - widget=forms.widgets.HiddenInput) - stack_name = forms.RegexField( -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) - -- api.cinder.volume_backup_list_paged( -- IsA(http.HttpRequest), marker=None, sort_dir='desc', -- paginate=True).AndReturn([vol_backups, False, False]) -- api.cinder.volume_list(IsA(http.HttpRequest)). \ -- AndReturn(volumes) - self.mox.ReplayAll() - - formData = {'action': - 'volume_backups__delete__%s' % backup.id} - res = self.client.post(INDEX_URL + - "?tab=volumes_and_snapshots__backups_tab", -- formData, follow=True) -+ formData) - -- self.assertIn("Scheduled deletion of Volume Backup: backup1", -- [m.message for m in res.context['messages']]) -+ self.assertRedirectsNoFollow(res, INDEX_URL + -+ "?tab=volumes_and_snapshots__backups_tab") -+ self.assertMessageCount(success=1) - - @test.create_stubs({api.cinder: ('volume_backup_get', 'volume_get')}) - def test_volume_backup_detail_get(self): -diff --git a/openstack_dashboard/dashboards/project/volumes/cgroups/tests.py b/openstack_dashboard/dashboards/project/volumes/cgroups/tests.py -index b0eacb3..b608cca 100644 ---- a/openstack_dashboard/dashboards/project/volumes/cgroups/tests.py -+++ b/openstack_dashboard/dashboards/project/volumes/cgroups/tests.py -@@ -10,8 +10,10 @@ - # License for the specific language governing permissions and limitations - # under the License. - -+import django - from django.core.urlresolvers import reverse - from django import http -+from django.utils.http import urlunquote # noqa - from mox3.mox import IsA # noqa - - from openstack_dashboard.api import cinder -@@ -19,7 +21,8 @@ from openstack_dashboard.test import helpers as test - - - VOLUME_INDEX_URL = reverse('horizon:project:volumes:index') --VOLUME_CGROUPS_TAB_URL = reverse('horizon:project:volumes:cgroups_tab') -+VOLUME_CGROUPS_TAB_URL = urlunquote(reverse( -+ 'horizon:project:volumes:cgroups_tab')) - - - class ConsistencyGroupTests(test.TestCase): -@@ -111,8 +114,9 @@ class ConsistencyGroupTests(test.TestCase): - AndReturn(cgroups) - cinder.volume_cgroup_delete(IsA(http.HttpRequest), cgroup.id, - force=False) -- cinder.volume_cgroup_list_with_vol_type_names(IsA(http.HttpRequest)).\ -- AndReturn(cgroups) -+ if django.VERSION < (1, 9): -+ cinder.volume_cgroup_list_with_vol_type_names( -+ IsA(http.HttpRequest)).AndReturn(cgroups) - - self.mox.ReplayAll() - -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', -- 'volume_snapshot_delete')}) -+ 'volume_snapshot_delete', -+ 'tenant_absolute_limits')}) - 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.TestCase): - AndReturn(volumes) - - api.cinder.volume_snapshot_delete(IsA(http.HttpRequest), snapshot.id) -- api.cinder.volume_snapshot_list_paged( -- IsA(http.HttpRequest), paginate=True, marker=None, -- sort_dir='desc').AndReturn([[], False, False]) -- api.cinder.volume_list(IsA(http.HttpRequest)). \ -- AndReturn(volumes) - self.mox.ReplayAll() - - formData = {'action': - 'volume_snapshots__delete__%s' % snapshot.id} -- res = self.client.post(VOLUME_SNAPSHOTS_TAB_URL, formData, follow=True) -+ res = self.client.post(VOLUME_SNAPSHOTS_TAB_URL, formData) - -- self.assertIn("Scheduled deletion of Volume Snapshot: test snapshot", -- [m.message for m in res.context['messages']]) -+ self.assertRedirectsNoFollow(res, VOLUME_SNAPSHOTS_TAB_URL) -+ self.assertMessageCount(success=1) - - @test.create_stubs({api.cinder: ('volume_snapshot_get', 'volume_get')}) - def test_volume_snapshot_detail_get(self): -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()) -- -- 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 - --from openstack_auth import policy --POLICY_CHECK_FUNCTION = policy.check -+ -+def check(actions, request, target=None): -+ # Note(Itxaka): This is to prevent circular dependencies and apps not ready -+ # If you do django imports in your settings, you are gonna have a bad time -+ from openstack_auth import policy -+ return policy.check(actions, request, target=None) -+ -+POLICY_CHECK_FUNCTION = check - - # This base context objects gets added to the offline context generator - # for each theme configured. -@@ -392,11 +398,14 @@ COMPRESS_OFFLINE_CONTEXT = 'horizon.themes.offline_context' - if DEBUG: - logging.basicConfig(level=logging.DEBUG) - -+# Note(Itxaka): This does not work due the apps not ready when importing -+# auth_utils - # during django reloads and an active user is logged in, the monkey - # patch below will not otherwise be applied in time - resulting in developers - # appearing to be logged out. In typical production deployments this section - # below may be omitted, though it should not be harmful --from openstack_auth import utils as auth_utils --auth_utils.patch_middleware_get_user() -+# -+# from openstack_auth import utils as auth_utils -+# auth_utils.patch_middleware_get_user() - - CSRF_COOKIE_AGE = None -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 - from django.test import utils as django_test_utils -+from django.utils import http - - from ceilometerclient.v2 import client as ceilometer_client - from cinderclient import client as cinder_client -@@ -232,8 +233,10 @@ class TestCase(horizon_helpers.TestCase): - processing the view which is redirected to. - """ - if django.VERSION >= (1, 9): -- self.assertEqual(response._headers.get('location', None), -- ('Location', expected_url)) -+ loc = six.text_type(response._headers.get('location', None)[1]) -+ loc = http.urlunquote(loc) -+ expected_url = http.urlunquote(expected_url) -+ self.assertEqual(loc, expected_url) - 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) diff --git a/xenial/debian/patches/series b/xenial/debian/patches/series index 41ab217..e883b03 100644 --- a/xenial/debian/patches/series +++ b/xenial/debian/patches/series @@ -1,4 +1,3 @@ fix-dashboard-django-wsgi.patch fix-dashboard-manage.patch fixed-horizon-MANIFEST.in.patch -Fix_remaining_Django_1.9_test_failures.patch -- 2.45.2