HPE 3PAR: Reuse existing session
The 3PAR driver creates new SSH connection to the backend for each operation (eg. create/delete volume). There is a limit on maximum number of SSH connections from 3PAR backend i.e 24 connections. The problem is that when multiple concurrent operations are performed, this limit gets reached & further operations get errored out. This patch performs two things: [a] Instead of creating new session for each operation, an attempt is made to reuse existing session for as most operations. [b] Since WSAPI of 3PAR has evolved, wsapi (http/https) requests are used; thus SSH connections are no longer required. Closes-Bug: #1940069 Change-Id: Ica59db93a0153be9ab2e5e9165651173d9b2afd0
This commit is contained in:
parent
98b49d0572
commit
1daded7951
File diff suppressed because it is too large
Load Diff
@ -71,32 +71,34 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
self.configuration.append_config_values(hpecommon.hpe3par_opts)
|
||||
self.configuration.append_config_values(san.san_opts)
|
||||
self.protocol = None
|
||||
self.common = None
|
||||
|
||||
@staticmethod
|
||||
def get_driver_options():
|
||||
return hpecommon.HPE3PARCommon.get_driver_options()
|
||||
|
||||
def _init_common(self):
|
||||
return hpecommon.HPE3PARCommon(self.configuration,
|
||||
self._active_backend_id)
|
||||
self.common = hpecommon.HPE3PARCommon(self.configuration,
|
||||
self._active_backend_id)
|
||||
return self.common
|
||||
|
||||
def _login(self, timeout=None, array_id=None):
|
||||
common = self._init_common()
|
||||
self.common = self._init_common()
|
||||
# If replication is enabled and we cannot login, we do not want to
|
||||
# raise an exception so a failover can still be executed.
|
||||
try:
|
||||
common.do_setup(None, timeout=timeout, stats=self._stats,
|
||||
array_id=array_id)
|
||||
common.client_login()
|
||||
self.common.do_setup(None, timeout=timeout, stats=self._stats,
|
||||
array_id=array_id)
|
||||
self.common.client_login()
|
||||
except Exception:
|
||||
if common._replication_enabled:
|
||||
if self.common._replication_enabled:
|
||||
LOG.warning("The primary array is not reachable at this "
|
||||
"time. Since replication is enabled, "
|
||||
"listing replication targets and failing over "
|
||||
"a volume can still be performed.")
|
||||
else:
|
||||
raise
|
||||
return common
|
||||
return self.common
|
||||
|
||||
def _logout(self, common):
|
||||
# If replication is enabled and we do not have a client ID, we did not
|
||||
@ -128,20 +130,17 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
if not refresh:
|
||||
return self._stats
|
||||
|
||||
common = self._login()
|
||||
try:
|
||||
self._stats = common.get_volume_stats(
|
||||
refresh,
|
||||
self.get_filter_function(),
|
||||
self.get_goodness_function())
|
||||
self._stats['storage_protocol'] = self.protocol
|
||||
self._stats['driver_version'] = self.VERSION
|
||||
backend_name = self.configuration.safe_get('volume_backend_name')
|
||||
self._stats['volume_backend_name'] = (backend_name or
|
||||
self.__class__.__name__)
|
||||
return self._stats
|
||||
finally:
|
||||
self._logout(common)
|
||||
self._stats = self.common.get_volume_stats(
|
||||
refresh,
|
||||
self.get_filter_function(),
|
||||
self.get_goodness_function())
|
||||
|
||||
self._stats['storage_protocol'] = self.protocol
|
||||
self._stats['driver_version'] = self.VERSION
|
||||
backend_name = self.configuration.safe_get('volume_backend_name')
|
||||
self._stats['volume_backend_name'] = (backend_name or
|
||||
self.__class__.__name__)
|
||||
return self._stats
|
||||
|
||||
def check_for_setup_error(self):
|
||||
"""Setup errors are already checked for in do_setup so return pass."""
|
||||
@ -149,28 +148,16 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
|
||||
@volume_utils.trace
|
||||
def create_volume(self, volume):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.create_volume(volume)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_volume(volume)
|
||||
|
||||
@volume_utils.trace
|
||||
def create_cloned_volume(self, volume, src_vref):
|
||||
"""Clone an existing volume."""
|
||||
common = self._login()
|
||||
try:
|
||||
return common.create_cloned_volume(volume, src_vref)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_cloned_volume(volume, src_vref)
|
||||
|
||||
@volume_utils.trace
|
||||
def delete_volume(self, volume):
|
||||
common = self._login()
|
||||
try:
|
||||
common.delete_volume(volume)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.delete_volume(volume)
|
||||
|
||||
@volume_utils.trace
|
||||
def create_volume_from_snapshot(self, volume, snapshot):
|
||||
@ -178,140 +165,76 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
|
||||
TODO: support using the size from the user.
|
||||
"""
|
||||
common = self._login()
|
||||
try:
|
||||
return common.create_volume_from_snapshot(volume, snapshot)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_volume_from_snapshot(volume, snapshot)
|
||||
|
||||
@volume_utils.trace
|
||||
def create_snapshot(self, snapshot):
|
||||
common = self._login()
|
||||
try:
|
||||
common.create_snapshot(snapshot)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_snapshot(snapshot)
|
||||
|
||||
@volume_utils.trace
|
||||
def delete_snapshot(self, snapshot):
|
||||
common = self._login()
|
||||
try:
|
||||
common.delete_snapshot(snapshot)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.delete_snapshot(snapshot)
|
||||
|
||||
@volume_utils.trace
|
||||
def extend_volume(self, volume, new_size):
|
||||
common = self._login()
|
||||
try:
|
||||
common.extend_volume(volume, new_size)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.extend_volume(volume, new_size)
|
||||
|
||||
@volume_utils.trace
|
||||
def create_group(self, context, group):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.create_group(context, group)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_group(context, group)
|
||||
|
||||
@volume_utils.trace
|
||||
def create_group_from_src(self, context, group, volumes,
|
||||
group_snapshot=None, snapshots=None,
|
||||
source_group=None, source_vols=None):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.create_group_from_src(
|
||||
context, group, volumes, group_snapshot, snapshots,
|
||||
source_group, source_vols)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_group_from_src(
|
||||
context, group, volumes, group_snapshot, snapshots,
|
||||
source_group, source_vols)
|
||||
|
||||
@volume_utils.trace
|
||||
def delete_group(self, context, group, volumes):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.delete_group(context, group, volumes)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.delete_group(context, group, volumes)
|
||||
|
||||
@volume_utils.trace
|
||||
def update_group(self, context, group, add_volumes=None,
|
||||
remove_volumes=None):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.update_group(context, group, add_volumes,
|
||||
remove_volumes)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.update_group(context, group, add_volumes,
|
||||
remove_volumes)
|
||||
|
||||
@volume_utils.trace
|
||||
def create_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.create_group_snapshot(context, group_snapshot,
|
||||
snapshots)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.create_group_snapshot(context, group_snapshot,
|
||||
snapshots)
|
||||
|
||||
@volume_utils.trace
|
||||
def delete_group_snapshot(self, context, group_snapshot, snapshots):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.delete_group_snapshot(context, group_snapshot,
|
||||
snapshots)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.delete_group_snapshot(context, group_snapshot,
|
||||
snapshots)
|
||||
|
||||
@volume_utils.trace
|
||||
def manage_existing(self, volume, existing_ref):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.manage_existing(volume, existing_ref)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.manage_existing(volume, existing_ref)
|
||||
|
||||
@volume_utils.trace
|
||||
def manage_existing_snapshot(self, snapshot, existing_ref):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.manage_existing_snapshot(snapshot, existing_ref)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.manage_existing_snapshot(snapshot, existing_ref)
|
||||
|
||||
@volume_utils.trace
|
||||
def manage_existing_get_size(self, volume, existing_ref):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.manage_existing_get_size(volume, existing_ref)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.manage_existing_get_size(volume, existing_ref)
|
||||
|
||||
@volume_utils.trace
|
||||
def manage_existing_snapshot_get_size(self, snapshot, existing_ref):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.manage_existing_snapshot_get_size(snapshot,
|
||||
existing_ref)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.manage_existing_snapshot_get_size(snapshot,
|
||||
existing_ref)
|
||||
|
||||
@volume_utils.trace
|
||||
def unmanage(self, volume):
|
||||
common = self._login()
|
||||
try:
|
||||
common.unmanage(volume)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.unmanage(volume)
|
||||
|
||||
@volume_utils.trace
|
||||
def unmanage_snapshot(self, snapshot):
|
||||
common = self._login()
|
||||
try:
|
||||
common.unmanage_snapshot(snapshot)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.unmanage_snapshot(snapshot)
|
||||
|
||||
@volume_utils.trace
|
||||
def retype(self, context, volume, new_type, diff, host):
|
||||
@ -334,43 +257,28 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
'storage_protocol': protocol})
|
||||
return False, None
|
||||
|
||||
common = self._login()
|
||||
try:
|
||||
return common.migrate_volume(volume, host)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.migrate_volume(volume, host)
|
||||
|
||||
@volume_utils.trace
|
||||
def update_migrated_volume(self, context, volume, new_volume,
|
||||
original_volume_status):
|
||||
"""Update the name of the migrated volume to it's new ID."""
|
||||
common = self._login()
|
||||
try:
|
||||
return common.update_migrated_volume(context, volume, new_volume,
|
||||
original_volume_status)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.update_migrated_volume(context, volume, new_volume,
|
||||
original_volume_status)
|
||||
|
||||
@volume_utils.trace
|
||||
def get_pool(self, volume):
|
||||
common = self._login()
|
||||
try:
|
||||
return common.get_cpg(volume)
|
||||
return self.common.get_cpg(volume)
|
||||
except hpeexceptions.HTTPNotFound:
|
||||
reason = (_("Volume %s doesn't exist on array.") % volume)
|
||||
LOG.error(reason)
|
||||
raise exception.InvalidVolume(reason)
|
||||
finally:
|
||||
self._logout(common)
|
||||
|
||||
@volume_utils.trace
|
||||
def revert_to_snapshot(self, context, volume, snapshot):
|
||||
"""Revert volume to snapshot."""
|
||||
common = self._login()
|
||||
try:
|
||||
common.revert_to_snapshot(volume, snapshot)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.revert_to_snapshot(volume, snapshot)
|
||||
|
||||
@volume_utils.trace
|
||||
def failover_host(self, context, volumes, secondary_id=None, groups=None):
|
||||
@ -394,11 +302,7 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
:param volumes: the list of volumes
|
||||
:returns: model_update, None
|
||||
"""
|
||||
common = self._login()
|
||||
try:
|
||||
return common.enable_replication(context, group, volumes)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.enable_replication(context, group, volumes)
|
||||
|
||||
def disable_replication(self, context, group, volumes):
|
||||
"""Disable replication for a group.
|
||||
@ -408,11 +312,7 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
:param volumes: the list of volumes
|
||||
:returns: model_update, None
|
||||
"""
|
||||
common = self._login()
|
||||
try:
|
||||
return common.disable_replication(context, group, volumes)
|
||||
finally:
|
||||
self._logout(common)
|
||||
return self.common.disable_replication(context, group, volumes)
|
||||
|
||||
def failover_replication(self, context, group, volumes,
|
||||
secondary_backend_id=None):
|
||||
|
@ -422,20 +422,6 @@ class HPE3PARCommon(object):
|
||||
LOG.error(msg)
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
known_hosts_file = CONF.ssh_hosts_key_file
|
||||
policy = "AutoAddPolicy"
|
||||
if CONF.strict_ssh_host_key_policy:
|
||||
policy = "RejectPolicy"
|
||||
self.client.setSSHOptions(
|
||||
self._client_conf['san_ip'],
|
||||
self._client_conf['san_login'],
|
||||
self._client_conf['san_password'],
|
||||
port=self._client_conf['san_ssh_port'],
|
||||
conn_timeout=self._client_conf['ssh_conn_timeout'],
|
||||
privatekey=self._client_conf['san_private_key'],
|
||||
missing_key_policy=policy,
|
||||
known_hosts_file=known_hosts_file)
|
||||
|
||||
def client_logout(self):
|
||||
LOG.debug("Disconnect from 3PAR REST and SSH %s", self.uuid)
|
||||
self.client.logout()
|
||||
@ -451,19 +437,6 @@ class HPE3PARCommon(object):
|
||||
LOG.error(msg)
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
known_hosts_file = CONF.ssh_hosts_key_file
|
||||
policy = "AutoAddPolicy"
|
||||
if CONF.strict_ssh_host_key_policy:
|
||||
policy = "RejectPolicy"
|
||||
cl.setSSHOptions(
|
||||
remote_array['san_ip'],
|
||||
remote_array['san_login'],
|
||||
remote_array['san_password'],
|
||||
port=remote_array['san_ssh_port'],
|
||||
conn_timeout=remote_array['ssh_conn_timeout'],
|
||||
privatekey=remote_array['san_private_key'],
|
||||
missing_key_policy=policy,
|
||||
known_hosts_file=known_hosts_file)
|
||||
return cl
|
||||
|
||||
def _destroy_replication_client(self, client):
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
HPE 3PAR driver `Bug #1940069 <https://bugs.launchpad.net/cinder/+bug/1940069>`_:
|
||||
Fixed issue of connection rejected by reusing existing session.
|
||||
|
Loading…
Reference in New Issue
Block a user