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
This commit is contained in:
Mark Sturdevant 2014-05-05 14:13:48 -07:00
parent 4726b6543c
commit 541cc9d53a
7 changed files with 126 additions and 48 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -41,9 +41,12 @@ import pprint
import re
import uuid
import hp3parclient
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:

View File

@ -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
"""
try:
from hp3parclient import exceptions as hpexceptions
except ImportError:
hpexceptions = None
from cinder.openstack.common import log as logging
from cinder import utils

View File

@ -29,7 +29,10 @@ volume_driver=cinder.volume.drivers.san.hp.hp_3par_iscsi.HP3PARISCSIDriver
import sys
try:
from hp3parclient import exceptions as hpexceptions
except ImportError:
hpexceptions = None
from cinder import exception
from cinder.openstack.common import log as logging

View File

@ -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