Files
cinder/cinder/volume/drivers/dell_emc/vnx/driver.py
Tina Tang 6359dcecd5 Add CG capability to generic groups in VNX driver
This patch adds the consistency group capability to generic group in
VNX driver. Consistency groups will be used as generic groups.

DocImpact:
Implements: blueprint vnx-generic-group
Change-Id: I92ad0032e5b4e0f72157febe64205a4d72a561e5
2017-01-10 02:27:49 +00:00

381 lines
15 KiB
Python

# Copyright (c) 2016 EMC Corporation.
# 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.
"""Cinder Driver for EMC VNX based on CLI."""
from oslo_log import log as logging
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.dell_emc.vnx import adapter
from cinder.volume.drivers.dell_emc.vnx import common
from cinder.volume.drivers.dell_emc.vnx import utils
from cinder.zonemanager import utils as zm_utils
LOG = logging.getLogger(__name__)
@interface.volumedriver
class VNXDriver(driver.TransferVD,
driver.ManageableVD,
driver.ExtendVD,
driver.SnapshotVD,
driver.ManageableSnapshotsVD,
driver.MigrateVD,
driver.ConsistencyGroupVD,
driver.BaseVD):
"""Dell EMC Cinder Driver for VNX using CLI.
Version history:
1.0.0 - Initial driver
2.0.0 - Thick/thin provisioning, robust enhancement
3.0.0 - Array-based Backend Support, FC Basic Support,
Target Port Selection for MPIO,
Initiator Auto Registration,
Storage Group Auto Deletion,
Multiple Authentication Type Support,
Storage-Assisted Volume Migration,
SP Toggle for HA
3.0.1 - Security File Support
4.0.0 - Advance LUN Features (Compression Support,
Deduplication Support, FAST VP Support,
FAST Cache Support), Storage-assisted Retype,
External Volume Management, Read-only Volume,
FC Auto Zoning
4.1.0 - Consistency group support
5.0.0 - Performance enhancement, LUN Number Threshold Support,
Initiator Auto Deregistration,
Force Deleting LUN in Storage Groups,
robust enhancement
5.1.0 - iSCSI multipath enhancement
5.2.0 - Pool-aware scheduler support
5.3.0 - Consistency group modification support
6.0.0 - Over subscription support
Create consistency group from cgsnapshot support
Multiple pools support enhancement
Manage/unmanage volume revise
White list target ports support
Snap copy support
Support efficient non-disruptive backup
7.0.0 - Clone consistency group support
Replication v2 support(managed)
Configurable migration rate support
8.0.0 - New VNX Cinder driver
"""
VERSION = '08.00.00'
VENDOR = 'Dell EMC'
# ThirdPartySystems wiki page
CI_WIKI_NAME = "EMC_VNX_CI"
def __init__(self, *args, **kwargs):
super(VNXDriver, self).__init__(*args, **kwargs)
utils.init_ops(self.configuration)
self.protocol = self.configuration.storage_protocol.lower()
self.active_backend_id = kwargs.get('active_backend_id', None)
self.adapter = None
self._stats = {}
def do_setup(self, context):
if self.protocol == common.PROTOCOL_FC:
self.adapter = adapter.FCAdapter(self.configuration,
self.active_backend_id)
else:
self.adapter = adapter.ISCSIAdapter(self.configuration,
self.active_backend_id)
self.adapter.VERSION = self.VERSION
self.adapter.do_setup()
def check_for_setup_error(self):
pass
def create_volume(self, volume):
"""Creates a volume."""
return self.adapter.create_volume(volume)
def create_volume_from_snapshot(self, volume, snapshot):
"""Creates a volume from a snapshot."""
return self.adapter.create_volume_from_snapshot(volume, snapshot)
def create_cloned_volume(self, volume, src_vref):
"""Creates a cloned volume."""
return self.adapter.create_cloned_volume(volume, src_vref)
def extend_volume(self, volume, new_size):
"""Extend a volume."""
self.adapter.extend_volume(volume, new_size)
def delete_volume(self, volume):
"""Deletes a volume."""
self.adapter.delete_volume(volume)
def migrate_volume(self, ctxt, volume, host):
"""Migrate volume via EMC migration functionality."""
return self.adapter.migrate_volume(ctxt, volume, host)
def retype(self, ctxt, volume, new_type, diff, host):
"""Convert the volume to be of the new type."""
return self.adapter.retype(ctxt, volume, new_type, diff, host)
def create_snapshot(self, snapshot):
"""Creates a snapshot."""
self.adapter.create_snapshot(snapshot)
def delete_snapshot(self, snapshot):
"""Deletes a snapshot."""
self.adapter.delete_snapshot(snapshot)
def ensure_export(self, context, volume):
"""Driver entry point to get the export info for an existing volume."""
pass
def create_export(self, context, volume, connector):
"""Driver entry point to get the export info for a new volume."""
pass
def remove_export(self, context, volume):
"""Driver entry point to remove an export for a volume."""
pass
def check_for_export(self, context, volume_id):
"""Make sure volume is exported."""
pass
@zm_utils.AddFCZone
def initialize_connection(self, volume, connector):
"""Initializes the connection and returns connection info.
Assign any created volume to a compute node/host so that it can be
used from that host.
The driver returns a driver_volume_type of 'fibre_channel'.
The target_wwn can be a single entry or a list of wwns that
correspond to the list of remote wwn(s) that will export the volume.
The initiator_target_map is a map that represents the remote wwn(s)
and a list of wwns which are visible to the remote wwn(s).
Example return values:
FC:
{
'driver_volume_type': 'fibre_channel'
'data': {
'target_discovered': True,
'target_lun': 1,
'target_wwn': ['1234567890123', '0987654321321'],
'initiator_target_map': {
'1122334455667788': ['1234567890123',
'0987654321321']
}
}
}
iSCSI:
{
'driver_volume_type': 'iscsi'
'data': {
'target_discovered': True,
'target_iqns': ['iqn.2010-10.org.openstack:volume-00001',
'iqn.2010-10.org.openstack:volume-00002'],
'target_portals': ['127.0.0.1:3260', '127.0.1.1:3260'],
'target_luns': [1, 1],
}
}
"""
LOG.debug("Entering initialize_connection"
" - connector: %(connector)s.",
{'connector': connector})
conn_info = self.adapter.initialize_connection(volume,
connector)
LOG.debug("Exit initialize_connection"
" - Returning connection info: %(conn_info)s.",
{'conn_info': conn_info})
return conn_info
@zm_utils.RemoveFCZone
def terminate_connection(self, volume, connector, **kwargs):
"""Disallow connection from connector."""
LOG.debug("Entering terminate_connection"
" - connector: %(connector)s.",
{'connector': connector})
conn_info = self.adapter.terminate_connection(volume, connector)
LOG.debug("Exit terminate_connection"
" - Returning connection info: %(conn_info)s.",
{'conn_info': conn_info})
return conn_info
def get_volume_stats(self, refresh=False):
"""Get volume stats.
:param refresh: True to get updated data
"""
if refresh:
self.update_volume_stats()
return self._stats
def update_volume_stats(self):
"""Retrieve stats info from volume group."""
LOG.debug("Updating volume stats.")
self._stats = self.adapter.update_volume_stats()
self._stats['driver_version'] = self.VERSION
self._stats['vendor_name'] = self.VENDOR
def manage_existing(self, volume, existing_ref):
"""Manage an existing lun in the array.
The lun should be in a manageable pool backend, otherwise
error would return.
Rename the backend storage object so that it matches the,
volume['name'] which is how drivers traditionally map between a
cinder volume and the associated backend storage object.
manage_existing_ref:{
'source-id':<lun id in VNX>
}
or
manage_existing_ref:{
'source-name':<lun name in VNX>
}
"""
return self.adapter.manage_existing(volume, existing_ref)
def manage_existing_get_size(self, volume, existing_ref):
"""Return size of volume to be managed by manage_existing."""
return self.adapter.manage_existing_get_size(volume, existing_ref)
def create_consistencygroup(self, context, group):
"""Creates a consistencygroup."""
return self.adapter.create_consistencygroup(context, group)
def delete_consistencygroup(self, context, group, volumes):
"""Deletes a consistency group."""
return self.adapter.delete_consistencygroup(
context, group, volumes)
def create_cgsnapshot(self, context, cgsnapshot, snapshots):
"""Creates a cgsnapshot."""
return self.adapter.create_cgsnapshot(
context, cgsnapshot, snapshots)
def delete_cgsnapshot(self, context, cgsnapshot, snapshots):
"""Deletes a cgsnapshot."""
return self.adapter.delete_cgsnapshot(
context, cgsnapshot, snapshots)
def get_pool(self, volume):
"""Returns the pool name of a volume."""
return self.adapter.get_pool_name(volume)
def update_consistencygroup(self, context, group,
add_volumes,
remove_volumes):
"""Updates LUNs in consistency group."""
return self.adapter.update_consistencygroup(context, group,
add_volumes,
remove_volumes)
def unmanage(self, volume):
"""Unmanages a volume."""
return self.adapter.unmanage(volume)
def create_consistencygroup_from_src(self, context, group, volumes,
cgsnapshot=None, snapshots=None,
source_cg=None, source_vols=None):
"""Creates a consistency group from source."""
if cgsnapshot:
return self.adapter.create_cg_from_cgsnapshot(
context, group, volumes, cgsnapshot, snapshots)
elif source_cg:
return self.adapter.create_cloned_cg(
context, group, volumes, source_cg, source_vols)
def update_migrated_volume(self, context, volume, new_volume,
original_volume_status=None):
"""Returns model update for migrated volume."""
return self.adapter.update_migrated_volume(context, volume, new_volume,
original_volume_status)
def create_export_snapshot(self, context, snapshot, connector):
"""Creates a snapshot mount point for snapshot."""
return self.adapter.create_export_snapshot(
context, snapshot, connector)
def remove_export_snapshot(self, context, snapshot):
"""Removes snapshot mount point for snapshot."""
return self.adapter.remove_export_snapshot(context, snapshot)
def initialize_connection_snapshot(self, snapshot, connector, **kwargs):
"""Allows connection to snapshot."""
return self.adapter.initialize_connection_snapshot(snapshot,
connector,
**kwargs)
def terminate_connection_snapshot(self, snapshot, connector, **kwargs):
"""Disallows connection to snapshot."""
return self.adapter.terminate_connection_snapshot(snapshot,
connector,
**kwargs)
def backup_use_temp_snapshot(self):
return True
def failover_host(self, context, volumes, secondary_id=None):
"""Fail-overs volumes from primary device to secondary."""
return self.adapter.failover_host(context, volumes, secondary_id)
@utils.require_consistent_group_snapshot_enabled
def create_group(self, context, group):
"""Creates a group."""
return self.adapter.create_group(context, group)
@utils.require_consistent_group_snapshot_enabled
def delete_group(self, context, group, volumes):
"""Deletes a group."""
return self.adapter.delete_group(
context, group, volumes)
@utils.require_consistent_group_snapshot_enabled
def update_group(self, context, group,
add_volumes=None, remove_volumes=None):
"""Updates a group."""
return self.adapter.update_group(context, group,
add_volumes,
remove_volumes)
@utils.require_consistent_group_snapshot_enabled
def create_group_from_src(self, context, group, volumes,
group_snapshot=None, snapshots=None,
source_group=None, source_vols=None):
"""Creates a group from source."""
if group_snapshot:
return self.adapter.create_group_from_group_snapshot(
context, group, volumes, group_snapshot, snapshots)
elif source_group:
return self.adapter.create_cloned_group(
context, group, volumes, source_group, source_vols)
@utils.require_consistent_group_snapshot_enabled
def create_group_snapshot(self, context, group_snapshot, snapshots):
"""Creates a group_snapshot."""
return self.adapter.create_group_snapshot(
context, group_snapshot, snapshots)
@utils.require_consistent_group_snapshot_enabled
def delete_group_snapshot(self, context, group_snapshot, snapshots):
"""Deletes a group_snapshot."""
return self.adapter.delete_group_snapshot(
context, group_snapshot, snapshots)
def is_consistent_group_snapshot_enabled(self):
return self._stats.get('consistent_group_snapshot_enabled')