]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add additional metadata as key-value pairs in 3PAR
authorSivaramakrishna Garimella <sivaramakrishna.garimella@hp.com>
Mon, 9 Dec 2013 05:41:13 +0000 (11:11 +0530)
committerSivaramakrishna Garimella <sivaramakrishna.garimella@hp.com>
Tue, 24 Dec 2013 21:53:42 +0000 (14:53 -0700)
Track status of openstack volumes on 3PAR through
additional metadata added as key-value pairs. During volume attach
and detach, corresponding instance metadata is updated onto the
cinder volumes.

Change-Id: Iea8d2f26555e6be60001bf73755cae42446afec6
Closes-Bug: #1258033

cinder/tests/test_hp3par.py
cinder/volume/drivers/san/hp/hp_3par_common.py
cinder/volume/drivers/san/hp/hp_3par_fc.py
cinder/volume/drivers/san/hp/hp_3par_iscsi.py

index 8034bca00d57f585a0322344f42e5e41fdf33360..942ec7a2a36371fb566e8d87fb7994df7579c850 100644 (file)
@@ -25,6 +25,7 @@ import tempfile
 
 from hp3parclient import exceptions as hpexceptions
 
+from cinder import context
 from cinder import exception
 from cinder.openstack.common import log as logging
 from cinder import test
@@ -574,6 +575,33 @@ class HP3PARBaseDriver():
         model_update = self.driver.create_cloned_volume(volume, src_vref)
         self.assertIsNotNone(model_update)
 
+    @mock.patch.object(hpdriver.hpcommon.HP3PARCommon, '_run_ssh')
+    def test_attach_volume(self, mock_run_ssh):
+        mock_run_ssh.side_effect = [[CLI_CR, ''], Exception('Custom ex')]
+        self.driver.attach_volume(context.get_admin_context(),
+                                  self.volume,
+                                  'abcdef',
+                                  'newhost',
+                                  '/dev/vdb')
+        self.assertTrue(mock_run_ssh.called)
+        self.assertRaises(exception.CinderException,
+                          self.driver.attach_volume,
+                          context.get_admin_context(),
+                          self.volume,
+                          'abcdef',
+                          'newhost',
+                          '/dev/vdb')
+
+    @mock.patch.object(hpdriver.hpcommon.HP3PARCommon, '_run_ssh')
+    def test_detach_volume(self, mock_run_ssh):
+        mock_run_ssh.side_effect = [[CLI_CR, ''], Exception('Custom ex')]
+        self.driver.detach_volume(context.get_admin_context(), self.volume)
+        self.assertTrue(mock_run_ssh.called)
+        self.assertRaises(exception.CinderException,
+                          self.driver.detach_volume,
+                          context.get_admin_context(),
+                          self.volume)
+
     def test_create_snapshot(self):
         self.flags(lock_path=self.tempdir)
         self.driver.create_snapshot(self.snapshot)
@@ -643,6 +671,35 @@ class HP3PARBaseDriver():
                           self.driver.common.client.getVLUN,
                           self.VOLUME_3PAR_NAME)
 
+    @mock.patch.object(hpdriver.hpcommon.HP3PARCommon, '_run_ssh')
+    def test_update_volume_key_value_pair(self, mock_run_ssh):
+        mock_run_ssh.return_value = [CLI_CR, '']
+        self.assertEqual(
+            self.driver.common.update_volume_key_value_pair(self.volume,
+                                                            'a',
+                                                            'b'),
+            None)
+        update_cmd = ['setvv', '-setkv', 'a=b', self.VOLUME_3PAR_NAME]
+        mock_run_ssh.assert_called_once_with(update_cmd, False)
+        self.assertRaises(exception.VolumeBackendAPIException,
+                          self.driver.common.update_volume_key_value_pair,
+                          self.volume,
+                          None,
+                          'b')
+
+    @mock.patch.object(hpdriver.hpcommon.HP3PARCommon, '_run_ssh')
+    def test_clear_volume_key_value_pair(self, mock_run_ssh):
+        mock_run_ssh.side_effect = [[CLI_CR, ''], Exception('Custom ex')]
+        self.assertEqual(
+            self.driver.common.clear_volume_key_value_pair(self.volume, 'a'),
+            None)
+        clear_cmd = ['setvv', '-clrkey', 'a', self.VOLUME_3PAR_NAME]
+        mock_run_ssh.assert_called_once_with(clear_cmd, False)
+        self.assertRaises(exception.VolumeBackendAPIException,
+                          self.driver.common.clear_volume_key_value_pair,
+                          self.volume,
+                          None)
+
     def test_extend_volume(self):
         self.flags(lock_path=self.tempdir)
         self.stubs.UnsetAll()
index 8da5e5269c5edf8909b299fdb64bd9580ec19635..2e86530b7fcb04ec2db7e229d444a86d42a4003d 100644 (file)
@@ -117,10 +117,11 @@ class HP3PARCommon(object):
         1.2.0 - Updated hp3parclient API use to 2.0.x
         1.2.1 - Check that the VVS exists
         1.2.2 - log prior to raising exceptions
