Ensure that lun_id is an int for NetApp Drivers

Various NetApp drivers were treating the lun_id as a string
rather than an int.  This was causing attempts to mount NetApp
volumes to Hyper-V nodes to fail as they were checking an integer
type against a unicode type which would fail.

This change casts result_lun to an integer after the value has
gone through the ssh injection attack check.  This way Hyper-V
is able to verify if the found LUN is the target LUN, enabling
mounting of NetApp volumes to Hyper-V.

This change also refactors initialize_connection into some helper
methods so as to enable simpler unit testing of the patchset.

Closes-bug: 1372808

Change-Id: I308b3b2dff315ec33451fb45a30ecd53d5d4c353
This commit is contained in:
Rushil Chugh 2014-11-18 14:37:17 -05:00
parent 5259bd7f60
commit 2d0204ff3c
6 changed files with 97 additions and 40 deletions

View File

@ -58,7 +58,7 @@ FC_FABRIC_MAP = {'fabricB':
'initiator_port_wwn_list': ['21000024ff406cc3']}}
FC_TARGET_INFO = {'driver_volume_type': 'fibre_channel',
'data': {'target_lun': '1',
'data': {'target_lun': 1,
'initiator_target_map': FC_I_T_MAP,
'access_mode': 'rw',
'target_wwn': FC_TARGET_WWPNS,

View File

@ -1,4 +1,5 @@
# Copyright (c) - 2014, Clinton Knight. All rights reserved.
# Copyright (c) - 2014, Clinton Knight All rights reserved.
# Copyright (c) - 2014, Rushil Chugh 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
@ -42,3 +43,27 @@ def create_configuration_eseries():
config = create_configuration()
config.append_config_values(na_opts.netapp_eseries_opts)
return config
ISCSI_FAKE_LUN_ID = 1
ISCSI_FAKE_IQN = 'iqn.1993-08.org.debian:01:10'
ISCSI_FAKE_ADDRESS = '10.63.165.216'
ISCSI_FAKE_PORT = '2232'
ISCSI_FAKE_VOLUME = {'id': 'fake_id'}
ISCSI_FAKE_TARGET = {}
ISCSI_FAKE_TARGET['address'] = ISCSI_FAKE_ADDRESS
ISCSI_FAKE_TARGET['port'] = ISCSI_FAKE_PORT
ISCSI_FAKE_VOLUME = {'id': 'fake_id', 'provider_auth': 'None stack password'}
FC_ISCSI_TARGET_INFO_DICT = {'target_discovered': False,
'target_portal': '10.63.165.216:2232',
'target_iqn': ISCSI_FAKE_IQN,
'target_lun': ISCSI_FAKE_LUN_ID,
'volume_id': ISCSI_FAKE_VOLUME['id'],
'auth_method': 'None', 'auth_username': 'stack',
'auth_password': 'password'}

View File

@ -24,6 +24,7 @@ from oslo.concurrency import processutils as putils
from cinder import exception
from cinder import test
import cinder.tests.volume.drivers.netapp.fakes as fake
from cinder import version
import cinder.volume.drivers.netapp.utils as na_utils
@ -350,3 +351,34 @@ class OpenStackInfoTestCase(test.TestCase):
info._update_openstack_info()
self.assertTrue(mock_updt_from_dpkg.called)
def test_iscsi_connection_properties(self):
actual_properties = na_utils.get_iscsi_connection_properties(
fake.ISCSI_FAKE_LUN_ID, fake.ISCSI_FAKE_VOLUME,
fake.ISCSI_FAKE_IQN, fake.ISCSI_FAKE_ADDRESS,
fake.ISCSI_FAKE_PORT)
actual_properties_mapped = actual_properties['data']
self.assertDictEqual(actual_properties_mapped,
fake.FC_ISCSI_TARGET_INFO_DICT)
def test_iscsi_connection_lun_id_type_str(self):
FAKE_LUN_ID = '1'
actual_properties = na_utils.get_iscsi_connection_properties(
FAKE_LUN_ID, fake.ISCSI_FAKE_VOLUME, fake.ISCSI_FAKE_IQN,
fake.ISCSI_FAKE_ADDRESS, fake.ISCSI_FAKE_PORT)
actual_properties_mapped = actual_properties['data']
self.assertIs(type(actual_properties_mapped['target_lun']), int)
def test_iscsi_connection_lun_id_type_dict(self):
FAKE_LUN_ID = {'id': 'fake_id'}
self.assertRaises(TypeError, na_utils.get_iscsi_connection_properties,
FAKE_LUN_ID, fake.ISCSI_FAKE_VOLUME,
fake.ISCSI_FAKE_IQN, fake.ISCSI_FAKE_ADDRESS,
fake.ISCSI_FAKE_PORT)

View File

@ -519,7 +519,6 @@ class NetAppBlockStorageLibrary(object):
msg = _("Mapped LUN %(name)s to the initiator %(initiator_name)s")
msg_fmt = {'name': name, 'initiator_name': initiator_name}
LOG.debug(msg % msg_fmt)
iqn = self.zapi_client.get_iscsi_service_details()
target_details_list = self.zapi_client.get_iscsi_target_details()
msg = _("Successfully fetched target details for LUN %(name)s and "
"initiator %(initiator_name)s")
@ -537,32 +536,22 @@ class NetAppBlockStorageLibrary(object):
if not target_details:
target_details = target_details_list[0]
(address, port) = (target_details['address'], target_details['port'])
if not target_details['address'] and target_details['port']:
msg = _('Failed to get target portal for the LUN %s')
raise exception.VolumeBackendAPIException(data=msg % name)
iqn = self.zapi_client.get_iscsi_service_details()
if not iqn:
msg = _('Failed to get target IQN for the LUN %s')
raise exception.VolumeBackendAPIException(data=msg % name)
properties = {}
properties['target_discovered'] = False
(address, port) = (target_details['address'], target_details['port'])
properties['target_portal'] = '%s:%s' % (address, port)
properties['target_iqn'] = iqn
properties['target_lun'] = lun_id
properties['volume_id'] = volume['id']
properties = na_utils.get_iscsi_connection_properties(lun_id, volume,
iqn, address,
port)
auth = volume['provider_auth']
if auth:
(auth_method, auth_username, auth_secret) = auth.split()
properties['auth_method'] = auth_method
properties['auth_username'] = auth_username
properties['auth_password'] = auth_secret
return {
'driver_volume_type': 'iscsi',
'data': properties,
}
return properties
def terminate_connection_iscsi(self, volume, connector, **kwargs):
"""Driver entry point to unattach a volume from an instance.
@ -648,7 +637,7 @@ class NetAppBlockStorageLibrary(object):
target_info = {'driver_volume_type': 'fibre_channel',
'data': {'target_discovered': True,
'target_lun': lun_id,
'target_lun': int(lun_id),
'target_wwn': target_wwpns,
'access_mode': 'rw',
'initiator_target_map': initiator_target_map}}

View File

@ -556,7 +556,7 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
initiator_name = connector['initiator']
vol = self._get_latest_volume(volume['name_id'])
iscsi_details = self._get_iscsi_service_details()
iscsi_det = self._get_iscsi_portal_for_vol(vol, iscsi_details)
iscsi_portal = self._get_iscsi_portal_for_vol(vol, iscsi_details)
mapping = self._map_volume_to_host(vol, initiator_name)
lun_id = mapping['lun']
self._cache_vol_mapping(mapping)
@ -566,23 +566,13 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
msg = _("Successfully fetched target details for volume %(id)s and "
"initiator %(initiator_name)s.")
LOG.debug(msg % msg_fmt)
properties = {}
properties['target_discovered'] = False
properties['target_portal'] = '%s:%s' % (iscsi_det['ip'],
iscsi_det['tcp_port'])
properties['target_iqn'] = iscsi_det['iqn']
properties['target_lun'] = lun_id
properties['volume_id'] = volume['id']
auth = volume['provider_auth']
if auth:
(auth_method, auth_username, auth_secret) = auth.split()
properties['auth_method'] = auth_method
properties['auth_username'] = auth_username
properties['auth_password'] = auth_secret
return {
'driver_volume_type': 'iscsi',
'data': properties,
}
iqn = iscsi_portal['iqn']
address = iscsi_portal['ip']
port = iscsi_portal['tcp_port']
properties = na_utils.get_iscsi_connection_properties(lun_id, volume,
iqn, address,
port)
return properties
def _get_iscsi_service_details(self):
"""Gets iscsi iqn, ip and port information."""

View File

@ -139,6 +139,27 @@ def log_extra_spec_warnings(extra_specs):
LOG.warning(msg % args)
def get_iscsi_connection_properties(lun_id, volume, iqn,
address, port):
properties = {}
properties['target_discovered'] = False
properties['target_portal'] = '%s:%s' % (address, port)
properties['target_iqn'] = iqn
properties['target_lun'] = int(lun_id)
properties['volume_id'] = volume['id']
auth = volume['provider_auth']
if auth:
(auth_method, auth_username, auth_secret) = auth.split()
properties['auth_method'] = auth_method
properties['auth_username'] = auth_username
properties['auth_password'] = auth_secret
return {
'driver_volume_type': 'iscsi',
'data': properties,
}
class hashabledict(dict):
"""A hashable dictionary that is comparable (i.e. in unit tests, etc.)"""
def __hash__(self):