NetApp fix for default host type in eseries
This fixes the issue where the default host type
provided in mapping should be high performing LnxALUA
type for eseries. It also makes it configurable in case
users want to configure a different host type.
Closes-Bug: #1365884
Change-Id: I30992ca69c25c3c02334470aae90c32731a5f3f4
(cherry picked from commit a120ede9ae
)
This commit is contained in:
parent
8692741fae
commit
f17aa46e94
@ -216,8 +216,8 @@ class FakeEseriesServerHandler(object):
|
||||
"index" : 5
|
||||
}, {
|
||||
"id" : "6",
|
||||
"code" : "LNX",
|
||||
"name" : "Linux",
|
||||
"code" : "LnxALUA",
|
||||
"name" : "LnxALUA",
|
||||
"index" : 6
|
||||
}]"""
|
||||
elif re.match("^/storage-systems/[0-9a-zA-Z]+/snapshot-groups$", path):
|
||||
@ -878,3 +878,59 @@ class NetAppEseriesIscsiDriverTestCase(test.TestCase):
|
||||
self.assertRaises(exception.NetAppDriverException,
|
||||
self.driver._get_iscsi_portal_for_vol,
|
||||
vol_nomatch, portals, False)
|
||||
|
||||
def test_get_host_right_type(self):
|
||||
self.driver._get_host_with_port = mock.Mock(
|
||||
return_value={'hostTypeIndex': 2, 'name': 'test'})
|
||||
self.driver._get_host_type_definition = mock.Mock(
|
||||
return_value={'index': 2, 'name': 'LnxALUA'})
|
||||
host = self.driver._get_or_create_host('port', 'LinuxALUA')
|
||||
self.assertEqual(host, {'hostTypeIndex': 2, 'name': 'test'})
|
||||
self.driver._get_host_with_port.assert_called_once_with('port')
|
||||
self.driver._get_host_type_definition.assert_called_once_with(
|
||||
'LinuxALUA')
|
||||
|
||||
def test_get_host_update_type(self):
|
||||
self.driver._get_host_with_port = mock.Mock(
|
||||
return_value={'hostTypeIndex': 2, 'hostRef': 'test'})
|
||||
self.driver._get_host_type_definition = mock.Mock(
|
||||
return_value={'index': 3, 'name': 'LnxALUA'})
|
||||
self.driver._client.update_host_type = mock.Mock(
|
||||
return_value={'hostTypeIndex': 3, 'hostRef': 'test'})
|
||||
host = self.driver._get_or_create_host('port', 'LinuxALUA')
|
||||
self.assertEqual(host, {'hostTypeIndex': 3, 'hostRef': 'test'})
|
||||
self.driver._get_host_with_port.assert_called_once_with('port')
|
||||
self.driver._get_host_type_definition.assert_called_once_with(
|
||||
'LinuxALUA')
|
||||
self.assertEqual(self.driver._client.update_host_type.call_count, 1)
|
||||
|
||||
def test_get_host_update_type_failed(self):
|
||||
self.driver._get_host_with_port = mock.Mock(
|
||||
return_value={'hostTypeIndex': 2, 'hostRef': 'test',
|
||||
'label': 'test'})
|
||||
self.driver._get_host_type_definition = mock.Mock(
|
||||
return_value={'index': 3, 'name': 'LnxALUA'})
|
||||
self.driver._client.update_host_type = mock.Mock(
|
||||
side_effect=exception.NetAppDriverException)
|
||||
host = self.driver._get_or_create_host('port', 'LinuxALUA')
|
||||
self.assertEqual(host, {'hostTypeIndex': 2, 'hostRef': 'test',
|
||||
'label': 'test'})
|
||||
self.driver._get_host_with_port.assert_called_once_with('port')
|
||||
self.driver._get_host_type_definition.assert_called_once_with(
|
||||
'LinuxALUA')
|
||||
self.assertEqual(self.driver._client.update_host_type.call_count, 1)
|
||||
|
||||
def test_get_host_not_found(self):
|
||||
self.driver._get_host_with_port = mock.Mock(
|
||||
side_effect=exception.NotFound)
|
||||
self.driver._create_host = mock.Mock()
|
||||
self.driver._get_or_create_host('port', 'LnxALUA')
|
||||
self.driver._get_host_with_port.assert_called_once_with('port')
|
||||
self.driver._create_host.assert_called_once_with('port', 'LnxALUA')
|
||||
|
||||
def test_setup_error_unsupported_host_type(self):
|
||||
configuration = self._set_config(create_configuration())
|
||||
configuration.netapp_eseries_host_type = 'garbage'
|
||||
driver = common.NetAppDriver(configuration=configuration)
|
||||
self.assertRaises(exception.NetAppDriverException,
|
||||
driver.check_for_setup_error)
|
||||
|
@ -217,6 +217,12 @@ class RestClient(WebserviceClient):
|
||||
port = {'type': port_type, 'port': port_id, 'label': port_label}
|
||||
return self.create_host(label, host_type, [port], group_id)
|
||||
|
||||
def update_host_type(self, host_ref, host_type):
|
||||
"""Updates host type for a given host."""
|
||||
path = "/storage-systems/{system-id}/hosts/{object-id}"
|
||||
data = {'hostType': host_type}
|
||||
return self._invoke('POST', path, data, **{'object-id': host_ref})
|
||||
|
||||
def list_host_types(self):
|
||||
"""Lists host types in storage system."""
|
||||
path = "/storage-systems/{system-id}/host-types"
|
||||
|
@ -58,6 +58,26 @@ class Driver(driver.ISCSIDriver):
|
||||
'netapp_storage_pools']
|
||||
SLEEP_SECS = 5
|
||||
MAX_LUNS_PER_HOST = 255
|
||||
HOST_TYPES = {'aix': 'AIX MPIO',
|
||||
'avt': 'AVT_4M',
|
||||
'factoryDefault': 'FactoryDefault',
|
||||
'hpux': 'HP-UX TPGS',
|
||||
'linux_atto': 'LnxTPGSALUA',
|
||||
'linux_dm_mp': 'LnxALUA',
|
||||
'linux_mpp_rdac': 'Linux',
|
||||
'linux_pathmanager': 'LnxTPGSALUA_PM',
|
||||
'macos': 'MacTPGSALUA',
|
||||
'ontap': 'ONTAP',
|
||||
'svc': 'SVC',
|
||||
'solaris_v11': 'SolTPGSALUA',
|
||||
'solaris_v10': 'Solaris',
|
||||
'vmware': 'VmwTPGSALUA',
|
||||
'windows':
|
||||
'Windows 2000/Server 2003/Server 2008 Non-Clustered',
|
||||
'windows_atto': 'WinTPGSALUA',
|
||||
'windows_clustered':
|
||||
'Windows 2000/Server 2003/Server 2008 Clustered'
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Driver, self).__init__(*args, **kwargs)
|
||||
@ -91,6 +111,12 @@ class Driver(driver.ISCSIDriver):
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
def check_for_setup_error(self):
|
||||
self.host_type =\
|
||||
self.HOST_TYPES.get(self.configuration.netapp_eseries_host_type,
|
||||
None)
|
||||
if not self.host_type:
|
||||
raise exception.NetAppDriverException(
|
||||
_('Configured host type is not supported.'))
|
||||
self._check_storage_system()
|
||||
self._populate_system_objects()
|
||||
|
||||
@ -579,7 +605,7 @@ class Driver(driver.ISCSIDriver):
|
||||
@cinder_utils.synchronized('map_es_volume')
|
||||
def _map_volume_to_host(self, vol, initiator):
|
||||
"""Maps the e-series volume to host with initiator."""
|
||||
host = self._get_or_create_host(initiator)
|
||||
host = self._get_or_create_host(initiator, self.host_type)
|
||||
vol_maps = self._get_host_mapping_for_vol_frm_array(vol)
|
||||
for vol_map in vol_maps:
|
||||
if vol_map.get('mapRef') == host['hostRef']:
|
||||
@ -592,30 +618,40 @@ class Driver(driver.ISCSIDriver):
|
||||
return self._client.create_volume_mapping(vol['volumeRef'],
|
||||
host['hostRef'], lun)
|
||||
|
||||
def _get_or_create_host(self, port_id, host_type='linux'):
|
||||
def _get_or_create_host(self, port_id, host_type):
|
||||
"""Fetch or create a host by given port."""
|
||||
try:
|
||||
return self._get_host_with_port(port_id, host_type)
|
||||
host = self._get_host_with_port(port_id)
|
||||
ht_def = self._get_host_type_definition(host_type)
|
||||
if host.get('hostTypeIndex') == ht_def.get('index'):
|
||||
return host
|
||||
else:
|
||||
try:
|
||||
return self._client.update_host_type(
|
||||
host['hostRef'], ht_def)
|
||||
except exception.NetAppDriverException as e:
|
||||
msg = _("Unable to update host type for host with"
|
||||
" label %(l)s. %(e)s")
|
||||
LOG.warn(msg % {'l': host['label'], 'e': e.msg})
|
||||
return host
|
||||
except exception.NotFound as e:
|
||||
LOG.warn(_("Message - %s."), e.msg)
|
||||
return self._create_host(port_id, host_type)
|
||||
|
||||
def _get_host_with_port(self, port_id, host_type='linux'):
|
||||
def _get_host_with_port(self, port_id):
|
||||
"""Gets or creates a host with given port id."""
|
||||
hosts = self._client.list_hosts()
|
||||
ht_def = self._get_host_type_definition(host_type)
|
||||
for host in hosts:
|
||||
if (host.get('hostTypeIndex') == ht_def.get('index')
|
||||
and host.get('hostSidePorts')):
|
||||
if host.get('hostSidePorts'):
|
||||
ports = host.get('hostSidePorts')
|
||||
for port in ports:
|
||||
if (port.get('type') == 'iscsi'
|
||||
and port.get('address') == port_id):
|
||||
return host
|
||||
msg = _("Host with port %(port)s and type %(type)s not found.")
|
||||
raise exception.NotFound(msg % {'port': port_id, 'type': host_type})
|
||||
msg = _("Host with port %(port)s not found.")
|
||||
raise exception.NotFound(msg % {'port': port_id})
|
||||
|
||||
def _create_host(self, port_id, host_type='linux'):
|
||||
def _create_host(self, port_id, host_type):
|
||||
"""Creates host on system with given initiator as port_id."""
|
||||
LOG.info(_("Creating host with port %s."), port_id)
|
||||
label = utils.convert_uuid_to_es_fmt(uuid.uuid4())
|
||||
@ -624,7 +660,7 @@ class Driver(driver.ISCSIDriver):
|
||||
return self._client.create_host_with_port(label, host_type,
|
||||
port_id, port_label)
|
||||
|
||||
def _get_host_type_definition(self, host_type='linux'):
|
||||
def _get_host_type_definition(self, host_type):
|
||||
"""Gets supported host type if available on storage system."""
|
||||
host_types = self._client.list_host_types()
|
||||
for ht in host_types:
|
||||
|
@ -161,7 +161,13 @@ netapp_eseries_opts = [
|
||||
'specified storage pools. Only dynamic disk pools are '
|
||||
'currently supported. Specify the value of this option to'
|
||||
' be a comma separated list of disk pool names to be used'
|
||||
' for provisioning.')), ]
|
||||
' for provisioning.')),
|
||||
cfg.StrOpt('netapp_eseries_host_type',
|
||||
default='linux_dm_mp',
|
||||
help=('This option is used to define how the controllers in '
|
||||
'the E-Series storage array will work with the '
|
||||
'particular operating system on the hosts that are '
|
||||
'connected to it.')), ]
|
||||
netapp_nfs_extra_opts = [
|
||||
cfg.StrOpt('netapp_copyoffload_tool_path',
|
||||
default=None,
|
||||
|
@ -1641,6 +1641,12 @@
|
||||
# provisioning. (string value)
|
||||
#netapp_storage_pools=<None>
|
||||
|
||||
# This option is used to define how the controllers in the
|
||||
# E-Series storage array will work with the particular
|
||||
# operating system on the hosts that are connected to it.
|
||||
# (string value)
|
||||
#netapp_eseries_host_type=linux_dm_mp
|
||||
|
||||
# If the percentage of available space for an NFS share has
|
||||
# dropped below the value specified by this option, the NFS
|
||||
# image cache will be cleaned. (integer value)
|
||||
|
Loading…
Reference in New Issue
Block a user