]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
vmware: default global pbm policy configuration
authorSubramanian Neelakantan <subramanian.neelakantan@gmail.com>
Tue, 28 Jan 2014 05:39:25 +0000 (11:09 +0530)
committerSubramanian Neelakantan <subramanian.neelakantan@gmail.com>
Mon, 3 Mar 2014 05:57:00 +0000 (11:27 +0530)
Adding support for a global pbm policy configuration for the vmdk
driver. Setting the 'pbm_default_policy' in cinder.conf will be
used as the default storage profile name to be used when creating
a volume without associated vmware:storage_profile extra spec.

Also renaming 'vmware-pbm-wsdl' to 'pbm-wsdl-location' to use
nova driver's naming convention.

Implements: blueprint vmdk-storage-policy-volume-type
Change-Id: I7fad167b7be6a479db88fb4d15d07f29afd023b0

cinder/tests/test_vmware_vmdk.py
cinder/volume/drivers/vmware/error_util.py
cinder/volume/drivers/vmware/vmdk.py
etc/cinder/cinder.conf.sample

index 2083bb5618e94c74caf2b5d9d6be6bdeac46d300..682c80a939eaaa69e65aefa5441803ec1282b696 100644 (file)
@@ -1054,12 +1054,34 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
     """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
@@ -1300,20 +1322,28 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
     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.'
index 0be99d95391734a4e1b38bcfe1f27facb173f855..a9c02bd862573575ebc78d74f04c29630306b0fc 100644 (file)
@@ -45,3 +45,25 @@ class VimFaultException(exception.VolumeBackendAPIException):
     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.")
index 176280238a4cd6130500cdf23c778270994770dd..44603e71c1ec0d6f97a5681ca7e00fc00726f435 100644 (file)
@@ -80,15 +80,23 @@ vmdk_opts = [
                     '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,
@@ -317,12 +325,15 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
 
         :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.
@@ -951,6 +962,7 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
 
     def __init__(self, *args, **kwargs):
         super(VMwareVcVmdkDriver, self).__init__(*args, **kwargs)
+        self.configuration.append_config_values(spbm_opts)
         self._session = None
 
     @property
@@ -962,16 +974,37 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
             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.
 
index abf31a02efdffed602fea06b7af1afbdd79c5440..d2f32770cd61196b3acc868d39cd60d9cd3dcd64 100644 (file)
 # 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