From 2303c8f22c7093890b2a7f1fbf69c0bc74ce78d3 Mon Sep 17 00:00:00 2001 From: Arindam Datta Date: Wed, 24 Mar 2021 17:37:58 +0530 Subject: [PATCH] Release verion 1.1.0 --- PyPowerFlex/base_client.py | 19 +- PyPowerFlex/exceptions.py | 38 +++- PyPowerFlex/objects/sdc.py | 27 +++ PyPowerFlex/objects/snapshot_policy.py | 32 ++-- PyPowerFlex/objects/storage_pool.py | 56 ++++-- PyPowerFlex/objects/system.py | 20 +- PyPowerFlex/objects/volume.py | 248 ++++++++++++++++++++++++- README.md | 2 +- setup.py | 8 +- 9 files changed, 387 insertions(+), 63 deletions(-) diff --git a/PyPowerFlex/base_client.py b/PyPowerFlex/base_client.py index 2b6405d..982d0db 100644 --- a/PyPowerFlex/base_client.py +++ b/PyPowerFlex/base_client.py @@ -153,7 +153,7 @@ def _create_entity(self, params=None): params=params ) if r.status_code != requests.codes.ok: - exc = exceptions.PowerFlexFailCreating(self.entity) + exc = exceptions.PowerFlexFailCreating(self.entity, response) LOG.error(exc.message) raise exc @@ -169,7 +169,8 @@ def _delete_entity(self, entity_id, params=None): entity_id=entity_id, params=params) if r.status_code != requests.codes.ok: - exc = exceptions.PowerFlexFailDeleting(self.entity, entity_id) + exc = exceptions.PowerFlexFailDeleting(self.entity, entity_id, + response) LOG.error(exc.message) raise exc @@ -180,7 +181,8 @@ def _rename_entity(self, action, entity_id, params=None): entity_id=entity_id, params=params) if r.status_code != requests.codes.ok: - exc = exceptions.PowerFlexFailRenaming(self.entity, entity_id) + exc = exceptions.PowerFlexFailRenaming(self.entity, entity_id, + response) LOG.error(exc.message) raise exc @@ -199,7 +201,8 @@ def get(self, entity_id=None, filter_fields=None, fields=None): r, response = self.send_get_request(url, **url_params) if r.status_code != requests.codes.ok: - exc = exceptions.PowerFlexFailQuerying(self.entity, entity_id) + exc = exceptions.PowerFlexFailQuerying(self.entity, entity_id, + response) LOG.error(exc.message) raise exc if filter_fields: @@ -220,9 +223,11 @@ def get_related(self, entity_id, related, filter_fields=None, fields=None): if r.status_code != requests.codes.ok: msg = ( 'Failed to query related {related} entities for PowerFlex ' - '{entity} with id {_id}.'.format(related=related, - entity=self.entity, - _id=entity_id) + '{entity} with id {_id}.' + ' Error: {response}'.format(related=related, + entity=self.entity, + _id=entity_id, + response=response) ) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) diff --git a/PyPowerFlex/exceptions.py b/PyPowerFlex/exceptions.py index 1a29ef6..a7fc0bb 100644 --- a/PyPowerFlex/exceptions.py +++ b/PyPowerFlex/exceptions.py @@ -15,8 +15,9 @@ class PowerFlexClientException(Exception): - def __init__(self, message): + def __init__(self, message, response=None): self.message = message + self.response = response def __str__(self): return self.message @@ -45,25 +46,45 @@ class InvalidInput(PowerFlexClientException): class PowerFlexFailCreating(PowerFlexClientException): base = 'Failed to create PowerFlex {entity}.' - def __init__(self, entity): + def __init__(self, entity, response=None): self.message = self.base.format(entity=entity) + self.response = response + if response: + self.message = '{msg} Error: ' \ + '{response}'.format(msg=self.message, + response=response) class PowerFlexFailDeleting(PowerFlexClientException): base = 'Failed to delete PowerFlex {entity} with id {_id}.' - def __init__(self, entity, entity_id): + def __init__(self, entity, entity_id, response=None): self.message = self.base.format(entity=entity, _id=entity_id) + self.response = response + if response: + self.message = '{msg} Error: ' \ + '{response}'.format(msg=self.message, + response=response) class PowerFlexFailQuerying(PowerFlexClientException): base = 'Failed to query PowerFlex {entity}' - def __init__(self, entity, entity_id=None): + def __init__(self, entity, entity_id=None, response=None): base = self.base.format(entity=entity) - if entity_id: + self.response = response + if entity_id and response is None: self.message = '{base} with id {_id}.'.format(base=base, _id=entity_id) + elif entity is None and response: + self.message = '{base} Error: ' \ + '{response}'.format(base=base, + response=response) + elif entity and response: + self.message = '{base} with id {_id}.' \ + ' Error: {response}'.format(base=base, + _id=entity_id, + response=response) else: self.message = '{base}.'.format(base=base) @@ -71,5 +92,10 @@ def __init__(self, entity, entity_id=None): class PowerFlexFailRenaming(PowerFlexClientException): base = 'Failed to rename PowerFlex {entity} with id {_id}.' - def __init__(self, entity, entity_id): + def __init__(self, entity, entity_id, response=None): self.message = self.base.format(entity=entity, _id=entity_id) + self.response = response + if response: + self.message = '{msg} Error: ' \ + '{response}'.format(msg=self.message, + response=response) diff --git a/PyPowerFlex/objects/sdc.py b/PyPowerFlex/objects/sdc.py index 2645d3d..1095cb6 100644 --- a/PyPowerFlex/objects/sdc.py +++ b/PyPowerFlex/objects/sdc.py @@ -57,3 +57,30 @@ def rename(self, sdc_id, name): ) return self._rename_entity(action, sdc_id, params) + + def set_performance_profile(self, sdc_id, perf_profile): + """Apply a performance profile to the specified SDC. + + :type sdc_id: str + :type perf_profile: str + :rtype: dict + """ + + action = 'setSdcPerformanceParameters' + + params = dict( + perfProfile=perf_profile + ) + + r, response = self.send_post_request(self.base_action_url, action, sdc_id, params) + + if r.status_code != requests.codes.ok: + msg = ('Failed to set Performance Profile on ' + 'PowerFlex {entity} with id {_id} ' + '. Error: {response}'.format(entity=self.entity, + _id=sdc_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=sdc_id) \ No newline at end of file diff --git a/PyPowerFlex/objects/snapshot_policy.py b/PyPowerFlex/objects/snapshot_policy.py index ea6b85e..9d969fe 100644 --- a/PyPowerFlex/objects/snapshot_policy.py +++ b/PyPowerFlex/objects/snapshot_policy.py @@ -53,8 +53,10 @@ def add_source_volume(self, snapshot_policy_id, volume_id): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to add source volume to PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=snapshot_policy_id)) + 'with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=snapshot_policy_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -118,8 +120,10 @@ def modify(self, params=params) if r.status_code != requests.codes.ok: msg = ('Failed to modify PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=snapshot_policy_id)) + 'with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=snapshot_policy_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -139,9 +143,10 @@ def pause(self, snapshot_policy_id): entity=self.entity, entity_id=snapshot_policy_id) if r.status_code != requests.codes.ok: - msg = ('Failed to pause PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=snapshot_policy_id)) + msg = ('Failed to pause PowerFlex {entity} with id {_id}.' + ' Error: {response}'.format(entity=self.entity, + _id=snapshot_policy_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -178,8 +183,10 @@ def remove_source_volume(self, params=params) if r.status_code != requests.codes.ok: msg = ('Failed to remove source volume from PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=snapshot_policy_id)) + 'with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=snapshot_policy_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -215,9 +222,10 @@ def resume(self, snapshot_policy_id): entity=self.entity, entity_id=snapshot_policy_id) if r.status_code != requests.codes.ok: - msg = ('Failed to resume PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=snapshot_policy_id)) + msg = ('Failed to resume PowerFlex {entity} with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=snapshot_policy_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) diff --git a/PyPowerFlex/objects/storage_pool.py b/PyPowerFlex/objects/storage_pool.py index 7690ed6..3e3dd3d 100644 --- a/PyPowerFlex/objects/storage_pool.py +++ b/PyPowerFlex/objects/storage_pool.py @@ -217,8 +217,9 @@ def set_checksum_enabled(self, storage_pool_id, checksum_enabled): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to enable/disable checksum for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format(entity=self.entity, + _id=storage_pool_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -245,8 +246,9 @@ def set_compression_method(self, storage_pool_id, compression_method): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to set compression method for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format(entity=self.entity, + _id=storage_pool_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -289,8 +291,9 @@ def set_external_acceleration_type( params=params) if r.status_code != requests.codes.ok: msg = ('Failed to set external acceleration type for PowerFlex ' - '{entity} with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + '{entity} with id {_id}. Error: {response}'.format(entity=self.entity, + _id=storage_pool_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -323,8 +326,11 @@ def set_media_type(self, params=params) if r.status_code != requests.codes.ok: msg = ('Failed to set media type for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format( + entity=self.entity, + _id=storage_pool_id, + response=response)) + LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -351,8 +357,10 @@ def set_rebalance_enabled(self, storage_pool_id, rebalance_enabled): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to enable/disable rebalance for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format( + entity=self.entity, + _id=storage_pool_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -407,8 +415,11 @@ def set_spare_percentage(self, storage_pool_id, spare_percentage): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to set spare percentage for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format( + entity=self.entity, + _id=storage_pool_id, + response=response)) + LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -432,8 +443,11 @@ def set_use_rfcache(self, storage_pool_id, use_rfcache): entity_id=storage_pool_id) if r.status_code != requests.codes.ok: msg = ('Failed to set Rfcache usage for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format( + entity=self.entity, + _id=storage_pool_id, + response=response)) + LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -460,9 +474,13 @@ def set_use_rmcache(self, storage_pool_id, use_rmcache): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to set Rmcache usage for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format( + entity=self.entity, + _id=storage_pool_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) return self.get(entity_id=storage_pool_id) @@ -488,8 +506,10 @@ def set_zero_padding_policy(self, storage_pool_id, zero_padding_enabled): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to set Zero Padding policy for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=storage_pool_id)) + 'with id {_id}. Error: {response}'.format( + entity=self.entity, + _id=storage_pool_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) diff --git a/PyPowerFlex/objects/system.py b/PyPowerFlex/objects/system.py index 93fbc10..c654ac6 100644 --- a/PyPowerFlex/objects/system.py +++ b/PyPowerFlex/objects/system.py @@ -105,8 +105,10 @@ def remove_cg_snapshots(self, system_id, cg_id, allow_ext_managed=None): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to remove consistency group snapshots from ' - 'PowerFlex {entity} with ' - 'id {_id}.'.format(entity=self.entity, _id=system_id)) + 'PowerFlex {entity} with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=system_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -115,9 +117,13 @@ def remove_cg_snapshots(self, system_id, cg_id, allow_ext_managed=None): def snapshot_volumes(self, system_id, snapshot_defs, + access_mode=None, + retention_period=None, allow_ext_managed=None): """Create snapshots of PowerFlex volumes. + :type retention_period: str + :type access_mode: str :type system_id: str :type snapshot_defs: list[dict] :type allow_ext_managed: bool @@ -128,7 +134,9 @@ def snapshot_volumes(self, params = dict( snapshotDefs=snapshot_defs, - allowOnExtManagedVol=allow_ext_managed + allowOnExtManagedVol=allow_ext_managed, + accessModeLimit=access_mode, + retentionPeriodInMin=retention_period ) r, response = self.send_post_request(self.base_action_url, @@ -138,8 +146,10 @@ def snapshot_volumes(self, params=params) if r.status_code != requests.codes.ok: msg = ('Failed to snapshot volumes on PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, - _id=system_id)) + 'with id {_id}.' + ' Error: {response}'.format(entity=self.entity, + _id=system_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) diff --git a/PyPowerFlex/objects/volume.py b/PyPowerFlex/objects/volume.py index 9a562ec..24131a5 100644 --- a/PyPowerFlex/objects/volume.py +++ b/PyPowerFlex/objects/volume.py @@ -20,7 +20,6 @@ from PyPowerFlex import base_client from PyPowerFlex import exceptions - LOG = logging.getLogger(__name__) @@ -58,7 +57,8 @@ def add_mapped_sdc(self, sdc_id=None, sdc_guid=None, allow_multiple_mappings=None, - allow_ext_managed=None): + allow_ext_managed=None, + access_mode=None): """Map PowerFlex volume to SDC. :param volume_id: str @@ -66,6 +66,7 @@ def add_mapped_sdc(self, :param sdc_guid: str :param allow_multiple_mappings: bool :param allow_ext_managed: bool + :type access_mode: str :return: dict """ @@ -78,7 +79,8 @@ def add_mapped_sdc(self, sdcId=sdc_id, guid=sdc_guid, allowMultipleMappings=allow_multiple_mappings, - allowOnExtManagedVol=allow_ext_managed + allowOnExtManagedVol=allow_ext_managed, + accessMode=access_mode ) r, response = self.send_post_request(self.base_action_url, @@ -88,7 +90,9 @@ def add_mapped_sdc(self, params=params) if r.status_code != requests.codes.ok: msg = ('Failed to map PowerFlex {entity} with id {_id} ' - 'to SDC.'.format(entity=self.entity, _id=volume_id)) + 'to SDC. Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -164,8 +168,10 @@ def extend(self, volume_id, size_in_gb, allow_ext_managed=None): entity_id=volume_id, params=params) if r.status_code != requests.codes.ok: - msg = ('Failed to extend PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, _id=volume_id)) + msg = ('Failed to extend PowerFlex {entity} with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -186,7 +192,10 @@ def lock_auto_snapshot(self, volume_id): entity_id=volume_id) if r.status_code != requests.codes.ok: msg = ('Failed to lock AutoSnapshot for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, _id=volume_id)) + 'with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -233,8 +242,10 @@ def remove_mapped_sdc(self, entity_id=volume_id, params=params) if r.status_code != requests.codes.ok: - msg = ('Failed to unmap PowerFlex {entity} with id {_id} ' - 'from SDC.'.format(entity=self.entity, _id=volume_id)) + msg = ('Failed to unmap PowerFlex {entity} with id {_id} from ' + 'SDC. Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) @@ -279,7 +290,224 @@ def unlock_auto_snapshot(self, volume_id, remove_auto_snapshot=None): params=params) if r.status_code != requests.codes.ok: msg = ('Failed to unlock AutoSnapshot for PowerFlex {entity} ' - 'with id {_id}.'.format(entity=self.entity, _id=volume_id)) + 'with id {_id}. Error: ' + '{response}'.format(entity=self.entity, _id=volume_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=volume_id) + + def set_mapped_sdc_limits(self, volume_id, sdc_id, bandwidth_limit=None, + iops_limit=None): + """Set the bandwidth limit and IOPS limit for the mapped SDC. + + :param volume_id: ID of the volume + :type volume_id: str + :param sdc_id: ID of the SDC + :type sdc_id: str + :param bandwidth_limit: Limit for the volume network bandwidth + :type bandwidth_limit: str + :param iops_limit: Limit for the volume IOPS + :type iops_limit: str + :return: dict + """ + + action = 'setMappedSdcLimits' + + params = dict( + sdcId=sdc_id, + bandwidthLimitInKbps=bandwidth_limit, + iopsLimit=iops_limit + ) + + r, response = self.send_post_request(self.base_action_url, + action=action, + entity=self.entity, + entity_id=volume_id, + params=params) + if r.status_code != requests.codes.ok: + msg = ('Failed to update the SDC limits of PowerFlex' + ' {entity} with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=volume_id) + + def set_compression_method(self, volume_id, compression_method): + """ + Modify the compression method to be used for a Volume, relevant only + if the volume has a space efficient data layout. + + :param volume_id: ID of the volume + :type volume_id: str + :param compression_method: one of predefined attributes of + CompressionMethod + :type compression_method: str + :return: dict + """ + + action = 'modifyCompressionMethod' + + params = dict( + compressionMethod=compression_method, + ) + + r, response = self.send_post_request(self.base_action_url, + action=action, + entity=self.entity, + entity_id=volume_id, + params=params) + if r.status_code != requests.codes.ok: + msg = ('Failed to update the compression method of PowerFlex' + ' {entity} with id' + ' {_id}. Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=volume_id) + + def set_use_rmcache(self, volume_id, use_rmcache): + """ + Control the use of Read RAM Cache in the specified volume. + If you want to ensure that all I/O operations for this volume are + cached, the relevant Storage Pool should be configured to use cache, + and the relevant SDSs should all have caching enabled. + + :param volume_id: ID of the volume + :type volume_id: str + :param use_rmcache: Whether to use Read RAM cache or not + :type use_rm_cache: bool + :return: dict + """ + + action = 'setVolumeUseRmcache' + + params = dict( + useRmcache=use_rmcache + ) + + r, response = self.send_post_request(self.base_action_url, + action=action, + entity=self.entity, + entity_id=volume_id, + params=params) + if r.status_code != requests.codes.ok: + msg = ('Failed to update the use_rmcache of PowerFlex' + ' {entity} with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=volume_id) + + def set_access_mode_for_sdc(self, volume_id, sdc_id, access_mode): + """ + Set the volume access mode for the specified + SDC mapped to the volume. + + :param volume_id: ID of the volume + :type volume_id: str + :param access_mode: The access mode of the volume for the mapped SDC + :type access_mode: str + :param sdc_id: ID of the SDC. + :type sdc_id: str + :return: dict + """ + + action = 'setVolumeMappingAccessMode' + + params = dict( + accessMode=access_mode, + sdcId=sdc_id + ) + + r, response = self.send_post_request(self.base_action_url, + action=action, + entity=self.entity, + entity_id=volume_id, + params=params) + if r.status_code != requests.codes.ok: + msg = ('Failed to set the access mode for the SDC {sdc_id}' + ' mapped to PowerFlex {entity} with id {_id}. Error:' + ' {response}'.format(entity=self.entity, _id=volume_id, + sdc_id=sdc_id, response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=volume_id) + + def set_retention_period(self, snap_id, retention_period): + """ + Set a new retention period for the given snapshot. If the snapshot + is already secure, then it can be delayed but not advanced. + + :param snap_id: ID of the volume + :type snap_id: str + :param retention_period: Retention period for the specified resource + :type retention_period: str + :return: dict + """ + + action = 'setSnapshotSecurity' + + params = dict( + retentionPeriodInMin=retention_period, + ) + + r, response = self.send_post_request(self.base_action_url, + action=action, + entity=self.entity, + entity_id=snap_id, + params=params) + if r.status_code != requests.codes.ok: + msg = ('Failed to set the retention period for PowerFlex' + ' {entity} with id {_id}.' + ' Error: {response}'.format(entity=self.entity, + _id=snap_id, + response=response)) + LOG.error(msg) + raise exceptions.PowerFlexClientException(msg) + + return self.get(entity_id=snap_id) + + + def set_volume_access_mode_limit(self, volume_id, access_mode_limit): + """ + Set the highest mapping access mode allowed for a volume. + + :param volume_id: ID of the volume + :type volume_id: str + :param access_mode_limit: Define the access mode limit of a volume, + options are ReadWrite or ReadOnly + :type access_mode_limit: str + :return: dict + """ + + action = 'setVolumeAccessModeLimit' + + params = dict( + accessModeLimit=access_mode_limit + ) + + r, response = self.send_post_request(self.base_action_url, + action=action, + entity=self.entity, + entity_id=volume_id, + params=params) + if r.status_code != requests.codes.ok: + msg = ('Failed to update the Volume Access Mode Limit of PowerFlex' + ' {entity} with id {_id}. ' + 'Error: {response}'.format(entity=self.entity, + _id=volume_id, + response=response)) LOG.error(msg) raise exceptions.PowerFlexClientException(msg) diff --git a/README.md b/README.md index 33d0e58..106e02c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ python setup.py install | password | (str) PowerFlex API password. | | verify_certificate | (bool) Verify server's certificate. **Default**: False. | | certificate_path | (str) Path to server's certificate. **Default**: None. | -| timeout | (int) Timeout for PowerFlex API request. **Default**: 120. +| timeout | (int) Timeout for PowerFlex API request **Default**: 120. | log_level | (int) Logging level (e. g. logging.DEBUG). **Default**: logging.ERROR. | #### Available resources diff --git a/setup.py b/setup.py index 396cdad..caeda27 100644 --- a/setup.py +++ b/setup.py @@ -17,13 +17,13 @@ setup( name='PyPowerFlex', - version='1.0.0', + version='1.1.0', description='Python library for Dell EMC PowerFlex', - author='Ivan Pchelintsev', - author_email='Ivan.Pchelintsev@dell.com', + author='Ansible Team at Dell EMC', + author_email='ansible.team@dell.com', install_requires=[ 'packaging==20.4', - 'requests==2.23.0', + 'requests>=2.23.0', ], packages=[ 'PyPowerFlex',