From 541cc9d53ac999535edcb7a02d1a76a883cfb02b Mon Sep 17 00:00:00 2001 From: Mark Sturdevant Date: Mon, 5 May 2014 14:13:48 -0700 Subject: [PATCH] eliminate the need for hp3parclient in tests In order to eliminate the need to have the hp3parclient in the global-requirements project, we need to remove the hp3parclient from being imported in all 3par driver unit tests in cinder. Closes-Bug: #1315195 Change-Id: Ife5c70871e742be5970be8f0284e12554f93cab4 --- cinder/tests/fake_hp_3par_client.py | 27 ++++++++ cinder/tests/fake_hp_client_exceptions.py | 57 +++++++++++++++++ cinder/tests/test_hp3par.py | 64 +++++++------------ .../volume/drivers/san/hp/hp_3par_common.py | 15 +++-- cinder/volume/drivers/san/hp/hp_3par_fc.py | 5 +- cinder/volume/drivers/san/hp/hp_3par_iscsi.py | 5 +- test-requirements.txt | 1 - 7 files changed, 126 insertions(+), 48 deletions(-) create mode 100644 cinder/tests/fake_hp_3par_client.py create mode 100644 cinder/tests/fake_hp_client_exceptions.py diff --git a/cinder/tests/fake_hp_3par_client.py b/cinder/tests/fake_hp_3par_client.py new file mode 100644 index 000000000..2834c0150 --- /dev/null +++ b/cinder/tests/fake_hp_3par_client.py @@ -0,0 +1,27 @@ +# (c) Copyright 2014 Hewlett-Packard Development Company, L.P. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +"""Fake HP client for testing 3PAR without installing the client.""" + +import mock +import sys + +from cinder.tests import fake_hp_client_exceptions as hpexceptions + +hp3par = mock.Mock() +hp3par.version = "3.0.0" +hp3par.exceptions = hpexceptions + +sys.modules['hp3parclient'] = hp3par diff --git a/cinder/tests/fake_hp_client_exceptions.py b/cinder/tests/fake_hp_client_exceptions.py new file mode 100644 index 000000000..295b710ca --- /dev/null +++ b/cinder/tests/fake_hp_client_exceptions.py @@ -0,0 +1,57 @@ +# (c) Copyright 2014 Hewlett-Packard Development Company, L.P. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +"""Fake HP client exceptions to use when mocking HP clients.""" + + +class HTTPConflict(Exception): + http_status = 409 + message = "Conflict" + + +class HTTPNotFound(Exception): + http_status = 404 + message = "Not found" + + +class HTTPForbidden(Exception): + http_status = 403 + message = "Forbidden" + + def __init__(self, error=None): + if error: + if 'code' in error: + self._error_code = error['code'] + + def get_code(self): + return self._error_code + + +class HTTPBadRequest(Exception): + http_status = 400 + message = "Bad request" + + +class HTTPServerError(Exception): + http_status = 500 + message = "Error" + + def __init__(self, error=None): + if error: + if 'message' in error: + self._error_desc = error['message'] + + def get_description(self): + return self._error_desc diff --git a/cinder/tests/test_hp3par.py b/cinder/tests/test_hp3par.py index ff47caefa..ce1018145 100644 --- a/cinder/tests/test_hp3par.py +++ b/cinder/tests/test_hp3par.py @@ -17,19 +17,20 @@ import mock -from hp3parclient import client -from hp3parclient import exceptions as hpexceptions - from cinder import context from cinder import exception from cinder.openstack.common import log as logging from cinder import test from cinder import units + +from cinder.tests import fake_hp_3par_client as hp3parclient from cinder.volume.drivers.san.hp import hp_3par_fc as hpfcdriver from cinder.volume.drivers.san.hp import hp_3par_iscsi as hpdriver from cinder.volume import qos_specs from cinder.volume import volume_types +hpexceptions = hp3parclient.hpexceptions + LOG = logging.getLogger(__name__) HP3PAR_CPG = 'OpenStackCPG' @@ -157,6 +158,18 @@ class HP3PARBaseDriver(object): 'state': 1, 'uuid': '29c214aa-62b9-41c8-b198-543f6cf24edf'}] + mock_client_conf = { + 'PORT_MODE_TARGET': 2, + 'PORT_STATE_READY': 4, + 'PORT_PROTO_ISCSI': 2, + 'PORT_PROTO_FC': 1, + 'TASK_DONE': 1, + 'HOST_EDIT_ADD': 1, + 'getPorts.return_value': { + 'members': FAKE_FC_PORTS + [FAKE_ISCSI_PORT] + } + } + def setup_configuration(self): configuration = mock.Mock() configuration.hp3par_debug = False @@ -181,15 +194,15 @@ class HP3PARBaseDriver(object): @mock.patch( 'hp3parclient.client.HP3ParClient', spec=True, - PORT_MODE_TARGET=client.HP3ParClient.PORT_MODE_TARGET, - PORT_STATE_READY=client.HP3ParClient.PORT_STATE_READY, - PORT_PROTO_ISCSI=client.HP3ParClient.PORT_PROTO_ISCSI, - PORT_PROTO_FC=client.HP3ParClient.PORT_PROTO_FC, - TASK_DONE=client.HP3ParClient.TASK_DONE, - HOST_EDIT_ADD=client.HP3ParClient.HOST_EDIT_ADD) + ) def setup_mock_client(self, _m_client, driver, conf=None, m_conf=None): _m_client = _m_client.return_value + + # Configure the base constants, defaults etc... + _m_client.configure_mock(**self.mock_client_conf) + + # If m_conf, drop those over the top of the base_conf. if m_conf is not None: _m_client.configure_mock(**m_conf) @@ -304,8 +317,6 @@ class HP3PARBaseDriver(object): def test_migrate_volume(self): conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getStorageSystemInfo.return_value': { 'serialNumber': '1234'}, 'getTask.return_value': { @@ -356,8 +367,6 @@ class HP3PARBaseDriver(object): def test_migrate_volume_diff_host(self): conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getStorageSystemInfo.return_value': { 'serialNumber': 'different'}, } @@ -383,8 +392,6 @@ class HP3PARBaseDriver(object): def test_migrate_volume_diff_domain(self): conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getStorageSystemInfo.return_value': { 'serialNumber': '1234'}, 'getTask.return_value': { @@ -413,16 +420,8 @@ class HP3PARBaseDriver(object): self.assertEqual((False, None), result) def test_migrate_volume_attached(self): - conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, - 'getStorageSystemInfo.return_value': { - 'serialNumber': '1234'}, - 'getTask.return_value': { - 'status': 1} - } - mock_client = self.setup_driver(mock_conf=conf) + mock_client = self.setup_driver() volume = {'name': HP3PARBaseDriver.VOLUME_NAME, 'id': HP3PARBaseDriver.CLONE_ID, @@ -596,8 +595,6 @@ class HP3PARBaseDriver(object): # setup_mock_client drive with default configuration # and return the mock HTTP 3PAR client conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getTask.return_value': { 'status': 1}, 'copyVolume.return_value': {'taskid': 1}, @@ -641,8 +638,6 @@ class HP3PARBaseDriver(object): # setup_mock_client drive with default configuration # and return the mock HTTP 3PAR client conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getTask.return_value': { 'status': 4, 'failure message': 'out of disk space'}, @@ -787,8 +782,6 @@ class HP3PARBaseDriver(object): def test_extend_volume_non_base(self): extend_ex = hpexceptions.HTTPForbidden(error={'code': 150}) conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getTask.return_value': { 'status': 1}, 'getCPG.return_value': {}, @@ -810,8 +803,6 @@ class HP3PARBaseDriver(object): def test_extend_volume_non_base_failure(self): extend_ex = hpexceptions.HTTPForbidden(error={'code': 150}) conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}, 'getTask.return_value': { 'status': 1}, 'getCPG.return_value': {}, @@ -1019,8 +1010,6 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase): {'active': True, 'volumeName': self.VOLUME_3PAR_NAME, 'lun': 90, 'type': 0}] - mock_client.getPorts.return_value = { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]} location = ("%(volume_name)s,%(lun_id)s,%(host)s,%(nsp)s" % {'volume_name': self.VOLUME_3PAR_NAME, 'lun_id': 90, @@ -1057,8 +1046,6 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase): {'active': True, 'volumeName': self.VOLUME_3PAR_NAME, 'lun': None, 'type': 0}] - mock_client.getPorts.return_value = { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]} self.driver.terminate_connection( self.volume, @@ -1299,11 +1286,6 @@ class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase): def setup_driver(self, config=None, mock_conf=None): self.ctxt = context.get_admin_context() - # setup_mock_client default config, if necessary - if mock_conf is None: - mock_conf = { - 'getPorts.return_value': { - 'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}} mock_client = self.setup_mock_client( conf=config, diff --git a/cinder/volume/drivers/san/hp/hp_3par_common.py b/cinder/volume/drivers/san/hp/hp_3par_common.py index 45bf53507..c9229fb57 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_common.py +++ b/cinder/volume/drivers/san/hp/hp_3par_common.py @@ -41,9 +41,12 @@ import pprint import re import uuid -import hp3parclient -from hp3parclient import client -from hp3parclient import exceptions as hpexceptions +from cinder.openstack.common import importutils +hp3parclient = importutils.try_import("hp3parclient") +if hp3parclient: + from hp3parclient import client + from hp3parclient import exceptions as hpexceptions + from oslo.config import cfg from cinder import context @@ -124,10 +127,11 @@ class HP3PARCommon(object): 2.0.8 - Fix detach issue for multiple hosts bug #1288927 2.0.9 - Remove unused 3PAR driver method bug #1310807 2.0.10 - Fixed an issue with 3PAR vlun location bug #1315542 + 2.0.11 - Remove hp3parclient requirement from unit tests #1315195 """ - VERSION = "2.0.10" + VERSION = "2.0.11" stats = {} @@ -209,6 +213,9 @@ class HP3PARCommon(object): LOG.debug("Disconnect from 3PAR") def do_setup(self, context): + if hp3parclient is None: + msg = _('You must install hp3parclient before using 3PAR drivers.') + raise exception.VolumeBackendAPIException(data=msg) try: self.client = self._create_client() except hpexceptions.UnsupportedVersion as ex: diff --git a/cinder/volume/drivers/san/hp/hp_3par_fc.py b/cinder/volume/drivers/san/hp/hp_3par_fc.py index 693172387..251e90f20 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_fc.py +++ b/cinder/volume/drivers/san/hp/hp_3par_fc.py @@ -29,7 +29,10 @@ Set the following in the cinder.conf file to enable the volume_driver=cinder.volume.drivers.san.hp.hp_3par_fc.HP3PARFCDriver """ -from hp3parclient import exceptions as hpexceptions +try: + from hp3parclient import exceptions as hpexceptions +except ImportError: + hpexceptions = None from cinder.openstack.common import log as logging from cinder import utils diff --git a/cinder/volume/drivers/san/hp/hp_3par_iscsi.py b/cinder/volume/drivers/san/hp/hp_3par_iscsi.py index 01d851b7a..7fa08a297 100644 --- a/cinder/volume/drivers/san/hp/hp_3par_iscsi.py +++ b/cinder/volume/drivers/san/hp/hp_3par_iscsi.py @@ -29,7 +29,10 @@ volume_driver=cinder.volume.drivers.san.hp.hp_3par_iscsi.HP3PARISCSIDriver import sys -from hp3parclient import exceptions as hpexceptions +try: + from hp3parclient import exceptions as hpexceptions +except ImportError: + hpexceptions = None from cinder import exception from cinder.openstack.common import log as logging diff --git a/test-requirements.txt b/test-requirements.txt index 56746da83..5a28119aa 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,7 +3,6 @@ hacking>=0.8.0,<0.9 coverage>=3.6 discover fixtures>=0.3.14 -hp3parclient>=3.0,<4.0 hplefthandclient>=1.0.0,<2.0.0 mock>=1.0 mox>=0.5.3 -- 2.45.2