Add additional metadata as key-value pairs in 3PAR

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
This commit is contained in:
Sivaramakrishna Garimella 2013-12-09 11:11:13 +05:30
parent 8a5ce963dc
commit dd9536ac6e
4 changed files with 138 additions and 3 deletions

View 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()

View 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))

View 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)

View 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)