From f668b347ca181229fab4b89fda25f1aadfbfdef1 Mon Sep 17 00:00:00 2001 From: Vipin Balachandran Date: Thu, 14 Aug 2014 15:09:40 +0530 Subject: [PATCH] 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 --- cinder/tests/test_vmware_volumeops.py | 41 +++++++++++++++++++++++ cinder/volume/drivers/vmware/volumeops.py | 9 +++-- 2 files changed, 47 insertions(+), 3 deletions(-) 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 -- 2.45.2