--- a/components/openstack/cinder/files/zfssa/zfssaiscsi.py Fri Mar 20 03:13:26 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,376 +0,0 @@
-# Copyright (c) 2014, Oracle and/or its affiliates. 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.
-"""
-ZFS Storage Appliance Cinder Volume Driver
-"""
-import base64
-
-from cinder import exception
-from cinder.openstack.common import log
-from cinder.volume import driver
-from oslo.config import cfg
-
-from cinder.volume.drivers.zfssa import zfssarest
-
-
-CONF = cfg.CONF
-LOG = log.getLogger(__name__)
-
-ZFSSA_OPTS = [
- cfg.StrOpt('zfssa_host', required=True,
- help='ZFSSA management IP address'),
- cfg.StrOpt('zfssa_auth_user', required=True, secret=True,
- help='ZFSSA management authorized user\'s name'),
- cfg.StrOpt('zfssa_auth_password', required=True, secret=True,
- help='ZFSSA management authorized user\'s password'),
- cfg.StrOpt('zfssa_pool', required=True,
- help='ZFSSA storage pool name'),
- cfg.StrOpt('zfssa_project', required=True,
- help='ZFSSA project name'),
- cfg.StrOpt('zfssa_lun_volblocksize', default='8k',
- help='Block size: 512, 1k, 2k, 4k, 8k, 16k, 32k, 64k, 128k'),
- cfg.BoolOpt('zfssa_lun_sparse', default=False,
- help='Flag to enable sparse (thin-provisioned): True, False'),
- cfg.StrOpt('zfssa_lun_compression', default='',
- help='Data compression-off, lzjb, gzip-2, gzip, gzip-9'),
- cfg.StrOpt('zfssa_lun_logbias', default='',
- help='Synchronous write bias-latency, throughput'),
- cfg.StrOpt('zfssa_initiator_group', default='',
- help='iSCSI initiator group'),
- cfg.StrOpt('zfssa_initiator', default='',
- help='iSCSI initiator IQNs (comma separated)'),
- cfg.StrOpt('zfssa_initiator_user', default='',
- help='iSCSI initiator CHAP user'),
- cfg.StrOpt('zfssa_initiator_password', default='',
- help='iSCSI initiator CHAP password'),
- cfg.StrOpt('zfssa_target_group', default='tgt-grp',
- help='iSCSI target group name'),
- cfg.StrOpt('zfssa_target_user', default='',
- help='iSCSI target CHAP user'),
- cfg.StrOpt('zfssa_target_password', default='',
- help='iSCSI target CHAP password'),
- cfg.StrOpt('zfssa_target_portal', required=True,
- help='iSCSI target portal (Data-IP:Port, w.x.y.z:3260)'),
- cfg.StrOpt('zfssa_target_interfaces', required=True,
- help='Network interfaces of iSCSI targets (comma separated)')
-]
-
-CONF.register_opts(ZFSSA_OPTS)
-
-SIZE_GB = 1073741824
-
-
-#pylint: disable=R0904
-class ZFSSAISCSIDriver(driver.ISCSIDriver):
- """ZFSSA Cinder volume driver"""
-
- VERSION = '1.0.0'
- protocol = 'iSCSI'
-
- def __init__(self, *args, **kwargs):
- super(ZFSSAISCSIDriver, self).__init__(*args, **kwargs)
- self.configuration.append_config_values(ZFSSA_OPTS)
- self.zfssa = None
- self._stats = None
-
- def _get_target_alias(self):
- """return target alias"""
- return self.configuration.zfssa_target_group
-
- def do_setup(self, context):
- """Setup - create project, initiators, initiatorgroup, target,
- targetgroup
- """
- self.configuration._check_required_opts()
- lcfg = self.configuration
-
- LOG.info('Connecting to host: %s' % lcfg.zfssa_host)
- self.zfssa = zfssarest.ZFSSAApi(lcfg.zfssa_host)
- auth_str = base64.encodestring('%s:%s' %
- (lcfg.zfssa_auth_user,
- lcfg.zfssa_auth_password))[:-1]
- self.zfssa.login(auth_str)
- self.zfssa.create_project(lcfg.zfssa_pool, lcfg.zfssa_project,
- compression=lcfg.zfssa_lun_compression,
- logbias=lcfg.zfssa_lun_logbias)
-
- if (lcfg.zfssa_initiator != '' and
- (lcfg.zfssa_initiator_group == '' or
- lcfg.zfssa_initiator_group == 'default')):
- LOG.warning('zfssa_initiator= %s wont be used on \
- zfssa_initiator_group= %s' %
- (lcfg.zfssa_initiator,
- lcfg.zfssa_initiator_group))
-
- # Setup initiator and initiator group
- if lcfg.zfssa_initiator != '' and \
- lcfg.zfssa_initiator_group != '' and \
- lcfg.zfssa_initiator_group != 'default':
- for initiator in lcfg.zfssa_initiator.split(','):
- self.zfssa.create_initiator(initiator,
- lcfg.zfssa_initiator_group + '-' +
- initiator,
- chapuser=
- lcfg.zfssa_initiator_user,
- chapsecret=
- lcfg.zfssa_initiator_password)
- self.zfssa.add_to_initiatorgroup(initiator,
- lcfg.zfssa_initiator_group)
- # Parse interfaces
- interfaces = []
- for interface in lcfg.zfssa_target_interfaces.split(','):
- if interface == '':
- continue
- interfaces.append(interface)
-
- # Setup target and target group
- iqn = self.zfssa.create_target(
- self._get_target_alias(),
- interfaces,
- tchapuser=lcfg.zfssa_target_user,
- tchapsecret=lcfg.zfssa_target_password)
-
- self.zfssa.add_to_targetgroup(iqn, lcfg.zfssa_target_group)
-
- def check_for_setup_error(self):
- """Check that driver can login and pool, project, initiators,
- initiatorgroup, target, targetgroup exist
- """
- lcfg = self.configuration
-
- self.zfssa.verify_pool(lcfg.zfssa_pool)
- self.zfssa.verify_project(lcfg.zfssa_pool, lcfg.zfssa_project)
-
- if lcfg.zfssa_initiator != '' and \
- lcfg.zfssa_initiator_group != '' and \
- lcfg.zfssa_initiator_group != 'default':
- for initiator in lcfg.zfssa_initiator.split(','):
- self.zfssa.verify_initiator(initiator)
-
- self.zfssa.verify_target(self._get_target_alias())
-
- def _get_provider_info(self, volume):
- """return provider information"""
- lcfg = self.configuration
- lun = self.zfssa.get_lun(lcfg.zfssa_pool,
- lcfg.zfssa_project, volume['name'])
- iqn = self.zfssa.get_target(self._get_target_alias())
- loc = "%s %s %s" % (lcfg.zfssa_target_portal, iqn, lun['number'])
- LOG.debug('_export_volume: provider_location: %s' % loc)
- provider = {'provider_location': loc}
- if lcfg.zfssa_target_user != '' and lcfg.zfssa_target_password != '':
- provider['provider_auth'] = 'CHAP %s %s' % \
- (lcfg.zfssa_target_user,
- lcfg.zfssa_target_password)
- return provider
-
- def create_volume(self, volume):
- """Create a volume on ZFSSA"""
- LOG.debug('zfssa.create_volume: volume=' + volume['name'])
- lcfg = self.configuration
- volsize = str(volume['size']) + 'g'
- self.zfssa.create_lun(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- volume['name'],
- volsize,
- targetgroup=lcfg.zfssa_target_group,
- volblocksize=lcfg.zfssa_lun_volblocksize,
- sparse=lcfg.zfssa_lun_sparse,
- compression=lcfg.zfssa_lun_compression,
- logbias=lcfg.zfssa_lun_logbias)
-
- return self._get_provider_info(volume)
-
- def delete_volume(self, volume):
- """Deletes a volume with the given volume['name']."""
- LOG.debug('zfssa.delete_volume: name=' + volume['name'])
- lcfg = self.configuration
- lun2del = self.zfssa.get_lun(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- volume['name'])
- """Delete clone's temp snapshot. see create_cloned_volume()"""
- """clone is deleted as part of the snapshot delete."""
- tmpsnap = 'tmp-snapshot-%s' % volume['id']
- if 'origin' in lun2del and lun2del['origin']['snapshot'] == tmpsnap:
- self.zfssa.delete_snapshot(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- lun2del['origin']['share'],
- lun2del['origin']['snapshot'])
- return
-
- self.zfssa.delete_lun(pool=lcfg.zfssa_pool,
- project=lcfg.zfssa_project,
- lun=volume['name'])
-
- def create_snapshot(self, snapshot):
- """Creates a snapshot with the given snapshot['name'] of the
- snapshot['volume_name']
- """
- LOG.debug('zfssa.create_snapshot: snapshot=' + snapshot['name'])
- lcfg = self.configuration
- self.zfssa.create_snapshot(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- snapshot['volume_name'],
- snapshot['name'])
-
- def delete_snapshot(self, snapshot):
- """Deletes a snapshot."""
- LOG.debug('zfssa.delete_snapshot: snapshot=' + snapshot['name'])
- lcfg = self.configuration
- has_clones = self.zfssa.has_clones(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- snapshot['volume_name'],
- snapshot['name'])
- if has_clones:
- LOG.error('snapshot %s: has clones' % snapshot['name'])
- raise exception.SnapshotIsBusy(snapshot_name=snapshot['name'])
-
- self.zfssa.delete_snapshot(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- snapshot['volume_name'],
- snapshot['name'])
-
- def create_volume_from_snapshot(self, volume, snapshot):
- """Creates a volume from a snapshot - clone a snapshot"""
- LOG.debug('zfssa.create_volume_from_snapshot: volume=' +
- volume['name'])
- LOG.debug('zfssa.create_volume_from_snapshot: snapshot=' +
- snapshot['name'])
- if not self._verify_clone_size(snapshot, volume['size'] * SIZE_GB):
- exception_msg = (_('Error verifying clone size on '
- 'Volume clone: %(clone)s '
- 'Size: %(size)d on'
- 'Snapshot: %(snapshot)s')
- % {'clone': volume['name'],
- 'size': volume['size'],
- 'snapshot': snapshot['name']})
- LOG.error(exception_msg)
- raise exception.InvalidInput(reason=exception_msg)
-
- lcfg = self.configuration
- self.zfssa.clone_snapshot(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- snapshot['volume_name'],
- snapshot['name'],
- volume['name'])
-
- def _update_volume_status(self):
- """Retrieve status info from volume group."""
- LOG.debug("Updating volume status")
- self._stats = None
- data = {}
- data["volume_backend_name"] = self.__class__.__name__
- data["vendor_name"] = 'Oracle'
- data["driver_version"] = self.VERSION
- data["storage_protocol"] = self.protocol
-
- lcfg = self.configuration
- (avail, used) = self.zfssa.get_pool_stats(lcfg.zfssa_pool)
- if avail is None or used is None:
- return
- total = int(avail) + int(used)
-
- if lcfg.zfssa_lun_sparse:
- data['total_capacity_gb'] = 'infinite'
- else:
- data['total_capacity_gb'] = total / SIZE_GB
- data['free_capacity_gb'] = int(avail) / SIZE_GB
- data['reserved_percentage'] = 0
- data['QoS_support'] = False
- self._stats = data
-
- def get_volume_stats(self, refresh=False):
- """Get volume status.
- If 'refresh' is True, run update the stats first.
- """
- if refresh:
- self._update_volume_status()
- return self._stats
-
- def _export_volume(self, volume):
- """Export the volume - set the initiatorgroup property."""
- LOG.debug('_export_volume: volume name: %s' % volume['name'])
- lcfg = self.configuration
-
- self.zfssa.set_lun_initiatorgroup(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- volume['name'],
- lcfg.zfssa_initiator_group)
- return self._get_provider_info(volume)
-
- def create_export(self, context, volume):
- """Driver entry point to get the export info for a new volume."""
- LOG.debug('create_export: volume name: %s' % volume['name'])
- return self._export_volume(volume)
-
- def remove_export(self, context, volume):
- """Driver entry point to remove an export for a volume."""
- LOG.debug('remove_export: volume name: %s' % volume['name'])
- lcfg = self.configuration
- self.zfssa.set_lun_initiatorgroup(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- volume['name'],
- '')
-
- def ensure_export(self, context, volume):
- """Driver entry point to get the export info for an existing volume."""
- LOG.debug('ensure_export: volume name: %s' % volume['name'])
- return self._export_volume(volume)
-
- def copy_image_to_volume(self, context, volume, image_service, image_id):
- self.ensure_export(context, volume)
- super(ZFSSAISCSIDriver, self).copy_image_to_volume(
- context, volume, image_service, image_id)
-
- def extend_volume(self, volume, new_size):
- """Driver entry point to extent volume size."""
- LOG.debug('extend_volume: volume name: %s' % volume['name'])
- lcfg = self.configuration
- self.zfssa.set_lun_size(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- volume['name'],
- new_size * SIZE_GB)
-
- def create_cloned_volume(self, volume, src_vref):
- """Create a clone of the specified volume."""
- zfssa_snapshot = {'volume_name': src_vref['name'],
- 'name': 'tmp-snapshot-%s' % volume['id']}
- self.create_snapshot(zfssa_snapshot)
- try:
- self.create_volume_from_snapshot(volume, zfssa_snapshot)
- except exception.VolumeBackendAPIException:
- LOG.error("Clone Volume '%s' failed from source volume '%s'"
- % (volume['name'], src_vref['name']))
- # Cleanup snapshot
- self.delete_snapshot(zfssa_snapshot)
-
- def local_path(self, volume):
- """Not implemented"""
- pass
-
- def backup_volume(self, context, backup, backup_service):
- """Not implemented"""
- pass
-
- def restore_backup(self, context, backup, volume, backup_service):
- """Not implemented"""
- pass
-
- def _verify_clone_size(self, snapshot, size):
- """Check whether the clone size is the same as the parent volume"""
- lcfg = self.configuration
- lun = self.zfssa.get_lun(lcfg.zfssa_pool,
- lcfg.zfssa_project,
- snapshot['volume_name'])
- return (lun['size'] == size)