From ebf00a5de541bb5d51996f065db17c27b9a0bc70 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 9 Feb 2016 18:40:21 +0100 Subject: [PATCH] Port API contribs to Python 3 * Replace dict.iteritems() with dict.items(), dict.iteritems() was removed in Python 3. * Replace dict.values() with list(dict.values()) to get a list on Python 3. * HTTP body type must be bytes: - Fix unit tests to use bytes strings for HTTP body - Encode XML to UTF-8 on Python 3. * Use "%r" instead of "%s" to format request and response in test to avoid BytesWarning on Python 3. * tests-py3.txt: add cinder.tests.unit.api.contrib Partial-Implements: blueprint cinder-python3 Change-Id: I65e412b2897635db5c8dfe13d61e71c52e0603e7 --- cinder/api/contrib/volume_actions.py | 10 +++-- cinder/api/contrib/volume_type_encryption.py | 2 +- cinder/tests/unit/api/contrib/test_backups.py | 29 +++++++++---- .../api/contrib/test_volume_image_metadata.py | 6 ++- .../api/contrib/test_volume_replication.py | 43 ++++++++++--------- .../unit/api/contrib/test_volume_transfer.py | 16 +++++-- .../api/contrib/test_volume_type_access.py | 4 +- .../contrib/test_volume_type_encryption.py | 6 +-- tests-py3.txt | 25 +---------- 9 files changed, 73 insertions(+), 68 deletions(-) diff --git a/cinder/api/contrib/volume_actions.py b/cinder/api/contrib/volume_actions.py index 225ad5e27..d2db66c36 100644 --- a/cinder/api/contrib/volume_actions.py +++ b/cinder/api/contrib/volume_actions.py @@ -15,6 +15,7 @@ from oslo_log import log as logging import oslo_messaging as messaging +from oslo_utils import encodeutils from oslo_utils import strutils import six import webob @@ -261,7 +262,8 @@ class VolumeActionsController(wsgi.Controller): try: force = strutils.bool_from_string(force, strict=True) except ValueError as error: - msg = _("Invalid value for 'force': '%s'") % error.message + err_msg = encodeutils.exception_to_unicode(error) + msg = _("Invalid value for 'force': '%s'") % err_msg raise webob.exc.HTTPBadRequest(explanation=msg) try: @@ -333,7 +335,8 @@ class VolumeActionsController(wsgi.Controller): readonly_flag = strutils.bool_from_string(readonly_flag, strict=True) except ValueError as error: - msg = _("Invalid value for 'readonly': '%s'") % error.message + err_msg = encodeutils.exception_to_unicode(error) + msg = _("Invalid value for 'readonly': '%s'") % err_msg raise webob.exc.HTTPBadRequest(explanation=msg) self.volume_api.update_readonly_flag(context, volume, readonly_flag) @@ -373,7 +376,8 @@ class VolumeActionsController(wsgi.Controller): bootable = strutils.bool_from_string(bootable, strict=True) except ValueError as error: - msg = _("Invalid value for 'bootable': '%s'") % error.message + err_msg = encodeutils.exception_to_unicode(error) + msg = _("Invalid value for 'bootable': '%s'") % err_msg raise webob.exc.HTTPBadRequest(explanation=msg) update_dict = {'bootable': bootable} diff --git a/cinder/api/contrib/volume_type_encryption.py b/cinder/api/contrib/volume_type_encryption.py index c0aeb72bf..5ffc7d026 100644 --- a/cinder/api/contrib/volume_type_encryption.py +++ b/cinder/api/contrib/volume_type_encryption.py @@ -46,7 +46,7 @@ class VolumeTypeEncryptionController(wsgi.Controller): encryption_specs = {} if not encryption_ref: return encryption_specs - for key, value in encryption_ref.iteritems(): + for key, value in encryption_ref.items(): encryption_specs[key] = value return encryption_specs diff --git a/cinder/tests/unit/api/contrib/test_backups.py b/cinder/tests/unit/api/contrib/test_backups.py index 3016e4b5a..dcd0e54ad 100644 --- a/cinder/tests/unit/api/contrib/test_backups.py +++ b/cinder/tests/unit/api/contrib/test_backups.py @@ -693,10 +693,14 @@ class BackupsAPITestCase(test.TestCase): volume_id = utils.create_volume(self.context, size=2)['id'] + body = ('' % volume_id) + if isinstance(body, six.text_type): + body = body.encode('utf-8') + req = webob.Request.blank('/v2/fake/backups') - req.body = ('' % volume_id) + req.body = body req.method = 'POST' req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' @@ -1165,8 +1169,12 @@ class BackupsAPITestCase(test.TestCase): size=2, display_name=volume_name)['id'] + body = '' % volume_id + if isinstance(body, six.text_type): + body = body.encode('utf-8') + req = webob.Request.blank('/v2/fake/backups/%s/restore' % backup_id) - req.body = '' % volume_id + req.body = body req.method = 'POST' req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' @@ -1792,14 +1800,17 @@ class BackupsAPITestCase(test.TestCase): _mock_import_record_rpc.return_value = None _mock_list_services.return_value = [backup_service] - req = webob.Request.blank('/v2/fake/backups/import_record') if six.PY2: backup_url = backup_url.encode('utf-8') - req.body = ('') \ - % {'backup_url': backup_url, - 'backup_service': backup_service} + body = ('' + % {'backup_url': backup_url, + 'backup_service': backup_service}) + if isinstance(body, six.text_type): + body = body.encode('utf-8') + req = webob.Request.blank('/v2/fake/backups/import_record') + req.body = body req.method = 'POST' req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' diff --git a/cinder/tests/unit/api/contrib/test_volume_image_metadata.py b/cinder/tests/unit/api/contrib/test_volume_image_metadata.py index 207f2ac2d..be986750c 100644 --- a/cinder/tests/unit/api/contrib/test_volume_image_metadata.py +++ b/cinder/tests/unit/api/contrib/test_volume_image_metadata.py @@ -341,5 +341,7 @@ class VolumeImageMetadataXMLTest(VolumeImageMetadataTest): volume, 'volume_image_metadata' ) for volume in volume_list] - return map(wsgi.MetadataXMLDeserializer().extract_metadata, - image_metadata_list) + + metadata_deserializer = wsgi.MetadataXMLDeserializer() + return [metadata_deserializer.extract_metadata(image_metadata) + for image_metadata in image_metadata_list] diff --git a/cinder/tests/unit/api/contrib/test_volume_replication.py b/cinder/tests/unit/api/contrib/test_volume_replication.py index 20e688461..3a0385782 100644 --- a/cinder/tests/unit/api/contrib/test_volume_replication.py +++ b/cinder/tests/unit/api/contrib/test_volume_replication.py @@ -19,6 +19,7 @@ Tests for volume replication API code. import mock from oslo_config import cfg from oslo_serialization import jsonutils +import six import webob from cinder import context @@ -55,6 +56,8 @@ class VolumeReplicationAPITestCase(test.TestCase): body = '' % operation req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' + if isinstance(body, six.text_type): + body = body.encode('utf-8') req.body = body else: body = {'os-%s-replica' % operation: ''} @@ -68,12 +71,12 @@ class VolumeReplicationAPITestCase(test.TestCase): def test_promote_bad_id(self): (req, res) = self._get_resp('promote', 'fake') - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(404, res.status_int, msg) def test_promote_bad_id_xml(self): (req, res) = self._get_resp('promote', 'fake', xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(404, res.status_int, msg) def test_promote_volume_not_replicated(self): @@ -81,7 +84,7 @@ class VolumeReplicationAPITestCase(test.TestCase): self.ctxt, **self.volume_params) (req, res) = self._get_resp('promote', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) def test_promote_volume_not_replicated_xml(self): @@ -89,7 +92,7 @@ class VolumeReplicationAPITestCase(test.TestCase): self.ctxt, **self.volume_params) (req, res) = self._get_resp('promote', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) @mock.patch('cinder.volume.rpcapi.VolumeAPI.promote_replica') @@ -101,7 +104,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = 'active', **self.volume_params) (req, res) = self._get_resp('promote', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) for status in ['available']: @@ -110,7 +113,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = 'active', **self.volume_params) (req, res) = self._get_resp('promote', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(202, res.status_int, msg) @mock.patch('cinder.volume.rpcapi.VolumeAPI.promote_replica') @@ -122,7 +125,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = 'active', **self.volume_params) (req, res) = self._get_resp('promote', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) for status in ['available']: @@ -131,7 +134,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = 'active', **self.volume_params) (req, res) = self._get_resp('promote', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(202, res.status_int, msg) @mock.patch('cinder.volume.rpcapi.VolumeAPI.promote_replica') @@ -143,7 +146,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('promote', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) for status in ['active', 'active-stopped']: @@ -152,7 +155,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('promote', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(202, res.status_int, msg) @mock.patch('cinder.volume.rpcapi.VolumeAPI.promote_replica') @@ -164,7 +167,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('promote', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) for status in ['active', 'active-stopped']: @@ -173,17 +176,17 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('promote', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(202, res.status_int, msg) def test_reenable_bad_id(self): (req, res) = self._get_resp('reenable', 'fake') - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(404, res.status_int, msg) def test_reenable_bad_id_xml(self): (req, res) = self._get_resp('reenable', 'fake', xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(404, res.status_int, msg) def test_reenable_volume_not_replicated(self): @@ -191,7 +194,7 @@ class VolumeReplicationAPITestCase(test.TestCase): self.ctxt, **self.volume_params) (req, res) = self._get_resp('reenable', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) def test_reenable_volume_not_replicated_xml(self): @@ -199,7 +202,7 @@ class VolumeReplicationAPITestCase(test.TestCase): self.ctxt, **self.volume_params) (req, res) = self._get_resp('reenable', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) @mock.patch('cinder.volume.rpcapi.VolumeAPI.reenable_replication') @@ -211,7 +214,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('reenable', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) for status in ['inactive', 'active-stopped', 'error']: @@ -220,7 +223,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('reenable', volume['id']) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(202, res.status_int, msg) @mock.patch('cinder.volume.rpcapi.VolumeAPI.reenable_replication') @@ -232,7 +235,7 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('reenable', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(400, res.status_int, msg) for status in ['inactive', 'active-stopped', 'error']: @@ -241,5 +244,5 @@ class VolumeReplicationAPITestCase(test.TestCase): replication_status = status, **self.volume_params) (req, res) = self._get_resp('reenable', volume['id'], xml=True) - msg = ("request: %s\nresult: %s" % (req, res)) + msg = ("request: %r\nresult: %r" % (req, res)) self.assertEqual(202, res.status_int, msg) diff --git a/cinder/tests/unit/api/contrib/test_volume_transfer.py b/cinder/tests/unit/api/contrib/test_volume_transfer.py index 3407c28f8..685905e93 100644 --- a/cinder/tests/unit/api/contrib/test_volume_transfer.py +++ b/cinder/tests/unit/api/contrib/test_volume_transfer.py @@ -17,10 +17,11 @@ Tests for volume transfer code. """ +import mock from xml.dom import minidom -import mock from oslo_serialization import jsonutils +import six import webob from cinder.api.contrib import volume_transfer @@ -285,9 +286,12 @@ class VolumeTransferAPITestCase(test.TestCase): volume_size = 2 volume_id = self._create_volume(status='available', size=volume_size) + body = '' % volume_id + if isinstance(body, six.text_type): + body = body.encode('utf-8') + req = webob.Request.blank('/v2/fake/os-volume-transfer') - req.body = ('' % volume_id) + req.body = body req.method = 'POST' req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' @@ -434,9 +438,13 @@ class VolumeTransferAPITestCase(test.TestCase): transfer = self._create_transfer(volume_id) svc = self.start_service('volume', host='fake_host') + body = '' % transfer['auth_key'] + if isinstance(body, six.text_type): + body = body.encode('utf-8') + req = webob.Request.blank('/v2/fake/os-volume-transfer/%s/accept' % transfer['id']) - req.body = '' % transfer['auth_key'] + req.body = body req.method = 'POST' req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' diff --git a/cinder/tests/unit/api/contrib/test_volume_type_access.py b/cinder/tests/unit/api/contrib/test_volume_type_access.py index f39bb802a..4fe3f214b 100644 --- a/cinder/tests/unit/api/contrib/test_volume_type_access.py +++ b/cinder/tests/unit/api/contrib/test_volume_type_access.py @@ -72,7 +72,7 @@ def fake_volume_type_get_all(context, inactive=False, filters=None, sort_dirs=None, offset=None, list_result=False): if filters is None or filters['is_public'] is None: if list_result: - return VOLUME_TYPES.values() + return list(VOLUME_TYPES.values()) return VOLUME_TYPES res = {} for k, v in VOLUME_TYPES.items(): @@ -82,7 +82,7 @@ def fake_volume_type_get_all(context, inactive=False, filters=None, if v['is_public'] == filters['is_public']: res.update({k: v}) if list_result: - return res.values() + return list(res.values()) return res diff --git a/cinder/tests/unit/api/contrib/test_volume_type_encryption.py b/cinder/tests/unit/api/contrib/test_volume_type_encryption.py index 369589fe5..9cf51cf19 100644 --- a/cinder/tests/unit/api/contrib/test_volume_type_encryption.py +++ b/cinder/tests/unit/api/contrib/test_volume_type_encryption.py @@ -166,7 +166,7 @@ class VolumeTypeEncryptionTest(test.TestCase): self.assertEqual(200, res.status_code) # Confirm that volume type has no encryption information # before create. - self.assertEqual('{}', res.body) + self.assertEqual(b'{}', res.body) # Create encryption specs for the volume type # with the defined body. @@ -214,8 +214,8 @@ class VolumeTypeEncryptionTest(test.TestCase): req = webob.Request.blank('/v2/fake/types/%s/encryption' % volume_type['id']) req.method = 'POST' - req.body = ('') + req.body = (b'') req.headers['Content-Type'] = 'application/xml' req.headers['Accept'] = 'application/xml' res = req.get_response(fakes.wsgi_app(fake_auth_context=ctxt)) diff --git a/tests-py3.txt b/tests-py3.txt index b275f5734..29e8324cd 100644 --- a/tests-py3.txt +++ b/tests-py3.txt @@ -1,27 +1,4 @@ -cinder.tests.unit.api.contrib.test_admin_actions -cinder.tests.unit.api.contrib.test_availability_zones -cinder.tests.unit.api.contrib.test_capabilities -cinder.tests.unit.api.contrib.test_cgsnapshots -cinder.tests.unit.api.contrib.test_extended_snapshot_attributes -cinder.tests.unit.api.contrib.test_hosts -cinder.tests.unit.api.contrib.test_qos_specs_manage -cinder.tests.unit.api.contrib.test_quotas -cinder.tests.unit.api.contrib.test_quotas_classes -cinder.tests.unit.api.contrib.test_scheduler_hints -cinder.tests.unit.api.contrib.test_scheduler_stats -cinder.tests.unit.api.contrib.test_services -cinder.tests.unit.api.contrib.test_snapshot_actions -cinder.tests.unit.api.contrib.test_snapshot_manage -cinder.tests.unit.api.contrib.test_snapshot_unmanage -cinder.tests.unit.api.contrib.test_types_extra_specs -cinder.tests.unit.api.contrib.test_types_manage -cinder.tests.unit.api.contrib.test_used_limits -cinder.tests.unit.api.contrib.test_volume_encryption_metadata -cinder.tests.unit.api.contrib.test_volume_host_attribute -cinder.tests.unit.api.contrib.test_volume_manage -cinder.tests.unit.api.contrib.test_volume_unmanage -cinder.tests.unit.api.contrib.test_volume_migration_status_attribute -cinder.tests.unit.api.contrib.test_volume_tenant_attribute +cinder.tests.unit.api.contrib cinder.tests.unit.api.openstack.test_wsgi cinder.tests.unit.api.test_common cinder.tests.unit.api.test_extensions -- 2.45.2