"""Test class for VMwareVcVmdkDriver."""
PBM_WSDL = '/fake/wsdl/path'
+ DEFAULT_PROFILE = 'fakeProfile'
def setUp(self):
super(VMwareVcVmdkDriverTestCase, self).setUp()
- self.flags(vmware_pbm_wsdl=self.PBM_WSDL)
+ self._config.pbm_wsdl_location = self.PBM_WSDL
+ self._config.pbm_default_policy = self.DEFAULT_PROFILE
self._driver = vmdk.VMwareVcVmdkDriver(configuration=self._config)
+ @mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
+ 'session', new_callable=mock.PropertyMock)
+ @mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
+ 'volumeops', new_callable=mock.PropertyMock)
+ def test_do_setup(self, vol_ops, session):
+ """Test do_setup."""
+ vol_ops = vol_ops.return_value
+ session = session.return_value
+ # pbm_wsdl_location is set and pbm_default_policy is used
+ self._driver.do_setup(mock.ANY)
+ default = self.DEFAULT_PROFILE
+ vol_ops.retrieve_profile_id.assert_called_once_with(default)
+ # pbm_wsdl_location is set and pbm_default_policy is wrong
+ vol_ops.retrieve_profile_id.return_value = None
+ self.assertRaises(error_util.PbmDefaultPolicyDoesNotExist,
+ self._driver.do_setup, mock.ANY)
+ # pbm_wsdl_location is not set
+ self._driver.configuration.pbm_wsdl_location = None
+ self._driver.do_setup(mock.ANY)
+
def test_init_conn_with_instance_and_backing(self):
"""Test initialize_connection with instance and backing."""
m = self.mox
def test_get_storage_profile(self, get_volume_type_extra_specs):
"""Test vmdk _get_storage_profile."""
- # Test volume with no type id returns None
+ # volume with no type id returns None
volume = FakeObject()
volume['volume_type_id'] = None
sp = self._driver._get_storage_profile(volume)
self.assertEqual(None, sp, "Without a volume_type_id no storage "
"profile should be returned.")
- # Test volume with type id calls extra specs
+ # profile associated with the volume type should be returned
fake_id = 'fake_volume_id'
volume['volume_type_id'] = fake_id
- self._driver._get_storage_profile(volume)
+ get_volume_type_extra_specs.return_value = 'fake_profile'
+ profile = self._driver._get_storage_profile(volume)
+ self.assertEqual('fake_profile', profile)
spec_key = 'vmware:storage_profile'
get_volume_type_extra_specs.assert_called_once_with(fake_id, spec_key)
+ # default profile should be returned when no storage profile is
+ # associated with the volume type
+ get_volume_type_extra_specs.return_value = False
+ profile = self._driver._get_storage_profile(volume)
+ self.assertEqual(self.DEFAULT_PROFILE, profile)
+
@mock.patch('cinder.volume.drivers.vmware.vim_util.'
'convert_datastores_to_hubs')
@mock.patch('cinder.volume.drivers.vmware.vim_util.'
def __init__(self, fault_list, msg):
exception.VolumeBackendAPIException.__init__(self, msg)
self.fault_list = fault_list
+
+
+class VMwareDriverException(exception.CinderException):
+ """Base class for all exceptions raised by the VMDK driver.
+
+ All exceptions raised by the vmdk driver should raise an exception
+ descended from this class as a root. This will allow the driver to
+ potentially trap problems related to its own internal configuration
+ before halting the cinder-volume node.
+ """
+ message = _("VMware VMDK driver exception.")
+
+
+class VMwaredriverConfigurationException(VMwareDriverException):
+ """Base class for all configuration exceptions.
+ """
+ message = _("VMware VMDK driver configuration error.")
+
+
+class PbmDefaultPolicyDoesNotExist(VMwaredriverConfigurationException):
+ message = _("The configured default PBM policy is not defined on "
+ "vCenter Server.")
'Query results will be obtained in batches from the '
'server and not in one shot. Server may still limit the '
'count to something less than the configured value.'),
- cfg.StrOpt('vmware_pbm_wsdl',
+]
+
+spbm_opts = [
+ cfg.StrOpt('pbm_wsdl_location',
help='PBM service WSDL file location URL. '
'e.g. file:///opt/SDK/spbm/wsdl/pbmService.wsdl. '
'Not setting this will disable storage policy based '
'placement of volumes.'),
+ cfg.StrOpt('pbm_default_policy',
+ help='The PBM default policy. If pbm_wsdl_location is set and '
+ 'there is no defined storage policy for the specific '
+ 'request then this policy will be used.'),
]
CONF = cfg.CONF
CONF.register_opts(vmdk_opts)
+CONF.register_opts(spbm_opts)
def _get_volume_type_extra_spec(type_id, spec_key, possible_values=None,
:param volume: volume whose storage profile should be queried
:return: string value of storage profile if volume type is associated,
+ default global profile if configured in pbm_default_profile,
None otherwise
"""
type_id = volume['volume_type_id']
if not type_id:
return
- return _get_volume_type_extra_spec(type_id, 'storage_profile')
+ default_policy = self.configuration.pbm_default_policy
+ return _get_volume_type_extra_spec(type_id, 'storage_profile',
+ default_value=default_policy)
def _filter_ds_by_profile(self, datastores, storage_profile):
"""Filter out datastores that do not match given storage profile.
def __init__(self, *args, **kwargs):
super(VMwareVcVmdkDriver, self).__init__(*args, **kwargs)
+ self.configuration.append_config_values(spbm_opts)
self._session = None
@property
api_retry_count = self.configuration.vmware_api_retry_count
task_poll_interval = self.configuration.vmware_task_poll_interval
wsdl_loc = self.configuration.safe_get('vmware_wsdl_location')
- pbm_wsdl = self.configuration.vmware_pbm_wsdl
+ pbm_wsdl = self.configuration.pbm_wsdl_location
self._session = api.VMwareAPISession(ip, username,
password, api_retry_count,
task_poll_interval,
wsdl_loc=wsdl_loc,
pbm_wsdl=pbm_wsdl)
- if pbm_wsdl:
- self._storage_policy_enabled = True
return self._session
+ def do_setup(self, context):
+ """Any initialization the volume driver does while starting."""
+ super(VMwareVcVmdkDriver, self).do_setup(context)
+ # VC specific setup is done here
+ pbm_wsdl = self.configuration.pbm_wsdl_location
+ default_policy = self.configuration.pbm_default_policy
+ if not pbm_wsdl:
+ if default_policy:
+ LOG.warn(_("Ignoring %s since pbm_wsdl_location is not "
+ "set."), default_policy)
+ return
+ # pbm_wsdl is set, so storage policy should be enabled
+ self._storage_policy_enabled = True
+ # now verify the default policy exists in VC
+ if default_policy:
+ if not self.volumeops.retrieve_profile_id(default_policy):
+ msg = _("The configured default PBM policy '%s' is not "
+ "defined on vCenter Server.") % default_policy
+ raise error_util.PbmDefaultPolicyDoesNotExist(message=msg)
+ else:
+ LOG.info(_("Successfully verified existence of "
+ "pbm_default_policy: %s."), default_policy)
+
def _get_volume_group_folder(self, datacenter):
"""Get volume group folder.
# Options defined in cinder.volume.drivers.vmware.vmdk
#
+# PBM service WSDL file location URL. e.g.
+# file:///opt/SDK/spbm/wsdl/pbmService.wsdl. Not setting this
+# will disable storage policy based placement of volumes.
+# (string value)
+#pbm_wsdl_location=<None>
+
+# The PBM default policy. If pbm_wsdl_location is set and
+# there is no defined storage policy for the specific request
+# then this policy will be used. (string value)
+#pbm_default_policy=<None>
+
# IP address for connecting to VMware ESX/VC server. (string
# value)
#vmware_host_ip=<None>
# less than the configured value. (integer value)
#vmware_max_objects_retrieval=100
-# PBM service WSDL file location URL. e.g.
-# file:///opt/SDK/spbm/wsdl/pbmService.wsdl. Not setting this
-# will disable storage policy based placement of volumes.
-# (string value)
-#vmware_pbm_wsdl=<None>
-
#
# Options defined in cinder.volume.drivers.windows.windows