cinder/cinder/volume/drivers/prophetstor/dpl_iscsi.py

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