Merge "3PAR FC: add ability to add WWNs to host"

This commit is contained in:
Jenkins 2013-12-17 04:41:14 +00:00 committed by Gerrit Code Review
commit 57a7422c2e
2 changed files with 120 additions and 8 deletions

View File

@ -18,6 +18,7 @@
Unit tests for OpenStack Cinder volume drivers
"""
import ast
import mock
import mox
import shutil
import tempfile
@ -786,7 +787,10 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'123456789054321'])
_run_ssh(create_host_cmd, False).AndReturn([CLI_CR, ''])
getHost('fakehost').AndReturn({'name': self.FAKE_HOST})
getHost('fakehost').AndReturn({'name': self.FAKE_HOST,
'FCPaths': [{'wwn': '123456789012345'},
{'wwn': '123456789054321'}]}
)
self.mox.ReplayAll()
host = self.driver._create_host(self.volume, self.connector)
@ -817,7 +821,12 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'already used by host fakehost.foo (19)')
_run_ssh(create_host_cmd, False).AndReturn([create_host_ret, ''])
getHost('fakehost.foo').AndReturn({'name': 'fakehost.foo'})
host_ret = {
'name': 'fakehost.foo',
'FCPaths': [{'wwn': '123456789012345'},
{'wwn': '123456789054321'}]}
getHost('fakehost.foo').AndReturn(host_ret)
self.mox.ReplayAll()
host = self.driver._create_host(self.volume, self.connector)
@ -848,8 +857,8 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
'pathOperation': 1})
getHost('fakehost').AndReturn({'name': self.FAKE_HOST,
'FCPaths': [{'WWN': '123456789012345'},
{'WWN': '123456789054321'}]}
'FCPaths': [{'wwn': '123456789012345'},
{'wwn': '123456789054321'}]}
)
self.mox.ReplayAll()
@ -858,6 +867,82 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
self.assertEqual(host['name'], self.FAKE_HOST)
self.assertEqual(len(host['FCPaths']), 2)
def test_modify_host_with_new_wwn(self):
self.flags(lock_path=self.tempdir)
self.clear_mox()
hpdriver.hpcommon.HP3PARCommon.get_cpg = mock.Mock(
return_value=self.fake_get_cpg)
hpdriver.hpcommon.HP3PARCommon.get_domain = mock.Mock(
return_value=self.fake_get_domain)
# set up the getHost mock
self.driver.common.client.getHost = mock.Mock()
# define the return values for the 2 calls
getHost_ret1 = {
'name': self.FAKE_HOST,
'FCPaths': [{'wwn': '123456789054321'}]}
getHost_ret2 = {
'name': self.FAKE_HOST,
'FCPaths': [{'wwn': '123456789012345'},
{'wwn': '123456789054321'}]}
self.driver.common.client.getHost.side_effect = [
getHost_ret1, getHost_ret2]
# setup the modifyHost mock
self.driver.common.client.modifyHost = mock.Mock()
host = self.driver._create_host(self.volume, self.connector)
# mock assertions
self.driver.common.client.getHost.assert_has_calls([
mock.call('fakehost'),
mock.call('fakehost')])
self.driver.common.client.modifyHost.assert_called_once_with(
'fakehost', {'FCWWNs': ['123456789012345'], 'pathOperation': 1})
self.assertEqual(host['name'], self.FAKE_HOST)
self.assertEqual(len(host['FCPaths']), 2)
def test_modify_host_with_unknown_wwn_and_new_wwn(self):
self.flags(lock_path=self.tempdir)
self.clear_mox()
hpdriver.hpcommon.HP3PARCommon.get_cpg = mock.Mock(
return_value=self.fake_get_cpg)
hpdriver.hpcommon.HP3PARCommon.get_domain = mock.Mock(
return_value=self.fake_get_domain)
# set up the getHost mock
self.driver.common.client.getHost = mock.Mock()
# define the return values for the 2 calls
getHost_ret1 = {
'name': self.FAKE_HOST,
'FCPaths': [{'wwn': '123456789054321'},
{'wwn': 'xxxxxxxxxxxxxxx'}]}
getHost_ret2 = {
'name': self.FAKE_HOST,
'FCPaths': [{'wwn': '123456789012345'},
{'wwn': '123456789054321'},
{'wwn': 'xxxxxxxxxxxxxxx'}]}
self.driver.common.client.getHost.side_effect = [
getHost_ret1, getHost_ret2]
# setup the modifyHost mock
self.driver.common.client.modifyHost = mock.Mock()
host = self.driver._create_host(self.volume, self.connector)
# mock assertions
self.driver.common.client.getHost.assert_has_calls([
mock.call('fakehost'),
mock.call('fakehost')])
self.driver.common.client.modifyHost.assert_called_once_with(
'fakehost', {'FCWWNs': ['123456789012345'], 'pathOperation': 1})
self.assertEqual(host['name'], self.FAKE_HOST)
self.assertEqual(len(host['FCPaths']), 3)
class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):

View File

@ -56,9 +56,10 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
the drivers to use the new APIs.
1.2.1 - Synchronized extend_volume method.
1.2.2 - Added try/finally around client login/logout.
1.2.3 - Added ability to add WWNs to host.
"""
VERSION = "1.2.2"
VERSION = "1.2.3"
def __init__(self, *args, **kwargs):
super(HP3PARFCDriver, self).__init__(*args, **kwargs)
@ -261,9 +262,6 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
domain = self.common.get_domain(cpg)
try:
host = self.common._get_3par_host(hostname)
if 'FCPaths' not in host or len(host['FCPaths']) < 1:
self._modify_3par_fibrechan_host(hostname, connector['wwpns'])
host = self.common._get_3par_host(hostname)
except hpexceptions.HTTPNotFound as ex:
# get persona from the volume type extra specs
persona_id = self.common.get_persona_type(volume)
@ -274,6 +272,35 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
persona_id)
host = self.common._get_3par_host(hostname)
return self._add_new_wwn_to_host(host, connector['wwpns'])
def _add_new_wwn_to_host(self, host, wwns):
"""Add wwns to a host if one or more don't exist.
Identify if argument wwns contains any world wide names
not configured in the 3PAR host path. If any are found,
add them to the 3PAR host.
"""
# get the currently configured wwns
# from the host's FC paths
host_wwns = []
if 'FCPaths' in host:
for path in host['FCPaths']:
wwn = path.get('wwn', None)
if wwn is not None:
host_wwns.append(wwn.lower())
# lower case all wwns in the compare list
compare_wwns = [x.lower() for x in wwns]
# calculate wwns in compare list, but not in host_wwns list
new_wwns = list(set(compare_wwns).difference(host_wwns))
# if any wwns found that were not in host list,
# add them to the host
if (len(new_wwns) > 0):
self._modify_3par_fibrechan_host(host['name'], new_wwns)
host = self.common._get_3par_host(host['name'])
return host
@utils.synchronized('3par', external=True)