4b092e8d9d
Since NVMET target driver will be implemented it would be good to use the same config options both for NVMEoF and iSCSI targets. That's why this path renames iscsi_ip_address, iscsi_port, iscsi_helper iscsi_target_prefix, iscsi_protocol to target_ip_address, target_port, target_helper, target_prefix, and target_protocol according to current deprecation policy. Change-Id: I5231f8fe3399deb9c57e6efb121d0d008dc9c7f4 Related-Blueprint: nvme-target-cli
157 lines
6.9 KiB
Python
157 lines
6.9 KiB
Python
# Copyright (c) 2014 ProphetStor, Inc.
|
|
# 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
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import errno
|
|
|
|
from oslo_log import log as logging
|
|
|
|
from cinder import exception
|
|
from cinder.i18n import _
|
|
from cinder import interface
|
|
import cinder.volume.driver
|
|
from cinder.volume.drivers.prophetstor import dplcommon
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
@interface.volumedriver
|
|
class DPLISCSIDriver(dplcommon.DPLCOMMONDriver,
|
|
cinder.volume.driver.ISCSIDriver):
|
|
def __init__(self, *args, **kwargs):
|
|
super(DPLISCSIDriver, self).__init__(*args, **kwargs)
|
|
|
|
def initialize_connection(self, volume, connector):
|
|
"""Allow connection to connector and return connection info."""
|
|
properties = {}
|
|
properties['target_lun'] = None
|
|
properties['target_discovered'] = True
|
|
properties['target_portal'] = ''
|
|
properties['target_iqn'] = None
|
|
properties['volume_id'] = volume['id']
|
|
|
|
dpl_server = self.configuration.san_ip
|
|
dpl_iscsi_port = self.configuration.target_port
|
|
ret, output = self.dpl.assign_vdev(self._conver_uuid2hex(
|
|
volume['id']), connector['initiator'].lower(), volume['id'],
|
|
'%s:%d' % (dpl_server, dpl_iscsi_port), 0)
|
|
|
|
if ret == errno.EAGAIN:
|
|
ret, event_uuid = self._get_event_uuid(output)
|
|
if len(event_uuid):
|
|
ret = 0
|
|
status = self._wait_event(
|
|
self.dpl.get_vdev_status, self._conver_uuid2hex(
|
|
volume['id']), event_uuid)
|
|
if status['state'] == 'error':
|
|
ret = errno.EFAULT
|
|
msg = _('Flexvisor failed to assign volume %(id)s: '
|
|
'%(status)s.') % {'id': volume['id'],
|
|
'status': status}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
else:
|
|
ret = errno.EFAULT
|
|
msg = _('Flexvisor failed to assign volume %(id)s due to '
|
|
'unable to query status by event '
|
|
'id.') % {'id': volume['id']}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
elif ret != 0:
|
|
msg = _('Flexvisor assign volume failed.:%(id)s:'
|
|
'%(status)s.') % {'id': volume['id'], 'status': ret}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
|
|
if ret == 0:
|
|
ret, output = self.dpl.get_vdev(
|
|
self._conver_uuid2hex(volume['id']))
|
|
if ret == 0:
|
|
for tgInfo in output['exports']['Network/iSCSI']:
|
|
if tgInfo['permissions'] and \
|
|
isinstance(tgInfo['permissions'][0], dict):
|
|
for assign in tgInfo['permissions']:
|
|
if connector['initiator'].lower() in assign.keys():
|
|
for tgportal in tgInfo.get('portals', {}):
|
|
properties['target_portal'] = tgportal
|
|
break
|
|
properties['target_lun'] = \
|
|
int(assign[connector['initiator'].lower()])
|
|
break
|
|
|
|
if properties['target_portal'] != '':
|
|
properties['target_iqn'] = tgInfo['target_identifier']
|
|
break
|
|
else:
|
|
if connector['initiator'].lower() in tgInfo['permissions']:
|
|
for tgportal in tgInfo.get('portals', {}):
|
|
properties['target_portal'] = tgportal
|
|
break
|
|
|
|
if properties['target_portal'] != '':
|
|
properties['target_lun'] = \
|
|
int(tgInfo['logical_unit_number'])
|
|
properties['target_iqn'] = \
|
|
tgInfo['target_identifier']
|
|
break
|
|
|
|
if not (ret == 0 or properties['target_portal']):
|
|
msg = _('Flexvisor failed to assign volume %(volume)s '
|
|
'iqn %(iqn)s.') % {'volume': volume['id'],
|
|
'iqn': connector['initiator']}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
|
|
return {'driver_volume_type': 'iscsi', 'data': properties}
|
|
|
|
def terminate_connection(self, volume, connector, **kwargs):
|
|
"""Disallow connection from connector."""
|
|
ret, output = self.dpl.unassign_vdev(
|
|
self._conver_uuid2hex(volume['id']),
|
|
connector['initiator'])
|
|
|
|
if ret == errno.EAGAIN:
|
|
ret, event_uuid = self._get_event_uuid(output)
|
|
if ret == 0:
|
|
status = self._wait_event(
|
|
self.dpl.get_vdev_status, volume['id'], event_uuid)
|
|
if status['state'] == 'error':
|
|
ret = errno.EFAULT
|
|
msg = _('Flexvisor failed to unassign volume %(id)s:'
|
|
' %(status)s.') % {'id': volume['id'],
|
|
'status': status}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
else:
|
|
msg = _('Flexvisor failed to unassign volume (get event) '
|
|
'%(id)s.') % {'id': volume['id']}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
elif ret == errno.ENODATA:
|
|
LOG.info('Flexvisor already unassigned volume %(id)s.',
|
|
{'id': volume['id']})
|
|
elif ret != 0:
|
|
msg = _('Flexvisor failed to unassign volume:%(id)s:'
|
|
'%(status)s.') % {'id': volume['id'], 'status': ret}
|
|
raise exception.VolumeBackendAPIException(data=msg)
|
|
|
|
def get_volume_stats(self, refresh=False):
|
|
if refresh:
|
|
try:
|
|
data = super(DPLISCSIDriver, self).get_volume_stats(refresh)
|
|
if data:
|
|
data['storage_protocol'] = 'iSCSI'
|
|
backend_name = \
|
|
self.configuration.safe_get('volume_backend_name')
|
|
data['volume_backend_name'] = \
|
|
(backend_name or 'DPLISCSIDriver')
|
|
self._stats = data
|
|
except Exception as exc:
|
|
LOG.warning('Cannot get volume status %(exc)s.', {'exc': exc})
|
|
return self._stats
|