Merge "NetApp fix for default host type in eseries" into stable/juno
This commit is contained in:
commit
3e6c4e6126
@ -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