Merge "Refactoring Kaminario iSCSI driver"

This commit is contained in:
Jenkins 2016-06-28 20:41:59 +00:00 committed by Gerrit Code Review
commit e769f52895
3 changed files with 138 additions and 82 deletions

View File

@ -26,8 +26,8 @@ from cinder.volume.drivers.kaminario import kaminario_iscsi
from cinder.volume import utils as vol_utils
CONNECTOR = {'initiator': 'iqn.1993-08.org.debian:01:84cd7e88bb5a',
'ip': '192.168.6.5', 'platform': 'x86_64', 'host': 'il-ksm1-055',
CONNECTOR = {'initiator': 'iqn.1993-08.org.debian:01:12aa12aa12aa',
'ip': '192.168.2.5', 'platform': 'x86_64', 'host': 'test-k2',
'os_type': 'linux2', 'multipath': False}
@ -113,7 +113,6 @@ class TestKaminarioISCSI(test.TestCase):
KaminarioISCSIDriver(configuration=self.conf))
device = mock.Mock(return_value={'device': {'path': '/dev'}})
self.driver._connect_device = device
self.driver._protocol = False
self.driver.client = FakeKrest()
def test_create_volume(self):
@ -233,3 +232,32 @@ class TestKaminarioISCSI(test.TestCase):
"""Test terminate_connection."""
result = self.driver.terminate_connection(self.vol, CONNECTOR)
self.assertIsNone(result)
def test_get_lun_number(self):
"""Test _get_lun_number."""
host, host_rs, host_name = self.driver._get_host_object(CONNECTOR)
result = self.driver._get_lun_number(self.vol, host)
self.assertEqual(548, result)
def test_get_volume_object(self):
"""Test _get_volume_object."""
result = self.driver._get_volume_object(self.vol)
self.assertEqual(548, result.id)
def test_get_host_object(self):
"""Test _get_host_object."""
host, host_rs, host_name = self.driver._get_host_object(CONNECTOR)
self.assertEqual(548, host.id)
self.assertEqual(1, host_rs.total)
self.assertEqual('test-k2', host_name)
def test_get_target_info(self):
"""Test get_target_info."""
iscsi_portal, target_iqn = self.driver.get_target_info()
self.assertEqual('10.0.0.1:3260', iscsi_portal)
self.assertEqual('xyztlnxyz', target_iqn)
def test_k2_initialize_connection(self):
"""Test k2_initialize_connection."""
result = self.driver.k2_initialize_connection(self.vol, CONNECTOR)
self.assertEqual(548, result)

View File