+        1.2.3 - Methods to update key/value pair bug #1258033
 
     """
 
-    VERSION = "1.2.2"
+    VERSION = "1.2.3"
 
     stats = {}
 
@@ -972,6 +973,61 @@ exit
             LOG.error(str(ex))
             raise exception.NotFound()
 
+    def update_volume_key_value_pair(self, volume, key, value):
+        """Updates key,value pair as metadata onto virtual volume.
+
+        If key already exists, the value will be replaced.
+        """
+        LOG.debug("VOLUME (%s : %s %s) Updating KEY-VALUE pair: (%s : %s)" %
+                  (volume['display_name'],
+                   volume['name'],
+                   self._get_3par_vol_name(volume['id']),
+                   str(key),
+                   str(value)))
+        try:
+            volume_name = self._get_3par_vol_name(volume['id'])
+            if value is None:
+                value = ''
+            cmd = ['setvv', '-setkv', key + '=' + value, volume_name]
+            self._cli_run(cmd)
+        except Exception as ex:
+            msg = _('Failure in update_volume_key_value_pair:%s') % str(ex)
+            LOG.error(msg)
+            raise exception.VolumeBackendAPIException(data=msg)
+
+    def clear_volume_key_value_pair(self, volume, key):
+        """Clears key,value pairs metadata from virtual volume."""
+
+        LOG.debug("VOLUME (%s : %s %s) Clearing Key : %s)" %
+                  (volume['display_name'], volume['name'],
+                   self._get_3par_vol_name(volume['id']), str(key)))
+        try:
+            volume_name = self._get_3par_vol_name(volume['id'])
+            cmd = ['setvv', '-clrkey', key, volume_name]
+            self._cli_run(cmd)
+        except Exception as ex:
+            msg = _('Failure in clear_volume_key_value_pair:%s') % str(ex)
+            LOG.error(msg)
+            raise exception.VolumeBackendAPIException(data=msg)
+
+    def attach_volume(self, volume, instance_uuid):
+        LOG.debug("Attach Volume\n%s" % pprint.pformat(volume))
+        try:
+            self.update_volume_key_value_pair(volume,
+                                              'HPQ-CS-instance_uuid',
+                                              instance_uuid)
+        except Exception:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_("Error attaching volume %s") % volume)
+
+    def detach_volume(self, volume):
+        LOG.debug("Detach Volume\n%s" % pprint.pformat(volume))
+        try:
+            self.clear_volume_key_value_pair(volume, 'HPQ-CS-instance_uuid')
+        except Exception:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_("Error detaching volume %s") % volume)
+
     def delete_snapshot(self, snapshot):
         LOG.debug("Delete Snapshot\n%s" % pprint.pformat(snapshot))
 
index e404f998dc305363225bff742840df51bf5c7caf..ee71de92dec7e23cd9de1ae496758ecedd45fa7c 100644 (file)
@@ -55,9 +55,11 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
         1.2.1 - Synchronized extend_volume method.
         1.2.2 - Added try/finally around client login/logout.
         1.2.3 - Added ability to add WWNs to host.
+        1.2.4 - Added metadata during attach/detach bug #1258033.
+
     """
 
-    VERSION = "1.2.3"
+    VERSION = "1.2.4"
 
     def __init__(self, *args, **kwargs):
         super(HP3PARFCDriver, self).__init__(*args, **kwargs)
@@ -316,3 +318,12 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
     @utils.synchronized('3par', external=True)
     def extend_volume(self, volume, new_size):
         self.common.extend_volume(volume, new_size)
+
+    @utils.synchronized('3par', external=True)
+    def attach_volume(self, context, volume, instance_uuid, host_name,
+                      mountpoint):
+        self.common.attach_volume(volume, instance_uuid)
+
+    @utils.synchronized('3par', external=True)
+    def detach_volume(self, context, volume):
+        self.common.detach_volume(volume)
index be4e0b1483e58f88a1a8de2785b4e6ca44a433f5..94fd27c9fee4002fcbfca7d935226f4746151fde 100644 (file)
@@ -59,9 +59,11 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver):
         1.2.2 - Added try/finally around client login/logout.
         1.2.3 - log exceptions before raising
         1.2.4 - Fixed iSCSI active path bug #1224594
+        1.2.5 - Added metadata during attach/detach bug #1258033
+
     """
 
-    VERSION = "1.2.4"
+    VERSION = "1.2.5"
 
     def __init__(self, *args, **kwargs):
         super(HP3PARISCSIDriver, self).__init__(*args, **kwargs)
@@ -423,3 +425,12 @@ class HP3PARISCSIDriver(cinder.volume.driver.ISCSIDriver):
     @utils.synchronized('3par', external=True)
     def extend_volume(self, volume, new_size):
         self.common.extend_volume(volume, new_size)
+
+    @utils.synchronized('3par', external=True)
+    def attach_volume(self, context, volume, instance_uuid, host_name,
+                      mountpoint):
+        self.common.attach_volume(volume, instance_uuid)
+
+    @utils.synchronized('3par', external=True)
+    def detach_volume(self, context, volume):
+        self.common.detach_volume(volume)