From c03c2fa70dabce689f0b6b86411997e0e24fcd5c Mon Sep 17 00:00:00 2001 From: dineshbhor Date: Mon, 19 Dec 2016 21:13:45 +0530 Subject: [PATCH] Fix python integer interpretation in Py2 and Py3 If user passes large number "11111111111111111111111111111" as size to the create volume api, then the api behaves inconsistently depending on whether the cinder-api service is running on Py2 and Py3. In case of Py2, it returns following error message: ERROR: Invalid input received: Volume size '11111111111111111111111111111' must be an integer and greater than 0 (HTTP 400) (Request-ID: req-abe6cd5 e-a0c6-4e0d-ba05-c9eceef547bf) But in case of Py3, it passes this validation. This patch fixes this inconsistency issue by checking isinstance(size, int) to isinstance(size, six.integer_types). NOTE: The unit test written in the patch will fail on master on Py2 environment and it's written to just ensure that the issue is resolved for Py2. Closes-Bug: #1651103 Change-Id: Ib43b96d458f0d4e9477886bd19c35a7e05664929 --- .../volume/flows/test_create_volume_flow.py | 57 +++++++++++++++++++ cinder/volume/flows/api/create_volume.py | 3 +- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/cinder/tests/unit/volume/flows/test_create_volume_flow.py b/cinder/tests/unit/volume/flows/test_create_volume_flow.py index 3d8a9fc962b..83b0037d625 100644 --- a/cinder/tests/unit/volume/flows/test_create_volume_flow.py +++ b/cinder/tests/unit/volume/flows/test_create_volume_flow.py @@ -14,6 +14,8 @@ # under the License. """ Tests for create_volume TaskFlow """ +import sys + import ddt import mock @@ -343,6 +345,61 @@ class CreateVolumeFlowTestCase(test.TestCase): 'replication_status': 'disabled'} self.assertEqual(expected_result, result) + @mock.patch('cinder.volume.volume_types.is_encrypted') + @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs') + @mock.patch('cinder.volume.flows.api.create_volume.' + 'ExtractVolumeRequestTask.' + '_get_volume_type_id') + def test_extract_volume_request_task_with_large_volume_size( + self, + fake_get_type_id, + fake_get_qos, + fake_is_encrypted): + fake_image_service = fake_image.FakeImageService() + image_id = 11 + image_meta = {} + image_meta['id'] = image_id + image_meta['status'] = 'active' + image_meta['size'] = 1 + fake_image_service.create(self.ctxt, image_meta) + fake_key_manager = mock_key_manager.MockKeyManager() + volume_type = 'type1' + + task = create_volume.ExtractVolumeRequestTask( + fake_image_service, + {'nova'}) + + fake_is_encrypted.return_value = False + fake_get_type_id.return_value = 1 + fake_get_qos.return_value = {'qos_specs': None} + result = task.execute(self.ctxt, + size=(sys.maxsize + 1), + snapshot=None, + image_id=image_id, + source_volume=None, + availability_zone=None, + volume_type=volume_type, + metadata=None, + key_manager=fake_key_manager, + source_replica=None, + consistencygroup=None, + cgsnapshot=None, + group=None) + expected_result = {'size': (sys.maxsize + 1), + 'snapshot_id': None, + 'source_volid': None, + 'availability_zone': 'nova', + 'volume_type': volume_type, + 'volume_type_id': 1, + 'encryption_key_id': None, + 'qos_specs': None, + 'replication_status': 'disabled', + 'source_replicaid': None, + 'consistencygroup_id': None, + 'cgsnapshot_id': None, + 'group_id': None, } + self.assertEqual(expected_result, result) + @mock.patch('cinder.volume.volume_types.is_encrypted') @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs') @mock.patch('cinder.volume.flows.api.create_volume.' diff --git a/cinder/volume/flows/api/create_volume.py b/cinder/volume/flows/api/create_volume.py index 6d9ab197e34..6b4f2bf1c58 100644 --- a/cinder/volume/flows/api/create_volume.py +++ b/cinder/volume/flows/api/create_volume.py @@ -15,6 +15,7 @@ from oslo_config import cfg from oslo_log import log as logging from oslo_utils import timeutils from oslo_utils import units +import six import taskflow.engines from taskflow.patterns import linear_flow from taskflow.types import failure as ft @@ -169,7 +170,7 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask): raise exception.InvalidInput(reason=msg) def validate_int(size): - if not isinstance(size, int) or size <= 0: + if not isinstance(size, six.integer_types) or size <= 0: msg = _("Volume size '%(size)s' must be an integer and" " greater than 0") % {'size': size} raise exception.InvalidInput(reason=msg)