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 import mock
from hp3parclient import client
from hp3parclient import exceptions as hpexceptions
from cinder import context from cinder import context
from cinder import exception from cinder import exception
from cinder.openstack.common import log as logging from cinder.openstack.common import log as logging
from cinder import test from cinder import test
from cinder import units 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_fc as hpfcdriver
from cinder.volume.drivers.san.hp import hp_3par_iscsi as hpdriver from cinder.volume.drivers.san.hp import hp_3par_iscsi as hpdriver
from cinder.volume import qos_specs from cinder.volume import qos_specs
from cinder.volume import volume_types from cinder.volume import volume_types
hpexceptions = hp3parclient.hpexceptions
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
HP3PAR_CPG = 'OpenStackCPG' HP3PAR_CPG = 'OpenStackCPG'
@ -157,6 +158,18 @@ class HP3PARBaseDriver(object):
'state': 1, 'state': 1,
'uuid': '29c214aa-62b9-41c8-b198-543f6cf24edf'}] '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): def setup_configuration(self):
configuration = mock.Mock() configuration = mock.Mock()
configuration.hp3par_debug = False configuration.hp3par_debug = False
@ -181,15 +194,15 @@ class HP3PARBaseDriver(object):
@mock.patch( @mock.patch(
'hp3parclient.client.HP3ParClient', 'hp3parclient.client.HP3ParClient',
spec=True, 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): def setup_mock_client(self, _m_client, driver, conf=None, m_conf=None):
_m_client = _m_client.return_value _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: if m_conf is not None:
_m_client.configure_mock(**m_conf) _m_client.configure_mock(**m_conf)
@ -304,8 +317,6 @@ class HP3PARBaseDriver(object):
def test_migrate_volume(self): def test_migrate_volume(self):
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getStorageSystemInfo.return_value': { 'getStorageSystemInfo.return_value': {
'serialNumber': '1234'}, 'serialNumber': '1234'},
'getTask.return_value': { 'getTask.return_value': {
@ -356,8 +367,6 @@ class HP3PARBaseDriver(object):
def test_migrate_volume_diff_host(self): def test_migrate_volume_diff_host(self):
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getStorageSystemInfo.return_value': { 'getStorageSystemInfo.return_value': {
'serialNumber': 'different'}, 'serialNumber': 'different'},
} }
@ -383,8 +392,6 @@ class HP3PARBaseDriver(object):
def test_migrate_volume_diff_domain(self): def test_migrate_volume_diff_domain(self):
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getStorageSystemInfo.return_value': { 'getStorageSystemInfo.return_value': {
'serialNumber': '1234'}, 'serialNumber': '1234'},
'getTask.return_value': { 'getTask.return_value': {
@ -413,16 +420,8 @@ class HP3PARBaseDriver(object):
self.assertEqual((False, None), result) self.assertEqual((False, None), result)
def test_migrate_volume_attached(self): 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, volume = {'name': HP3PARBaseDriver.VOLUME_NAME,
'id': HP3PARBaseDriver.CLONE_ID, 'id': HP3PARBaseDriver.CLONE_ID,
@ -596,8 +595,6 @@ class HP3PARBaseDriver(object):
# setup_mock_client drive with default configuration # setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client # and return the mock HTTP 3PAR client
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getTask.return_value': { 'getTask.return_value': {
'status': 1}, 'status': 1},
'copyVolume.return_value': {'taskid': 1}, 'copyVolume.return_value': {'taskid': 1},
@ -641,8 +638,6 @@ class HP3PARBaseDriver(object):
# setup_mock_client drive with default configuration # setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client # and return the mock HTTP 3PAR client
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getTask.return_value': { 'getTask.return_value': {
'status': 4, 'status': 4,
'failure message': 'out of disk space'}, 'failure message': 'out of disk space'},
@ -787,8 +782,6 @@ class HP3PARBaseDriver(object):
def test_extend_volume_non_base(self): def test_extend_volume_non_base(self):
extend_ex = hpexceptions.HTTPForbidden(error={'code': 150}) extend_ex = hpexceptions.HTTPForbidden(error={'code': 150})
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getTask.return_value': { 'getTask.return_value': {
'status': 1}, 'status': 1},
'getCPG.return_value': {}, 'getCPG.return_value': {},
@ -810,8 +803,6 @@ class HP3PARBaseDriver(object):
def test_extend_volume_non_base_failure(self): def test_extend_volume_non_base_failure(self):
extend_ex = hpexceptions.HTTPForbidden(error={'code': 150}) extend_ex = hpexceptions.HTTPForbidden(error={'code': 150})
conf = { conf = {
'getPorts.return_value': {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]},
'getTask.return_value': { 'getTask.return_value': {
'status': 1}, 'status': 1},
'getCPG.return_value': {}, 'getCPG.return_value': {},
@ -1019,8 +1010,6 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
{'active': True, {'active': True,
'volumeName': self.VOLUME_3PAR_NAME, 'volumeName': self.VOLUME_3PAR_NAME,
'lun': 90, 'type': 0}] '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" % location = ("%(volume_name)s,%(lun_id)s,%(host)s,%(nsp)s" %
{'volume_name': self.VOLUME_3PAR_NAME, {'volume_name': self.VOLUME_3PAR_NAME,
'lun_id': 90, 'lun_id': 90,
@ -1057,8 +1046,6 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
{'active': True, {'active': True,
'volumeName': self.VOLUME_3PAR_NAME, 'volumeName': self.VOLUME_3PAR_NAME,
'lun': None, 'type': 0}] 'lun': None, 'type': 0}]
mock_client.getPorts.return_value = {
'members': self.FAKE_FC_PORTS + [self.FAKE_ISCSI_PORT]}
self.driver.terminate_connection( self.driver.terminate_connection(
self.volume, self.volume,
@ -1299,11 +1286,6 @@ class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
def setup_driver(self, config=None, mock_conf=None): def setup_driver(self, config=None, mock_conf=None):
self.ctxt = context.get_admin_context() 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( mock_client = self.setup_mock_client(
conf=config, conf=config,

View File

@ -41,9 +41,12 @@ import pprint
import re import re
import uuid import uuid
import hp3parclient from cinder.openstack.common import importutils
from hp3parclient import client hp3parclient = importutils.try_import("hp3parclient")
from hp3parclient import exceptions as hpexceptions if hp3parclient:
from hp3parclient import client
from hp3parclient import exceptions as hpexceptions
from oslo.config import cfg from oslo.config import cfg
from cinder import context from cinder import context
@ -124,10 +127,11 @@ class HP3PARCommon(object):
2.0.8 - Fix detach issue for multiple hosts bug #1288927 2.0.8 - Fix detach issue for multiple hosts bug #1288927
2.0.9 - Remove unused 3PAR driver method bug #1310807 2.0.9 - Remove unused 3PAR driver method bug #1310807
2.0.10 - Fixed an issue with 3PAR vlun location bug #1315542 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 = {} stats = {}
@ -209,6 +213,9 @@ class HP3PARCommon(object):
LOG.debug("Disconnect from 3PAR") LOG.debug("Disconnect from 3PAR")
def do_setup(self, context): def do_setup(self, context):
if hp3parclient is None:
msg = _('You must install hp3parclient before using 3PAR drivers.')
raise exception.VolumeBackendAPIException(data=msg)
try: try:
self.client = self._create_client() self.client = self._create_client()
except hpexceptions.UnsupportedVersion as ex: 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 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.openstack.common import log as logging
from cinder import utils from cinder import utils

View File

@ -29,7 +29,10 @@ volume_driver=cinder.volume.drivers.san.hp.hp_3par_iscsi.HP3PARISCSIDriver
import sys 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 import exception
from cinder.openstack.common import log as logging from cinder.openstack.common import log as logging

View File

@ -3,7 +3,6 @@ hacking>=0.8.0,<0.9
coverage>=3.6 coverage>=3.6
discover discover
fixtures>=0.3.14 fixtures>=0.3.14
hp3parclient>=3.0,<4.0
hplefthandclient>=1.0.0,<2.0.0 hplefthandclient>=1.0.0,<2.0.0
mock>=1.0 mock>=1.0
mox>=0.5.3 mox>=0.5.3