Refactor HP LeftHand driver to now be HPE

This patch refactors the HP LeftHand driver to be
HPE LeftHand.

This is being done because the company responsible for
this driver is now Hewlett Packard Enterprise (HPE).

The driver is now located in the cinder/volume/drivers/hpe
folder.

DocImpact
Implements: blueprint rebrand-hp-lefthand-driver
Change-Id: I42eb5b3a51d547e45338a4964f31e0aca2ce43d8
This commit is contained in:
Anthony Lee 2015-10-29 15:29:19 -07:00
parent 3a5fc76918
commit 091d4cc3fa
5 changed files with 268 additions and 181 deletions

View File

@ -1,4 +1,4 @@
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
# (c) Copyright 2014-2015 Hewlett Packard Enterprise Development LP
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -13,16 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
#
"""Fake HP client for testing LeftHand without installing the client."""
"""Fake HPE client for testing LeftHand without installing the client."""
import sys
import mock
from cinder.tests.unit import fake_hpe_client_exceptions as hpexceptions
from cinder.tests.unit import fake_hpe_client_exceptions as hpeexceptions
hplefthand = mock.Mock()
hplefthand.version = "1.0.4"
hplefthand.exceptions = hpexceptions
hpelefthand = mock.Mock()
hpelefthand.version = "2.0.0"
hpelefthand.exceptions = hpeexceptions
sys.modules['hplefthandclient'] = hplefthand
sys.modules['hpelefthandclient'] = hpelefthand

View File

