Using the SDK¶
Refer to the API reference for indivual resource manipulations. This introduction illustrate how to use the SDK and the more advanced features. HPE Nimble Storage specific workflows can be found in the example workflows section.
Using python interactively¶
From scratch on a python
prompt.
$ python
Python 3.7.7 (default, Mar 10 2020, 15:43:03)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from nimbleclient import NimOSClient
>>> import pprint
>>> api = NimOSClient('192.168.1.128', 'admin', 'admin')
>>>
Note
All the examples below uses pprint
for formatting purposes only.
Manipulating resources¶
Simple interactions with the volumes
endpoint. Refer to the volumes API reference for more details.
Create a volume¶
>>> api.volumes.create('myvol1', size=1024, description='My first volume')
<Volume(id=0649686580b78e0b16000000000000000000000004, name=myvol1)>
Create a volume with custom metadata¶
>>> meta_data = {'mykey1': 'myval1', 'mykey2': 'myval2'}
>>> api.volumes.create('myvol2', size=2048, description='My second volume', metadata=meta_data)
<Volume(id=0649686580b78e0b16000000000000000000000005, name=myvol2)>
List volumes¶
>>> pprint.pprint(api.volumes.list())
[<Volume(id=0649686580b78e0b16000000000000000000000004, name=myvol1)>,
<Volume(id=0649686580b78e0b16000000000000000000000005, name=myvol2)>]
Fetch volume attributes¶
>>> pprint.pprint(api.volumes.get('0649686580b78e0b16000000000000000000000005').attrs)
{'access_control_records': None,
'agent_type': 'none',
'app_category': 'Other',
'app_uuid': '',
'avg_stats_last_5mins': {'combined_iops': 0,
'combined_latency': 0,
'combined_throughput': 0,
'read_iops': 0,
'read_latency': 0,
'read_throughput': 0,
'write_iops': 0,
'write_latency': 0,
'write_throughput': 0},
'base_snap_id': '',
'base_snap_name': '',
'block_size': 4096,
'cache_needed_for_pin': 2147483648,
'cache_pinned': False,
'cache_policy': 'normal',
'caching_enabled': True,
'cksum_last_verified': 0,
'clone': False,
'content_repl_errors_found': False,
'creation_time': 1573161873,
'dedupe_enabled': False,
'description': 'My second volume',
'dest_pool_id': '',
'dest_pool_name': '',
'encryption_cipher': 'none',
'fc_sessions': None,
'folder_id': '',
'folder_name': '',
'full_name': 'default:/myvol2',
'id': '0649686580b78e0b16000000000000000000000005',
'iscsi_sessions': None,
'iscsi_target_scope': 'group',
'last_content_snap_br_cg_uid': 0,
'last_content_snap_br_gid': 0,
'last_content_snap_id': 0,
'last_modified': 1573161873,
'last_replicated_snap': None,
'last_snap': None,
'limit': 100,
'limit_iops': -1,
'limit_mbps': -1,
'metadata': [{'key': 'mykey2', 'value': 'myval2'},
{'key': 'mykey1', 'value': 'myval1'}],
'move_aborting': False,
'move_bytes_migrated': 0,
'move_bytes_remaining': 0,
'move_est_compl_time': 0,
'move_start_time': 0,
'multi_initiator': False,
'name': 'myvol2',
'needs_content_repl': False,
'num_connections': 0,
'num_fc_connections': 0,
'num_iscsi_connections': 0,
'num_snaps': 0,
'offline_reason': None,
'online': True,
'online_snaps': None,
'owned_by_group': 'nva-test-grp',
'owned_by_group_id': '0049686580b78e0b16000000000000000000000001',
'parent_vol_id': '',
'parent_vol_name': '',
'perfpolicy_id': '0349686580b78e0b16000000000000000000000001',
'perfpolicy_name': 'default',
'pinned_cache_size': 0,
'pool_id': '0a49686580b78e0b16000000000000000000000001',
'pool_name': 'default',
'previously_deduped': False,
'projected_num_snaps': 0,
'protection_type': 'unprotected',
'read_only': False,
'replication_role': 'no_replication',
'reserve': 0,
'search_name': 'myvol2',
'serial_number': '2ee4231f34e21d4b6c9ce900966ee6fe',
'size': 2048,
'snap_limit': 9223372036854775807,
'snap_limit_percent': -1,
'snap_reserve': 0,
'snap_usage_compressed_bytes': 0,
'snap_usage_populated_bytes': 0,
'snap_usage_uncompressed_bytes': 0,
'snap_warn_level': 0,
'space_usage_level': 'normal',
'srep_last_sync': 0,
'srep_resync_percent': 0,
'target_name': 'iqn.2007-11.com.nimblestorage:nva-test-grp-g49686580b78e0b16',
'thinly_provisioned': True,
'total_usage_bytes': 0,
'upstream_cache_pinned': False,
'usage_valid': True,
'vol_state': 'online',
'vol_usage_compressed_bytes': 0,
'vol_usage_mapped_bytes': 0,
'vol_usage_uncompressed_bytes': 0,
'volcoll_id': '',
'volcoll_name': '',
'vpd_ieee0': '2ee4231f34e21d4b',
'vpd_ieee1': '6c9ce900966ee6fe',
'vpd_t10': 'Nimble 2ee4231f34e21d4b6c9ce900966ee6fe',
'warn_level': 0}
Assign a volume to an object¶
>>> vol = api.volumes.get(name='myvol1')
<Volume(id=0601a32bf8f45646a500000000000000000000070d, name=vol-3)>
Access object attributes¶
>>> vol = api.volumes.get(name='myvol2')
>>> pprint.pprint(vol.attrs['metadata'])
[{'key': 'mykey2', 'value': 'myval2'}, {'key': 'mykey1', 'value': 'myval1'}]
Update volume attributes¶
>>> vol.update(id=vol.attrs['id'], description='My new cool description')
>>> vol.reload()
>>> pprint.pprint(vol.attrs['description'])
'My new cool description'
Access object methods¶
>>> vol.offline()
{ 'offline_reason': 'user', 'online': False } # Full object representation omitted
>>> vol.delete()
{}
Pagination¶
The list
operation of an API resource comes with limit
and from_id
attributes that provide means to paginate objects and perform operations in batches. The below example uses the volumes
resource to paginate volume objects.
>>> pprint.pprint(api.volumes.list(limit=3))
[<Volume(id=0649686580b78e0b16000000000000000000000004, name=myvol1)>,
<Volume(id=0649686580b78e0b16000000000000000000000005, name=myvol2)>,
<Volume(id=0649686580b78e0b16000000000000000000000006, name=myvol3)>]
>>>
>>> pprint.pprint(api.volumes.list(limit=3, from_id='0649686580b78e0b16000000000000000000000006'))
[<Volume(id=0649686580b78e0b16000000000000000000000007, name=myvol4)>,
<Volume(id=0649686580b78e0b16000000000000000000000008, name=myvol5)>,
<Volume(id=0649686580b78e0b16000000000000000000000009, name=myvol6)>]
>>>
>>> pprint.pprint(api.volumes.list(limit=3, from_id='0649686580b78e0b16000000000000000000000009'))
[<Volume(id=0649686580b78e0b1600000000000000000000000a, name=myvol7)>]
>>>
Field filters¶
Most of the time a developer have a vague idea of what he's looking for and what attributes are of interest. Using field filters one way to satisfy the need and optimize the payload.
List only resources with a certain name¶
>>> pprint.pprint(api.volumes.list(name='myvol1'))
[<Volume(id=0649686580b78e0b16000000000000000000000004, name=myvol1)>]
Expand object with limited resource attributes¶
>>> pprint.pprint(api.volumes.list(name='myvol1', detail=True, fields='name,id,size,online,clone')[0].attrs)
{'clone': False,
'id': '0649686580b78e0b16000000000000000000000004',
'name': 'myvol1',
'online': True,
'size': 1024}
Using Fields¶
Each API resource comes with "Fields" class which allow complex querying of the resource. The class naming convention is the resource name in singular without underscores in camelcase. Example:
volumes
->VolumeFields
volume_collections
-VolumeCollectionFields
protection_templates
-ProtectionTemplateFields
Note
The volume named "myvol2" in previous steps that was deleted has to be recreated for the next set of examples to make sense.
Search for a volume wildcard¶
>>> from nimbleclient import *
>>> from nimbleclient.v1 import VolumeFields
>>> pprint.pprint(api.volumes.list(filter=and_(VolumeFields.name.contains('vol'))))
[<Volume(id=0649686580b78e0b16000000000000000000000004, name=myvol1)>,
<Volume(id=0649686580b78e0b16000000000000000000000006, name=myvol2)>]
Combining multiple Fields¶
>>> myfilter = and_(
... VolumeFields.name.contains('vol'),
... VolumeFields.metadata('mykey1') == 'myval1'
... )
>>> pprint.pprint(api.volumes.list(detail=True, filter=myfilter, fields='id,name,size,metadata'))
[<Volume(id=0649686580b78e0b16000000000000000000000006, name=myvol2)>]
>>> pprint.pprint(api.volumes.list(detail=True, filter=myfilter, fields='name,size,metadata'
... )[0].attrs)
{'metadata': [{'key': 'mykey2', 'value': 'myval2'},
{'key': 'mykey1', 'value': 'myval1'}],
'name': 'myvol2',
'size': 2048}
Complex Fields with AND and OR operators¶
>>> myfilter = and_(
... VolumeFields.name.contains('vol'),
... VolumeFields.online == 'true',
... or_(
... VolumeFields.protection_type == 'unprotected',
... and_(
... VolumeFields.size <= '4096',
... VolumeFields.encryption_cipher == None,
... )
... )
... )
>>> pprint.pprint(api.volumes.list(detail=True, filter=myfilter, fields='id,name,size,metadata'))
[<Volume(id=0649686580b78e0b16000000000000000000000004, name=myvol1)>,
<Volume(id=0649686580b78e0b16000000000000000000000006, name=myvol2)>]