Merge "3PAR FC: add ability to add WWNs to host"
This commit is contained in:
commit
57a7422c2e
|
@ -18,6 +18,7 @@
|
||||||
Unit tests for OpenStack Cinder volume drivers
|
Unit tests for OpenStack Cinder volume drivers
|
||||||
"""
|
"""
|
||||||
import ast
|
import ast
|
||||||
|
import mock
|
||||||
import mox
|
import mox
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -786,7 +787,10 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
|
||||||
'123456789054321'])
|
'123456789054321'])
|
||||||
_run_ssh(create_host_cmd, False).AndReturn([CLI_CR, ''])
|
_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()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
host = self.driver._create_host(self.volume, self.connector)
|
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)')
|
'already used by host fakehost.foo (19)')
|
||||||
_run_ssh(create_host_cmd, False).AndReturn([create_host_ret, ''])
|
_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()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
host = self.driver._create_host(self.volume, self.connector)
|
host = self.driver._create_host(self.volume, self.connector)
|
||||||
|
@ -848,8 +857,8 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
|
||||||
'pathOperation': 1})
|
'pathOperation': 1})
|
||||||
|
|
||||||
getHost('fakehost').AndReturn({'name': self.FAKE_HOST,
|
getHost('fakehost').AndReturn({'name': self.FAKE_HOST,
|
||||||
'FCPaths': [{'WWN': '123456789012345'},
|
'FCPaths': [{'wwn': '123456789012345'},
|
||||||
{'WWN': '123456789054321'}]}
|
{'wwn': '123456789054321'}]}
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@ -858,6 +867,82 @@ class TestHP3PARFCDriver(HP3PARBaseDriver, test.TestCase):
|
||||||
self.assertEqual(host['name'], self.FAKE_HOST)
|
self.assertEqual(host['name'], self.FAKE_HOST)
|
||||||
self.assertEqual(len(host['FCPaths']), 2)
|
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):
|
class TestHP3PARISCSIDriver(HP3PARBaseDriver, test.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,10 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
|
||||||
the drivers to use the new APIs.
|
the drivers to use the new APIs.
|
||||||
1.2.1 - Synchronized extend_volume method.
|
1.2.1 - Synchronized extend_volume method.
|
||||||
1.2.2 - Added try/finally around client login/logout.
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
super(HP3PARFCDriver, self).__init__(*args, **kwargs)
|
super(HP3PARFCDriver, self).__init__(*args, **kwargs)
|
||||||
|
@ -261,9 +262,6 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
|
||||||
domain = self.common.get_domain(cpg)
|
domain = self.common.get_domain(cpg)
|
||||||
try:
|
try:
|
||||||
host = self.common._get_3par_host(hostname)
|
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:
|
except hpexceptions.HTTPNotFound as ex:
|
||||||
# get persona from the volume type extra specs
|
# get persona from the volume type extra specs
|
||||||
persona_id = self.common.get_persona_type(volume)
|
persona_id = self.common.get_persona_type(volume)
|
||||||
|
@ -274,6 +272,35 @@ class HP3PARFCDriver(cinder.volume.driver.FibreChannelDriver):
|
||||||
persona_id)
|
persona_id)
|
||||||
host = self.common._get_3par_host(hostname)
|
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
|
return host
|
||||||
|
|
||||||
@utils.synchronized('3par', external=True)
|
@utils.synchronized('3par', external=True)
|
||||||
|
|
Loading…
Reference in New Issue