@ -1,4 +1,4 @@
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
# (c) Copyright 2014-2015 Hewlett Packard Enterprise Development LP
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -21,11 +21,11 @@ from oslo_utils import units
from cinder import context
from cinder import exception
from cinder import test
from cinder.tests.unit import fake_hp_lefthand_client as hplefthandclient
from cinder.volume.drivers.san.hp import hp_lefthand_iscsi
from cinder.tests.unit import fake_hpe_lefthand_client as hpelefthandclient
from cinder.volume.drivers.hpe import hpe_lefthand_iscsi
from cinder.volume import volume_types
hpexceptions = hplefthandclient.hpexceptions
hpeexceptions = hpelefthandclient.hpeexceptions
GOODNESS_FUNCTION = \
"capabilities.capacity_utilization < 0.6? 100 : 25"
@ -33,7 +33,7 @@ FILTER_FUNCTION = \
"capabilities.total_volumes < 400 && capabilities.capacity_utilization"
class HPLeftHandBaseDriver(object):
class HPELeftHandBaseDriver(object):
cluster_id = 1
@ -73,11 +73,19 @@ class HPLeftHandBaseDriver(object):
volume_type = {'name': 'gold',
'deleted': False,
'updated_at': None,
'extra_specs': {'hplh:provisioning': 'thin',
'hplh:ao': 'true',
'hplh:data_pl': 'r-0'},
'extra_specs': {'hpelh:provisioning': 'thin',
'hpelh:ao': 'true',
'hpelh:data_pl': 'r-0'},
'deleted_at': None,
'id': 'gold'}
old_volume_type = {'name': 'gold',
'deleted': False,
'updated_at': None,
'extra_specs': {'hplh:provisioning': 'thin',
'hplh:ao': 'true',
'hplh:data_pl': 'r-0'},
'deleted_at': None,
'id': 'gold'}
connector = {
'ip': '10.0.0.2',
@ -90,7 +98,7 @@ class HPLeftHandBaseDriver(object):
]
class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
class TestHPELeftHandISCSIDriver(HPELeftHandBaseDriver, test.TestCase):
CONSIS_GROUP_ID = '3470cc4c-63b3-4c7a-8120-8a0693b45838'
CGSNAPSHOT_ID = '5351d914-6c90-43e7-9a8e-7e84610927da'
@ -103,12 +111,12 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
def default_mock_conf(self):
mock_conf = mock.Mock()
mock_conf.hplefthand_api_url = 'http://fake.foo:8080/lhos'
mock_conf.hplefthand_username = 'foo1'
mock_conf.hplefthand_password = 'bar2'
mock_conf.hplefthand_iscsi_chap_enabled = False
mock_conf.hplefthand_debug = False
mock_conf.hplefthand_clustername = "CloudCluster1"
mock_conf.hpelefthand_api_url = 'http://fake.foo:8080/lhos'
mock_conf.hpelefthand_username = 'foo1'
mock_conf.hpelefthand_password = 'bar2'
mock_conf.hpelefthand_iscsi_chap_enabled = False
mock_conf.hpelefthand_debug = False
mock_conf.hpelefthand_clustername = "CloudCluster1"
mock_conf.goodness_function = GOODNESS_FUNCTION
mock_conf.filter_function = FILTER_FUNCTION
mock_conf.reserved_percentage = 25
@ -122,7 +130,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
return mock_conf
@mock.patch('hplefthandclient.client.HPLeftHandClient', spec=True)
@mock.patch('hpelefthandclient.client.HPELeftHandClient', spec=True)
def setup_driver(self, _mock_client, config=None):
if config is None:
config = self.default_mock_conf()
@ -133,19 +141,19 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'spaceTotal': units.Gi * 500,
'spaceAvailable': units.Gi * 250}
db = mock.Mock()
self.driver = hp_lefthand_iscsi.HPLeftHandISCSIDriver(
self.driver = hpe_lefthand_iscsi.HPELeftHandISCSIDriver(
configuration=config, db=db)
self.driver.do_setup(None)
self.cluster_name = config.hplefthand_clustername
self.cluster_name = config.hpelefthand_clustername
return _mock_client.return_value
@mock.patch('hplefthandclient.version', "1.0.0")
@mock.patch('hpelefthandclient.version', "1.0.0")
def test_unsupported_client_version(self):
self.assertRaises(exception.InvalidInput,
self.setup_driver)
@mock.patch('hplefthandclient.version', "3.0.0")
@mock.patch('hpelefthandclient.version', "3.0.0")
def test_supported_client_version(self):
self.setup_driver()
@ -162,7 +170,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.createVolume.return_value = {
'iscsiIqn': self.connector['initiator']}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -185,7 +193,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
# mock HTTPServerError
mock_client.createVolume.side_effect =\
hpexceptions.HTTPServerError()
hpeexceptions.HTTPServerError()
# ensure the raised exception is a cinder exception
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.create_volume, self.volume)
@ -193,7 +201,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
@mock.patch.object(
volume_types,
'get_volume_type',
return_value={'extra_specs': {'hplh:provisioning': 'full'}})
return_value={'extra_specs': {'hpelh:provisioning': 'full'}})
def test_create_volume_with_es(self, _mock_volume_type):
# setup drive with default configuration
@ -208,7 +216,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'iscsiIqn': self.connector['initiator']}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -229,6 +237,51 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.assert_has_calls(expected)
@mock.patch.object(
volume_types,
'get_volume_type',
return_value={'extra_specs': (HPELeftHandBaseDriver.
old_volume_type['extra_specs'])})
def test_create_volume_old_volume_type(self, _mock_volume_type):
# setup drive with default configuration
# and return the mock HTTP LeftHand client
mock_client = self.setup_driver()
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
# mock return value of createVolume
mock_client.createVolume.return_value = {
'iscsiIqn': self.connector['initiator']}
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
# execute driver
volume_info = self.driver.create_volume(self.volume)
self.assertEqual('10.0.1.6:3260,1 iqn.1993-08.org.debian:01:222 0',
volume_info['provider_location'])
expected = self.driver_startup_call_stack + [
mock.call.createVolume(
'fakevolume',
1,
units.Gi,
{'isThinProvisioned': True,
'clusterName': 'CloudCluster1'}),
mock.call.logout()]
mock_client.assert_has_calls(expected)
# mock HTTPServerError
mock_client.createVolume.side_effect =\
hpeexceptions.HTTPServerError()
# ensure the raised exception is a cinder exception
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.create_volume, self.volume)
def test_delete_volume(self):
# setup drive with default configuration
@ -239,7 +292,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -255,12 +308,12 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
# mock HTTPNotFound (volume not found)
mock_client.getVolumeByName.side_effect =\
hpexceptions.HTTPNotFound()
hpeexceptions.HTTPNotFound()
# no exception should escape method
self.driver.delete_volume(self.volume)
# mock HTTPConflict
mock_client.deleteVolume.side_effect = hpexceptions.HTTPConflict()
mock_client.deleteVolume.side_effect = hpeexceptions.HTTPConflict()
# ensure the raised exception is a cinder exception
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.delete_volume, self.volume_id)
@ -275,7 +328,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -292,7 +345,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
# mock HTTPServerError (array failure)
mock_client.modifyVolume.side_effect =\
hpexceptions.HTTPServerError()
hpeexceptions.HTTPServerError()
# ensure the raised exception is a cinder exception
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.extend_volume, self.volume, 2)
@ -304,7 +357,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client = self.setup_driver()
# mock return value of getVolumeByName
mock_client.getServerByName.side_effect = hpexceptions.HTTPNotFound()
mock_client.getServerByName.side_effect = hpeexceptions.HTTPNotFound()
mock_client.createServer.return_value = {'id': self.server_id}
mock_client.getVolumeByName.return_value = {
'id': self.volume_id,
@ -312,7 +365,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -344,7 +397,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
# mock HTTPServerError (array failure)
mock_client.createServer.side_effect =\
hpexceptions.HTTPServerError()
hpeexceptions.HTTPServerError()
# ensure the raised exception is a cinder exception
self.assertRaises(
exception.VolumeBackendAPIException,
@ -357,7 +410,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client = self.setup_driver()
# mock return value of getVolumeByName
mock_client.getServerByName.side_effect = hpexceptions.HTTPNotFound()
mock_client.getServerByName.side_effect = hpeexceptions.HTTPNotFound()
mock_client.createServer.return_value = {'id': self.server_id}
mock_client.getVolumeByName.return_value = {
'id': self.volume_id,
@ -365,7 +418,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -401,7 +454,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client = self.setup_driver()
# mock return value of getVolumeByName
mock_client.getServerByName.side_effect = hpexceptions.HTTPNotFound()
mock_client.getServerByName.side_effect = hpeexceptions.HTTPNotFound()
mock_client.createServer.return_value = {
'id': self.server_id,
'chapAuthenticationRequired': True,
@ -412,7 +465,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -455,7 +508,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.findServerVolumes.return_value = [{'id': self.volume_id}]
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -473,7 +526,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.assert_has_calls(expected)
mock_client.getVolumeByName.side_effect = (
hpexceptions.HTTPNotFound())
hpeexceptions.HTTPNotFound())
# ensure the raised exception is a cinder exception
self.assertRaises(
exception.VolumeBackendAPIException,
@ -496,7 +549,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
{'id': 99999}]
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -514,7 +567,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.assertFalse(mock_client.deleteServer.called)
mock_client.getVolumeByName.side_effect = (
hpexceptions.HTTPNotFound())
hpeexceptions.HTTPNotFound())
# ensure the raised exception is a cinder exception
self.assertRaises(
exception.VolumeBackendAPIException,
@ -531,7 +584,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -552,7 +605,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
# mock HTTPServerError (array failure)
mock_client.getVolumeByName.side_effect =\
hpexceptions.HTTPNotFound()
hpeexceptions.HTTPNotFound()
# ensure the raised exception is a cinder exception
self.assertRaises(
exception.VolumeBackendAPIException,
@ -567,7 +620,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.getSnapshotByName.return_value = {'id': self.snapshot_id}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -583,12 +636,12 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.assert_has_calls(expected)
mock_client.getSnapshotByName.side_effect =\
hpexceptions.HTTPNotFound()
hpeexceptions.HTTPNotFound()
# no exception is thrown, just error msg is logged
self.driver.delete_snapshot(self.snapshot)
# mock HTTPServerError (array failure)
ex = hpexceptions.HTTPServerError({'message': 'Some message.'})
ex = hpeexceptions.HTTPServerError({'message': 'Some message.'})
mock_client.getSnapshotByName.side_effect = ex
# ensure the raised exception is a cinder exception
self.assertRaises(
@ -597,7 +650,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.snapshot)
# mock HTTPServerError because the snap is in use
ex = hpexceptions.HTTPServerError({
ex = hpeexceptions.HTTPServerError({
'message':
'Hey, dude cannot be deleted because it is a clone point'
' duh.'})
@ -619,7 +672,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'iscsiIqn': self.connector['initiator']}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -651,7 +704,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'iscsiIqn': self.connector['initiator']}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -684,7 +737,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'extra_specs': {
'foo:bar': 'fake',
'bar:foo': 1234,
'hplh:provisioning': 'full'}}
'hpelh:provisioning': 'full'}}
volume_with_vt = self.volume
volume_with_vt['volume_type_id'] = self.volume_type_id
@ -694,7 +747,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
volume_with_vt)
extra_specs = self.driver._get_lh_extra_specs(
volume_extra_specs,
hp_lefthand_iscsi.extra_specs_key_map.keys())
hpe_lefthand_iscsi.extra_specs_key_map.keys())
# map the extra specs key/value pairs to key/value pairs
# used as optional configuration values by the LeftHand backend
@ -713,24 +766,24 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
_mock_get_volume_type.return_value = {
'extra_specs': {
# r-07 is an invalid value for hplh:ao
'hplh:data_pl': 'r-07',
'hplh:ao': 'true'}}
# r-07 is an invalid value for hpelh:ao
'hpelh:data_pl': 'r-07',
'hpelh:ao': 'true'}}
# get the extra specs of interest from this volume's volume type
volume_extra_specs = self.driver._get_volume_extra_specs(
volume_with_vt)
extra_specs = self.driver._get_lh_extra_specs(
volume_extra_specs,
hp_lefthand_iscsi.extra_specs_key_map.keys())
hpe_lefthand_iscsi.extra_specs_key_map.keys())
# map the extra specs key/value pairs to key/value pairs
# used as optional configuration values by the LeftHand backend
optional = self.driver._map_extra_specs(extra_specs)
# {'hplh:ao': 'true'} should map to
# {'hpelh:ao': 'true'} should map to
# {'isAdaptiveOptimizationEnabled': True}
# without hplh:data_pl since r-07 is an invalid value
# without hpelh:data_pl since r-07 is an invalid value
self.assertDictMatch({'isAdaptiveOptimizationEnabled': True}, optional)
def test_retype_with_no_LH_extra_specs(self):
@ -756,7 +809,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
volume['host'] = host
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -779,8 +832,8 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
ctxt = context.get_admin_context()
host = {'host': self.serverName}
key_specs_old = {'hplh:provisioning': 'thin'}
key_specs_new = {'hplh:provisioning': 'full', 'hplh:ao': 'true'}
key_specs_old = {'hpelh:provisioning': 'thin'}
key_specs_new = {'hpelh:provisioning': 'full', 'hpelh:ao': 'true'}
old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)
@ -793,7 +846,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
volume['host'] = host
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -820,8 +873,8 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
ctxt = context.get_admin_context()
host = {'host': self.serverName}
key_specs_old = {'hplh:provisioning': 'full', 'foo': 'bar'}
key_specs_new = {'hplh:provisioning': 'thin', 'foo': 'foobar'}
key_specs_old = {'hpelh:provisioning': 'full', 'foo': 'bar'}
key_specs_new = {'hpelh:provisioning': 'thin', 'foo': 'foobar'}
old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)
@ -834,7 +887,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
volume['host'] = host
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -858,8 +911,8 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
ctxt = context.get_admin_context()
host = {'host': self.serverName}
key_specs_old = {'hplh:provisioning': 'full', 'hplh:ao': 'true'}
key_specs_new = {'hplh:provisioning': 'full', 'hplh:ao': 'false'}
key_specs_old = {'hpelh:provisioning': 'full', 'hpelh:ao': 'true'}
key_specs_new = {'hpelh:provisioning': 'full', 'hpelh:ao': 'false'}
old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)
@ -872,7 +925,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
volume['host'] = host
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -895,7 +948,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
host = {'host': self.serverName, 'capabilities': {}}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -929,7 +982,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'host': self.serverName,
'capabilities': {'location_info': location}}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -973,7 +1026,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'host': self.serverName,
'capabilities': {'location_info': location}}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1024,7 +1077,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'host': self.serverName,
'capabilities': {'location_info': location}}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1059,7 +1112,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'_name_id': clone_id,
'provider_location': provider_location}
original_volume_status = 'available'
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
actual_update = self.driver.update_migrated_volume(
@ -1081,7 +1134,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'provider_location': provider_location}
original_volume_status = 'in-use'
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
actual_update = self.driver.update_migrated_volume(
@ -1093,7 +1146,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.assertEqual(expected_update, actual_update)
@mock.patch.object(volume_types, 'get_volume_type',
return_value={'extra_specs': {'hplh:ao': 'true'}})
return_value={'extra_specs': {'hpelh:ao': 'true'}})
def test_create_volume_with_ao_true(self, _mock_volume_type):
# setup drive with default configuration
@ -1108,7 +1161,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'iscsiIqn': self.connector['initiator']}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1131,7 +1184,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.assert_has_calls(expected)
@mock.patch.object(volume_types, 'get_volume_type',
return_value={'extra_specs': {'hplh:ao': 'false'}})
return_value={'extra_specs': {'hpelh:ao': 'false'}})
def test_create_volume_with_ao_false(self, _mock_volume_type):
# setup drive with default configuration
@ -1146,7 +1199,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'iscsiIqn': self.connector['initiator']}
mock_client.getVolumes.return_value = {'total': 1, 'members': []}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1193,7 +1246,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'volume_type_id': None,
'id': '12345'}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
@ -1231,9 +1284,9 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'name': 'gold',
'id': 'gold-id',
'extra_specs': {
'hplh:provisioning': 'thin',
'hplh:ao': 'true',
'hplh:data_pl': 'r-0',
'hpelh:provisioning': 'thin',
'hpelh:ao': 'true',
'hpelh:data_pl': 'r-0',
'volume_type': self.volume_type}}
self.driver.api_version = "1.1"
@ -1244,7 +1297,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'volume_type_id': 'bcfa9fa4-54a0-4340-a3d8-bfcf19aea65e',
'id': '12345'}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
@ -1282,9 +1335,9 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'name': 'gold',
'id': 'gold-id',
'extra_specs': {
'hplh:provisioning': 'thin',
'hplh:ao': 'true',
'hplh:data_pl': 'r-0',
'hpelh:provisioning': 'thin',
'hpelh:ao': 'true',
'hpelh:data_pl': 'r-0',
'volume_type': self.volume_type}}
self.driver.retype = mock.Mock(
@ -1298,7 +1351,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'volume_type_id': 'bcfa9fa4-54a0-4340-a3d8-bfcf19aea65e',
'id': '12345'}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
@ -1342,7 +1395,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
'volume_type_id': 'bcfa9fa4-54a0-4340-a3d8-bfcf19aea65e',
'id': '12345'}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
mock_client.getVolumeByName.return_value = {'id': self.volume_id}
@ -1374,7 +1427,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.driver.api_version = "1.1"
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
mock_client.getVolumes.return_value = {
@ -1407,7 +1460,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.driver.api_version = "1.1"
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1433,11 +1486,11 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
def test_manage_existing_get_size_invalid_input(self):
mock_client = self.setup_driver()
mock_client.getVolumeByName.side_effect = (
hpexceptions.HTTPNotFound('fake'))
hpeexceptions.HTTPNotFound('fake'))
self.driver.api_version = "1.1"
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
mock_client.getVolumes.return_value = {
@ -1481,7 +1534,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.driver.api_version = "1.1"
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
self.driver.unmanage(self.volume)
@ -1523,7 +1576,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
}]
}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1555,7 +1608,6 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.assert_has_calls(expected)
@mock.patch('hplefthandclient.version', "1.0.6")
def test_create_consistencygroup(self):
class fake_consitencygroup_object(object):
volume_type_id = '371c64d5-b92a-488c-bc14-1e63cef40e08'
@ -1568,7 +1620,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
# set up driver with default config
mock_client = self.setup_driver()
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1578,7 +1630,6 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.assertEqual('available', cg['status'])
@mock.patch('hplefthandclient.version', "1.0.6")
def test_delete_consistencygroup(self):
class fake_consitencygroup_object(object):
volume_type_id = '371c64d5-b92a-488c-bc14-1e63cef40e08'
@ -1595,7 +1646,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
expected_volumes = [mock_volume]
self.driver.db.volume_get_all_by_group.return_value = expected_volumes
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1609,7 +1660,6 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
cg, vols = self.driver.delete_consistencygroup(ctxt, group, [])
self.assertEqual('deleting', cg['status'])
@mock.patch('hplefthandclient.version', "1.0.6")
def test_update_consistencygroup_add_vol_delete_cg(self):
class fake_consitencygroup_object(object):
volume_type_id = '371c64d5-b92a-488c-bc14-1e63cef40e08'
@ -1633,7 +1683,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.createVolume.return_value = {
'iscsiIqn': self.connector['initiator']}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1651,7 +1701,6 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
cg, vols = self.driver.delete_consistencygroup(ctxt, group, [])
self.assertEqual('deleting', cg['status'])
@mock.patch('hplefthandclient.version', "1.0.6")
def test_update_consistencygroup_remove_vol_delete_cg(self):
class fake_consitencygroup_object(object):
volume_type_id = '371c64d5-b92a-488c-bc14-1e63cef40e08'
@ -1675,7 +1724,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
mock_client.createVolume.return_value = {
'iscsiIqn': self.connector['initiator']}
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1698,7 +1747,6 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.assertEqual('deleting', cg['status'])
@mock.patch('cinder.objects.snapshot.SnapshotList.get_all_for_cgsnapshot')
@mock.patch('hplefthandclient.version', "1.0.6")
def test_create_cgsnapshot(self, mock_snap_list):
class fake_consitencygroup_object(object):
volume_type_id = '371c64d5-b92a-488c-bc14-1e63cef40e08'
@ -1720,7 +1768,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
expected_snaps = [mock_snap]
mock_snap_list.return_value = expected_snaps
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client
@ -1739,7 +1787,6 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
self.assertEqual('available', cgsnap['status'])
@mock.patch('cinder.objects.snapshot.SnapshotList.get_all_for_cgsnapshot')
@mock.patch('hplefthandclient.version', "1.0.6")
def test_delete_cgsnapshot(self, mock_snap_list):
class fake_consitencygroup_object(object):
volume_type_id = '371c64d5-b92a-488c-bc14-1e63cef40e08'
@ -1761,7 +1808,7 @@ class TestHPLeftHandISCSIDriver(HPLeftHandBaseDriver, test.TestCase):
expected_snaps = [mock_snap]
mock_snap_list.return_value = expected_snaps
with mock.patch.object(hp_lefthand_iscsi.HPLeftHandISCSIDriver,
with mock.patch.object(hpe_lefthand_iscsi.HPELeftHandISCSIDriver,
'_create_client') as mock_do_setup:
mock_do_setup.return_value = mock_client

View File

@ -1,4 +1,4 @@
# (c) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
# (c) Copyright 2014-2015 Hewlett Packard Enterprise Development LP
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -13,7 +13,26 @@
# License for the specific language governing permissions and limitations
# under the License.
#
"""HP LeftHand SAN ISCSI REST Proxy."""
"""HPE LeftHand SAN ISCSI REST Proxy.
Volume driver for HPE LeftHand Storage array.
This driver requires 11.5 or greater firmware on the LeftHand array, using
the 2.0 or greater version of the hpelefthandclient.
You will need to install the python hpelefthandclient module.
sudo pip install python-lefthandclient
Set the following in the cinder.conf file to enable the
LeftHand iSCSI REST Driver along with the required flags:
volume_driver=cinder.volume.drivers.hpe.hpe_lefthand_iscsi.
HPELeftHandISCSIDriver
It also requires the setting of hpelefthand_api_url, hpelefthand_username,
hpelefthand_password for credentials to talk to the REST service on the
LeftHand array.
"""
from oslo_config import cfg
from oslo_log import log as logging
@ -36,41 +55,53 @@ import re
LOG = logging.getLogger(__name__)
hplefthandclient = importutils.try_import("hplefthandclient")
if hplefthandclient:
from hplefthandclient import client as hp_lh_client
from hplefthandclient import exceptions as hpexceptions
hpelefthandclient = importutils.try_import("hpelefthandclient")
if hpelefthandclient:
from hpelefthandclient import client as hpe_lh_client
from hpelefthandclient import exceptions as hpeexceptions
hplefthand_opts = [
cfg.StrOpt('hplefthand_api_url',
help="HP LeftHand WSAPI Server Url like "
"https://<LeftHand ip>:8081/lhos"),
cfg.StrOpt('hplefthand_username',
help="HP LeftHand Super user username"),
cfg.StrOpt('hplefthand_password',
help="HP LeftHand Super user password",
secret=True),
cfg.StrOpt('hplefthand_clustername',
help="HP LeftHand cluster name"),
cfg.BoolOpt('hplefthand_iscsi_chap_enabled',
hpelefthand_opts = [
cfg.StrOpt('hpelefthand_api_url',
default=None,
help="HPE LeftHand WSAPI Server Url like "
"https://<LeftHand ip>:8081/lhos",
deprecated_name='hplefthand_api_url'),
cfg.StrOpt('hpelefthand_username',
default=None,
help="HPE LeftHand Super user username",
deprecated_name='hplefthand_username'),
cfg.StrOpt('hpelefthand_password',
default=None,
help="HPE LeftHand Super user password",
secret=True,
deprecated_name='hplefthand_password'),
cfg.StrOpt('hpelefthand_clustername',
default=None,
help="HPE LeftHand cluster name",
deprecated_name='hplefthand_clustername'),
cfg.BoolOpt('hpelefthand_iscsi_chap_enabled',
default=False,
help='Configure CHAP authentication for iSCSI connections '
'(Default: Disabled)'),
cfg.BoolOpt('hplefthand_debug',
'(Default: Disabled)',
deprecated_name='hplefthand_iscsi_chap_enabled'),
cfg.BoolOpt('hpelefthand_debug',
default=False,
help="Enable HTTP debugging to LeftHand"),
help="Enable HTTP debugging to LeftHand",
deprecated_name='hplefthand_debug'),
]
CONF = cfg.CONF
CONF.register_opts(hplefthand_opts)
CONF.register_opts(hpelefthand_opts)
MIN_API_VERSION = "1.1"
MIN_CLIENT_VERSION = '1.0.4'
MIN_CG_CLIENT_VERSION = "1.0.6"
MIN_CLIENT_VERSION = '2.0.0'
# map the extra spec key to the REST client option key
extra_specs_key_map = {
'hpelh:provisioning': 'isThinProvisioned',
'hpelh:ao': 'isAdaptiveOptimizationEnabled',
'hpelh:data_pl': 'dataProtectionLevel',
'hplh:provisioning': 'isThinProvisioned',
'hplh:ao': 'isAdaptiveOptimizationEnabled',
'hplh:data_pl': 'dataProtectionLevel',
@ -85,8 +116,8 @@ extra_specs_value_map = {
}
class HPLeftHandISCSIDriver(driver.ISCSIDriver):
"""Executes REST commands relating to HP/LeftHand SAN ISCSI volumes.
class HPELeftHandISCSIDriver(driver.ISCSIDriver):
"""Executes REST commands relating to HPE/LeftHand SAN ISCSI volumes.
Version history:
1.0.0 - Initial REST iSCSI proxy
@ -108,17 +139,18 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
1.0.12 - Adds consistency group support
1.0.13 - Added update_migrated_volume #1493546
1.0.14 - Removed the old CLIQ based driver
2.0.0 - Rebranded HP to HPE
"""
VERSION = "1.0.14"
VERSION = "2.0.0"
device_stats = {}
def __init__(self, *args, **kwargs):
super(HPLeftHandISCSIDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(hplefthand_opts)
if not self.configuration.hplefthand_api_url:
raise exception.NotFound(_("HPLeftHand url not found"))
super(HPELeftHandISCSIDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(hpelefthand_opts)
if not self.configuration.hpelefthand_api_url:
raise exception.NotFound(_("HPELeftHand url not found"))
# blank is the only invalid character for cluster names
# so we need to use it as a separator
@ -128,21 +160,21 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
def _login(self):
client = self._create_client()
try:
if self.configuration.hplefthand_debug:
if self.configuration.hpelefthand_debug:
client.debug_rest(True)
client.login(
self.configuration.hplefthand_username,
self.configuration.hplefthand_password)
self.configuration.hpelefthand_username,
self.configuration.hpelefthand_password)
cluster_info = client.getClusterByName(
self.configuration.hplefthand_clustername)
self.configuration.hpelefthand_clustername)
self.cluster_id = cluster_info['id']
virtual_ips = cluster_info['virtualIPAddresses']
self.cluster_vip = virtual_ips[0]['ipV4Address']
return client
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
raise exception.DriverNotInitialized(
_('LeftHand cluster not found'))
except Exception as ex:
@ -152,16 +184,18 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
client.logout()
def _create_client(self):
return hp_lh_client.HPLeftHandClient(
self.configuration.hplefthand_api_url)
return hpe_lh_client.HPELeftHandClient(
self.configuration.hpelefthand_api_url)
def do_setup(self, context):
"""Set up LeftHand client."""
if hplefthandclient.version < MIN_CLIENT_VERSION:
ex_msg = (_("Invalid hplefthandclient version found ("
if hpelefthandclient.version < MIN_CLIENT_VERSION:
ex_msg = (_("Invalid hpelefthandclient version found ("
"%(found)s). Version %(minimum)s or greater "
"required.")
% {'found': hplefthandclient.version,
"required. Run 'pip install --upgrade "
"python-lefthandclient' to upgrade the "
"hpelefthandclient.")
% {'found': hpelefthandclient.version,
'minimum': MIN_CLIENT_VERSION})
LOG.error(ex_msg)
raise exception.InvalidInput(reason=ex_msg)
@ -172,10 +206,10 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
try:
self.api_version = client.getApiVersion()
LOG.info(_LI("HPLeftHand API version %s"), self.api_version)
LOG.info(_LI("HPELeftHand API version %s"), self.api_version)
if self.api_version < MIN_API_VERSION:
LOG.warning(_LW("HPLeftHand API is version %(current)s. "
LOG.warning(_LW("HPELeftHand API is version %(current)s. "
"A minimum version of %(min)s is needed for "
"manage/unmanage support."),
{'current': self.api_version,
@ -184,9 +218,9 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
self._logout(client)
def get_version_string(self):
return (_('REST %(proxy_ver)s hplefthandclient %(rest_ver)s') % {
return (_('REST %(proxy_ver)s hpelefthandclient %(rest_ver)s') % {
'proxy_ver': self.VERSION,
'rest_ver': hplefthandclient.get_version_string()})
'rest_ver': hpelefthandclient.get_version_string()})
def create_volume(self, volume):
"""Creates a volume."""
@ -215,7 +249,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
if optional.get('isAdaptiveOptimizationEnabled'):
del optional['isAdaptiveOptimizationEnabled']
clusterName = self.configuration.hplefthand_clustername
clusterName = self.configuration.hpelefthand_clustername
optional['clusterName'] = clusterName
volume_info = client.createVolume(
@ -235,7 +269,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
try:
volume_info = client.getVolumeByName(volume['name'])
client.deleteVolume(volume_info['id'])
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
LOG.error(_LE("Volume did not exist. It will not be deleted"))
except Exception as ex:
raise exception.VolumeBackendAPIException(ex)
@ -368,10 +402,10 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
snap_name = snap_name_base + "-" + six.text_type(i)
snap_info = client.getSnapshotByName(snap_name)
client.deleteSnapshot(snap_info['id'])
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
LOG.error(_LE("Snapshot did not exist. It will not be "
"deleted."))
except hpexceptions.HTTPServerError as ex:
except hpeexceptions.HTTPServerError as ex:
in_use_msg = ('cannot be deleted because it is a clone '
'point')
if in_use_msg in ex.get_description():
@ -411,9 +445,9 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
try:
snap_info = client.getSnapshotByName(snapshot['name'])
client.deleteSnapshot(snap_info['id'])
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
LOG.error(_LE("Snapshot did not exist. It will not be deleted"))
except hpexceptions.HTTPServerError as ex:
except hpeexceptions.HTTPServerError as ex:
in_use_msg = 'cannot be deleted because it is a clone point'
if in_use_msg in ex.get_description():
raise exception.SnapshotIsBusy(snapshot_name=snapshot['name'])
@ -444,9 +478,9 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
data['reserved_percentage'] = (
self.configuration.safe_get('reserved_percentage'))
data['storage_protocol'] = 'iSCSI'
data['vendor_name'] = 'Hewlett-Packard'
data['vendor_name'] = 'Hewlett Packard Enterprise'
data['location_info'] = (self.DRIVER_LOCATION % {
'cluster': self.configuration.hplefthand_clustername,
'cluster': self.configuration.hpelefthand_clustername,
'vip': self.cluster_vip})
data['thin_provisioning_support'] = True
data['thick_provisioning_support'] = True
@ -472,7 +506,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
total_volumes = 0
provisioned_size = 0
volumes = client.getVolumes(
cluster=self.configuration.hplefthand_clustername,
cluster=self.configuration.hpelefthand_clustername,
fields=['members[id]', 'members[clusterName]', 'members[size]'])
if volumes:
total_volumes = volumes['total']
@ -483,8 +517,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
data['total_volumes'] = total_volumes
data['filter_function'] = self.get_filter_function()
data['goodness_function'] = self.get_goodness_function()
if hplefthandclient.version >= MIN_CG_CLIENT_VERSION:
data['consistencygroup_support'] = True
data['consistencygroup_support'] = True
self.device_stats = data
@ -492,7 +525,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
"""Assigns the volume to a server.
Assign any created volume to a compute node/host so that it can be
used from that host. HP VSA requires a volume to be assigned
used from that host. HPE VSA requires a volume to be assigned
to a server.
"""
client = self._login()
@ -595,6 +628,10 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
extra_specs_of_interest = {}
for key, value in extra_specs.items():
if key in valid_keys:
prefix = key.split(":")
if prefix[0] == "hplh":
LOG.warning(_LW("The 'hplh' prefix is deprecated. Use "
"'hpelh' instead."))
extra_specs_of_interest[key] = value
return extra_specs_of_interest
@ -626,7 +663,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
def _create_server(self, connector, client):
server_info = None
chap_enabled = self.configuration.hplefthand_iscsi_chap_enabled
chap_enabled = self.configuration.hpelefthand_iscsi_chap_enabled
try:
server_info = client.getServerByName(connector['host'])
chap_secret = server_info['chapTargetSecret']
@ -637,7 +674,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
LOG.warning(_LW('CHAP is enabled, but server secret not '
'configured on server %s'), connector['host'])
return server_info
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
# server does not exist, so create one
pass
@ -705,7 +742,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
if len(options) > 0:
client.modifyVolume(volume_info['id'], options)
return True
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
raise exception.VolumeNotFound(volume_id=volume['id'])
except Exception as ex:
LOG.warning(_LW("%s"), ex)
@ -739,7 +776,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
'cluster=%(cluster)s', {
'id': volume['id'],
'host': host,
'cluster': self.configuration.hplefthand_clustername})
'cluster': self.configuration.hpelefthand_clustername})
false_ret = (False, None)
if 'location_info' not in host['capabilities']:
@ -765,7 +802,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
"management group."), volume['name'])
return false_ret
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
LOG.info(_LI("Cannot provide backend assisted migration for "
"volume: %s because cluster exists in different "
"management group."), volume['name'])
@ -798,12 +835,12 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
options = {'clusterName': cluster}
client.modifyVolume(volume_info['id'], options)
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
LOG.info(_LI("Cannot provide backend assisted migration for "
"volume: %s because volume does not exist in this "
"management group."), volume['name'])
return false_ret
except hpexceptions.HTTPServerError as ex:
except hpeexceptions.HTTPServerError as ex:
LOG.error(_LE("Exception: %s"), ex)
return false_ret
finally:
@ -865,7 +902,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
client = self._login()
try:
volume_info = client.getVolumeByName(target_vol_name)
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
err = (_("Virtual volume '%s' doesn't exist on array.") %
target_vol_name)
LOG.error(err)
@ -963,7 +1000,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
client = self._login()
try:
volume_info = client.getVolumeByName(target_vol_name)
except hpexceptions.HTTPNotFound:
except hpeexceptions.HTTPNotFound:
err = (_("Virtual volume '%s' doesn't exist on array.") %
target_vol_name)
LOG.error(err)
@ -1012,7 +1049,7 @@ class HPLeftHandISCSIDriver(driver.ISCSIDriver):
def _check_api_version(self):
"""Checks that the API version is correct."""
if (self.api_version < MIN_API_VERSION):
ex_msg = (_('Invalid HPLeftHand API version found: %(found)s. '
ex_msg = (_('Invalid HPELeftHand API version found: %(found)s. '
'Version %(minimum)s or greater required for '
'manage/unmanage support.')
% {'found': self.api_version,

View File

@ -126,7 +126,10 @@ MAPPING = {
'cinder.volume.drivers.san.hp.hp_3par_fc.HP3PARFCDriver':
'cinder.volume.drivers.hpe.hpe_3par_fc.HPE3PARFCDriver',
'cinder.volume.drivers.san.hp.hp_3par_iscsi.HP3PARISCSIDriver':
'cinder.volume.drivers.hpe.hpe_3par_iscsi.HPE3PARISCSIDriver', }
'cinder.volume.drivers.hpe.hpe_3par_iscsi.HPE3PARISCSIDriver',
'cinder.volume.drivers.san.hp.hp_lefthand_iscsi.HPLeftHandISCSIDriver':
'cinder.volume.drivers.hpe.hpe_lefthand_iscsi.HPELeftHandISCSIDriver',
}
def locked_volume_operation(f):

View File

@ -70,7 +70,7 @@ cinder.tests.unit.test_hitachi_hnas_backend
cinder.tests.unit.test_hitachi_hnas_iscsi
cinder.tests.unit.test_hitachi_hnas_nfs
cinder.tests.unit.test_hp_xp_fc
cinder.tests.unit.test_hplefthand
cinder.tests.unit.test_hpelefthand
cinder.tests.unit.test_huawei_drivers
cinder.tests.unit.test_huawei_drivers_compatibility
cinder.tests.unit.test_ibm_flashsystem