@ -25,7 +25,7 @@ from oslo_utils import versionutils
import cinder
from cinder import exception
from cinder.i18n import _, _LE
from cinder.i18n import _, _LE, _LW
from cinder import utils
from cinder.volume.drivers.san import san
from cinder.volume import utils as vol_utils
@ -408,7 +408,7 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
return "cview-{0}".format(vid)
@kaminario_logger
def delete_host_by_name(self, name):
def _delete_host_by_name(self, name):
"""Deleting host by name."""
host_rs = self.client.search("hosts", name=name)
if hasattr(host_rs, "hits") and host_rs.total != 0:
@ -427,8 +427,87 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
raise exception.KaminarioCinderDriverException(
reason=six.text_type(ex.message))
@kaminario_logger
def _get_volume_object(self, volume):
vol_name = self.get_volume_name(volume.id)
LOG.debug("Searching volume : %s in K2.", vol_name)
vol_rs = self.client.search("volumes", name=vol_name)
if not hasattr(vol_rs, 'hits') or vol_rs.total == 0:
msg = _("Unable to find volume: %s from K2.") % vol_name
LOG.error(msg)
raise exception.KaminarioCinderDriverException(reason=msg)
return vol_rs.hits[0]
@kaminario_logger
def _get_lun_number(self, vol, host):
volsnap = None
LOG.debug("Searching volsnaps in K2.")
volsnap_rs = self.client.search("volsnaps", snapshot=vol)
if hasattr(volsnap_rs, 'hits') and volsnap_rs.total != 0:
volsnap = volsnap_rs.hits[0]
LOG.debug("Searching mapping of volsnap in K2.")
map_rs = self.client.search("mappings", volume=volsnap, host=host)
return map_rs.hits[0].lun
def initialize_connection(self, volume, connector):
pass
@kaminario_logger
def terminate_connection(self, volume, connector, **kwargs):
"""Terminate connection of volume from host."""
# Get volume object
if type(volume).__name__ != 'RestObject':
vol_name = self.get_volume_name(volume.id)
LOG.debug("Searching volume: %s in K2.", vol_name)
volume_rs = self.client.search("volumes", name=vol_name)
if hasattr(volume_rs, "hits") and volume_rs.total != 0:
volume = volume_rs.hits[0]
else:
vol_name = volume.name
# Get host object.
host_name = self.get_initiator_host_name(connector)
host_rs = self.client.search("hosts", name=host_name)
if hasattr(host_rs, "hits") and host_rs.total != 0 and volume:
host = host_rs.hits[0]
LOG.debug("Searching and deleting mapping of volume: %(name)s to "
"host: %(host)s", {'host': host_name, 'name': vol_name})
map_rs = self.client.search("mappings", volume=volume, host=host)
if hasattr(map_rs, "hits") and map_rs.total != 0:
map_rs.hits[0].delete()
if self.client.search("mappings", host=host).total == 0:
LOG.debug("Deleting initiator hostname: %s in K2.", host_name)
host.delete()
else:
LOG.warning(_LW("Host: %s not found on K2."), host_name)
def k2_initialize_connection(self, volume, connector):
# Get volume object.
if type(volume).__name__ != 'RestObject':
vol = self._get_volume_object(volume)
else:
vol = volume
# Get host object.
host, host_rs, host_name = self._get_host_object(connector)
try:
# Map volume object to host object.
LOG.debug("Mapping volume: %(vol)s to host: %(host)s",
{'host': host_name, 'vol': vol.name})
mapping = self.client.new("mappings", volume=vol, host=host).save()
except Exception as ex:
if host_rs.total == 0:
self._delete_host_by_name(host_name)
LOG.exception(_LE("Unable to map volume: %(vol)s to host: "
"%(host)s"), {'host': host_name,
'vol': vol.name})
raise exception.KaminarioCinderDriverException(
reason=six.text_type(ex.message))
# Get lun number.
if type(volume).__name__ == 'RestObject':
return self._get_lun_number(vol, host)
else:
return mapping.lun
def _get_host_object(self, connector):
pass

View File

