Fuel plugin that enables to configure multiple Cinder backend support for Kaminario K2 All-Flash Array
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kaminario_iscsi.py 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # Copyright (c) 2016 by Kaminario Technologies, Ltd.
  2. # All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. # not use this file except in compliance with the License. You may obtain
  6. # a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. # License for the specific language governing permissions and limitations
  14. # under the License.
  15. """Volume driver for Kaminario K2 all-flash arrays."""
  16. import six
  17. from oslo_log import log as logging
  18. from cinder import coordination
  19. from cinder import exception
  20. from cinder.i18n import _, _LE
  21. from cinder import interface
  22. from cinder.objects import fields
  23. from cinder.volume.drivers.kaminario import kaminario_common as common
  24. ISCSI_TCP_PORT = "3260"
  25. LOG = logging.getLogger(__name__)
  26. kaminario_logger = common.kaminario_logger
  27. @interface.volumedriver
  28. class KaminarioISCSIDriver(common.KaminarioCinderDriver):
  29. """Kaminario K2 iSCSI Volume Driver.
  30. Version history:
  31. 1.0 - Initial driver
  32. 1.1 - Added manage/unmanage and extra-specs support for nodedup
  33. 1.2 - Added replication support
  34. 1.3 - Added retype support
  35. """
  36. VERSION = '1.3'
  37. # ThirdPartySystems wiki page name
  38. CI_WIKI_NAME = "Kaminario_K2_CI"
  39. @kaminario_logger
  40. def __init__(self, *args, **kwargs):
  41. super(KaminarioISCSIDriver, self).__init__(*args, **kwargs)
  42. self._protocol = 'iSCSI'
  43. @kaminario_logger
  44. @coordination.synchronized('{self.k2_lock_name}')
  45. def initialize_connection(self, volume, connector):
  46. """Attach K2 volume to host."""
  47. # Get target_portal and target iqn.
  48. iscsi_portal, target_iqn = self.get_target_info(volume)
  49. # Map volume.
  50. lun = self.k2_initialize_connection(volume, connector)
  51. # Return target volume information.
  52. return {"driver_volume_type": "iscsi",
  53. "data": {"target_iqn": target_iqn,
  54. "target_portal": iscsi_portal,
  55. "target_lun": lun,
  56. "target_discovered": True}}
  57. @kaminario_logger
  58. @coordination.synchronized('{self.k2_lock_name}')
  59. def terminate_connection(self, volume, connector, **kwargs):
  60. super(KaminarioISCSIDriver, self).terminate_connection(volume,
  61. connector)
  62. @kaminario_logger
  63. def get_target_info(self, volume):
  64. rep_status = fields.ReplicationStatus.FAILED_OVER
  65. if (hasattr(volume, 'replication_status') and
  66. volume.replication_status == rep_status):
  67. self.client = self.target
  68. LOG.debug("Searching first iscsi port ip without wan in K2.")
  69. iscsi_ip_rs = self.client.search("system/net_ips", wan_port="")
  70. iscsi_ip = target_iqn = None
  71. if hasattr(iscsi_ip_rs, 'hits') and iscsi_ip_rs.total != 0:
  72. iscsi_ip = iscsi_ip_rs.hits[0].ip_address
  73. if not iscsi_ip:
  74. msg = _("Unable to get ISCSI IP address from K2.")
  75. LOG.error(msg)
  76. raise exception.KaminarioCinderDriverException(reason=msg)
  77. iscsi_portal = "{0}:{1}".format(iscsi_ip, ISCSI_TCP_PORT)
  78. LOG.debug("Searching system state for target iqn in K2.")
  79. sys_state_rs = self.client.search("system/state")
  80. if hasattr(sys_state_rs, 'hits') and sys_state_rs.total != 0:
  81. target_iqn = sys_state_rs.hits[0].iscsi_qualified_target_name
  82. if not target_iqn:
  83. msg = _("Unable to get target iqn from K2.")
  84. LOG.error(msg)
  85. raise exception.KaminarioCinderDriverException(reason=msg)
  86. return iscsi_portal, target_iqn
  87. @kaminario_logger
  88. def _get_host_object(self, connector):
  89. host_name = self.get_initiator_host_name(connector)
  90. LOG.debug("Searching initiator hostname: %s in K2.", host_name)
  91. host_rs = self.client.search("hosts", name=host_name)
  92. """Create a host if not exists."""
  93. if host_rs.total == 0:
  94. try:
  95. LOG.debug("Creating initiator hostname: %s in K2.", host_name)
  96. host = self.client.new("hosts", name=host_name,
  97. type="Linux").save()
  98. LOG.debug("Adding iqn: %(iqn)s to host: %(host)s in K2.",
  99. {'iqn': connector['initiator'], 'host': host_name})
  100. iqn = self.client.new("host_iqns", iqn=connector['initiator'],
  101. host=host)
  102. iqn.save()
  103. except Exception as ex:
  104. self._delete_host_by_name(host_name)
  105. LOG.exception(_LE("Unable to create host: %s in K2."),
  106. host_name)
  107. raise exception.KaminarioCinderDriverException(
  108. reason=six.text_type(ex.message))
  109. else:
  110. LOG.debug("Use existing initiator hostname: %s in K2.", host_name)
  111. host = host_rs.hits[0]
  112. return host, host_rs, host_name