diff --git a/cinder/tests/unit/fake_hp_lefthand_client.py b/cinder/tests/unit/fake_hpe_lefthand_client.py similarity index 63% rename from cinder/tests/unit/fake_hp_lefthand_client.py rename to cinder/tests/unit/fake_hpe_lefthand_client.py index 8a27921a6d9..404f00bffa5 100644 --- a/cinder/tests/unit/fake_hp_lefthand_client.py +++ b/cinder/tests/unit/fake_hpe_lefthand_client.py @@ -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 diff --git a/cinder/tests/unit/test_hplefthand.py b/cinder/tests/unit/test_hpelefthand.py similarity index 88% rename from cinder/tests/unit/test_hplefthand.py rename to cinder/tests/unit/test_hpelefthand.py index 31dbcd1c466..5d4379dd692 100644 --- a/cinder/tests/unit/test_hplefthand.py +++ b/cinder/tests/unit/test_hpelefthand.py @@ -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 diff --git a/cinder/volume/drivers/san/hp/hp_lefthand_iscsi.py b/cinder/volume/drivers/hpe/hpe_lefthand_iscsi.py similarity index 88% rename from cinder/volume/drivers/san/hp/hp_lefthand_iscsi.py rename to cinder/volume/drivers/hpe/hpe_lefthand_iscsi.py index fe6b6ba9779..2bdd34b2c5b 100644 --- a/cinder/volume/drivers/san/hp/hp_lefthand_iscsi.py +++ b/cinder/volume/drivers/hpe/hpe_lefthand_iscsi.py @@ -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://: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://: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, diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 72845ccf514..2a637cfd88f 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -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): diff --git a/tests-py3.txt b/tests-py3.txt index fe50c167986..ba29aaa2e6b 100644 --- a/tests-py3.txt +++ b/tests-py3.txt @@ -71,7 +71,7 @@ cinder.tests.unit.test_hitachi_hnas_iscsi cinder.tests.unit.test_hitachi_hnas_nfs cinder.tests.unit.test_hpe3par 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