@ -15,11 +15,12 @@
"""Volume driver for Kaminario K2 all-flash arrays."""
import six
from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _, _LW
from cinder.i18n import _, _LE
from cinder import interface
from cinder.volume.drivers.kaminario import kaminario_common as common
from oslo_log import log as logging
ISCSI_TCP_PORT = "3260"
LOG = logging.getLogger(__name__)
@ -37,20 +38,21 @@ class KaminarioISCSIDriver(common.KaminarioCinderDriver):
@kaminario_logger
def initialize_connection(self, volume, connector):
"""Get volume object and map to initiator host."""
if type(volume).__name__ != 'RestObject':
vol_name = self.get_volume_name(volume.id)
LOG.debug("Searching volume : %s in K2.", vol_name)
vol_rs = self.client.search("volumes", name=vol_name)
if not hasattr(vol_rs, 'hits') or vol_rs.total == 0:
msg = _("Unable to find volume: %s from K2.") % vol_name
LOG.error(msg)
raise exception.KaminarioCinderDriverException(reason=msg)
vol = vol_rs.hits[0]
else:
vol = volume
"""Get target_portal"""
LOG.debug("Searching first iscsi port ip without wan in K2.")
"""Attach K2 volume to host."""
# Get target_portal and target iqn.
iscsi_portal, target_iqn = self.get_target_info()
# Map volume.
lun = self.k2_initialize_connection(volume, connector)
# Return target volume information.
return {"driver_volume_type": "iscsi",
"data": {"target_iqn": target_iqn,
"target_portal": iscsi_portal,
"target_lun": lun,
"target_discovered": True}}
@kaminario_logger
def get_target_info(self):
LOG.debug("Searching first iscsi port ip without wan in K2.")
iscsi_ip_rs = self.client.search("system/net_ips", wan_port="")
iscsi_ip = target_iqn = None
if hasattr(iscsi_ip_rs, 'hits') and iscsi_ip_rs.total != 0:
@ -70,6 +72,10 @@ class KaminarioISCSIDriver(common.KaminarioCinderDriver):
msg = _("Unable to get target iqn from K2.")
LOG.error(msg)
raise exception.KaminarioCinderDriverException(reason=msg)
return iscsi_portal, target_iqn
@kaminario_logger
def _get_host_object(self, connector):
host_name = self.get_initiator_host_name(connector)
LOG.debug("Searching initiator hostname: %s in K2.", host_name)
host_rs = self.client.search("hosts", name=host_name)
@ -85,69 +91,12 @@ class KaminarioISCSIDriver(common.KaminarioCinderDriver):
host=host)
iqn.save()
except Exception as ex:
LOG.debug("Unable to create host : %s in K2.", host_name)
self.delete_host_by_name(host_name)
self._delete_host_by_name(host_name)
LOG.exception(_LE("Unable to create host: %s in K2."),
host_name)
raise exception.KaminarioCinderDriverException(
reason=six.text_type(ex.message))
else:
LOG.debug("Use existing initiator hostname: %s in K2.", host_name)
host = host_rs.hits[0]
try:
LOG.debug("Mapping volume: %(vol)s to host: %(host)s",
{'host': host_name, 'vol': vol.name})
mapping = self.client.new("mappings", volume=vol, host=host).save()
except Exception as ex:
if host_rs.total == 0:
LOG.debug("Unable to mapping volume:%(vol)s to host: %(host)s",
{'host': host_name, 'vol': vol.name})
self.delete_host_by_name(host_name)
raise exception.KaminarioCinderDriverException(
reason=six.text_type(ex.message))
if type(volume).__name__ == 'RestObject':
volsnap = None
LOG.debug("Searching volsnaps in K2.")
volsnaps = self.client.search("volsnaps")
for v in volsnaps.hits:
if v.snapshot.id == vol.id:
volsnap = v
break
LOG.debug("Searching mapping of volsnap in K2.")
rv = self.client.search("mappings", volume=volsnap)
lun = rv.hits[0].lun
else:
lun = mapping.lun
return {"driver_volume_type": "iscsi",
"data": {"target_iqn": target_iqn,
"target_portal": iscsi_portal,
"target_lun": lun,
"target_discovered": True}}
@kaminario_logger
def terminate_connection(self, volume, connector, **kwargs):
"""Terminate connection of volume from host."""
# Get volume object
if type(volume).__name__ != 'RestObject':
vol_name = self.get_volume_name(volume.id)
LOG.debug("Searching volume: %s in K2.", vol_name)
volume_rs = self.client.search("volumes", name=vol_name)
if hasattr(volume_rs, "hits") and volume_rs.total != 0:
volume = volume_rs.hits[0]
else:
vol_name = volume.name
# Get host object.
host_name = self.get_initiator_host_name(connector)
host_rs = self.client.search("hosts", name=host_name)
if hasattr(host_rs, "hits") and host_rs.total != 0 and volume:
host = host_rs.hits[0]
LOG.debug("Searching and deleting mapping of volume: %(name)s to "
"host: %(host)s", {'host': host_name, 'name': vol_name})
map_rs = self.client.search("mappings", volume=volume, host=host)
if hasattr(map_rs, "hits") and map_rs.total != 0:
map_rs.hits[0].delete()
if self.client.search("mappings", host=host).total == 0:
LOG.debug("Deleting initiator hostname: %s in K2.", host_name)
host.delete()
else:
LOG.warning(_LW("Host: %s not found on K2."), host_name)
return host, host_rs, host_name