From: Vipin Balachandran Date: Thu, 14 Aug 2014 09:39:40 +0000 (+0530) Subject: VMware:Unquote folder name for folder exists check X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=f668b347ca181229fab4b89fda25f1aadfbfdef1;p=openstack-build%2Fcinder-build.git VMware:Unquote folder name for folder exists check vCenter server escapes special characters in the folder name using URL encoding and returns back the encoded string while querying. This causes the check for folder existence to return false. Therefore, folder creation is reattempted which eventually fails. This patch fixes the problem by decoding the folder name returned by vCenter before comparison. Change-Id: I40aa6f42ea0d85fbfcb40970c55b20e13ea46522 Closes-Bug: #1356794 --- diff --git a/cinder/tests/test_vmware_volumeops.py b/cinder/tests/test_vmware_volumeops.py index 4288e52c1..7e2caaf8f 100644 --- a/cinder/tests/test_vmware_volumeops.py +++ b/cinder/tests/test_vmware_volumeops.py @@ -454,6 +454,47 @@ class VolumeOpsTestCase(test.TestCase): # Clear side effects. self.session.invoke_api.side_effect = None + def test_create_folder_with_special_characters(self): + """Test create_folder with names containing special characters.""" + # Test folder already exists case. + child_entity_1 = mock.Mock(_type='Folder') + child_entity_1_name = 'cinder-volumes' + + child_entity_2 = mock.Mock(_type='Folder') + child_entity_2_name = '%2fcinder-volumes' + + prop_val = mock.Mock(ManagedObjectReference=[child_entity_1, + child_entity_2]) + self.session.invoke_api.side_effect = [prop_val, + child_entity_1_name, + child_entity_2_name] + + parent_folder = mock.sentinel.parent_folder + child_name = '/cinder-volumes' + ret = self.vops.create_folder(parent_folder, child_name) + + self.assertEqual(child_entity_2, ret) + + # Test non-existing folder case. + child_entity_2_name = '%25%25cinder-volumes' + new_child_folder = mock.sentinel.new_child_folder + self.session.invoke_api.side_effect = [prop_val, + child_entity_1_name, + child_entity_2_name, + new_child_folder] + + child_name = '%cinder-volumes' + ret = self.vops.create_folder(parent_folder, child_name) + + self.assertEqual(new_child_folder, ret) + self.session.invoke_api.assert_called_with(self.session.vim, + 'CreateFolder', + parent_folder, + name=child_name) + + # Reset side effects. + self.session.invoke_api.side_effect = None + def test_create_disk_backing_thin(self): backing = mock.Mock() del backing.eagerlyScrub diff --git a/cinder/volume/drivers/vmware/volumeops.py b/cinder/volume/drivers/vmware/volumeops.py index 307b2f33a..775314624 100644 --- a/cinder/volume/drivers/vmware/volumeops.py +++ b/cinder/volume/drivers/vmware/volumeops.py @@ -17,6 +17,8 @@ Implements operations on volumes residing on VMware datastores. """ +import urllib + from cinder.i18n import _ from cinder.openstack.common import log as logging from cinder.openstack.common import units @@ -536,9 +538,10 @@ class VMwareVolumeOps(object): if child_entity._type != 'Folder': continue child_entity_name = self.get_entity_name(child_entity) - if child_entity_name == child_folder_name: - LOG.debug("Child folder already present: %s." % - child_entity) + if child_entity_name and (urllib.unquote(child_entity_name) == + child_folder_name): + LOG.debug("Child folder: %s already present.", + child_folder_name) return child_entity # Need to create the child folder