def netappSnapshot( ontapClusterMgmtHostname: str, pvName: str, verifySSLCert: bool = True ) -> str : # Install netapp_ontap package import sys, subprocess; subprocess.run([sys.executable, '-m', 'pip', 'install', 'netapp_ontap']) # Import needed functions/classes from netapp_ontap import config as netappConfig from netapp_ontap.host_connection import HostConnection as NetAppHostConnection from netapp_ontap.resources import Volume, Snapshot from datetime import datetime import json # Retrieve ONTAP cluster admin account details from mounted K8s secrets usernameSecret = open('/mnt/secret/username', 'r') ontapClusterAdminUsername = usernameSecret.read().strip() passwordSecret = open('/mnt/secret/password', 'r') ontapClusterAdminPassword = passwordSecret.read().strip() # Configure connection to ONTAP cluster/instance netappConfig.CONNECTION = NetAppHostConnection( host = ontapClusterMgmtHostname, username = ontapClusterAdminUsername, password = ontapClusterAdminPassword, verify = verifySSLCert ) # Convert pv name to ONTAP volume name # The following will not work if you specified a custom storagePrefix when creating your # Trident backend. If you specified a custom storagePrefix, you will need to update this # code to match your prefix. volumeName = 'trident_%s' % pvName.replace("-", "_") print('\npv name: ', pvName) print('ONTAP volume name: ', volumeName) # Create snapshot; print API response volume = Volume.find(name = volumeName) timestamp = datetime.today().strftime("%Y%m%d_%H%M%S") snapshot = Snapshot.from_dict({ 'name': 'kfp_%s' % timestamp, 'comment': 'Snapshot created by a Kubeflow pipeline', 'volume': volume.to_dict() }) response = snapshot.post() print("\nAPI Response:") print(response.http_response.text) # Retrieve snapshot details snapshot.get() # Convert snapshot details to JSON string and print snapshotDetails = snapshot.to_dict() print("\nSnapshot Details:") print(json.dumps(snapshotDetails, indent=2)) # Return name of newly created snapshot return snapshotDetails['name']
def delete_volume(volume_name: str) -> None: """Delete a volume in a SVM""" volume = Volume.find(name=volume_name) try: volume.delete() print("Volume %s deleted successfully" % volume.name) except NetAppRestError as err: print("Error: Volume was not deleted: %s" % err) return
def get_volume(volume_name: str) -> None: """Get the details of a volume""" volume = Volume.find(name=volume_name) #volumemetrics = VolumeMetrics(volume.uuid) volumemetrics = VolumeMetrics.get_collection(volume.uuid, fields="iops.total", interval="1h") print( f"IOPs over the last hour for volume {volume.name} was {volumemetrics.iops.total}" ) return
def make_snap_pycl(vol_name: str, snapshot_name: str, svm_name: str) -> None: """Create a new snapshot with default settings for a given volume""" volume = Volume.find(**{'svm.name': svm_name, 'name': vol_name}) snapshot = Snapshot(volume.uuid, name=snapshot_name) try: snapshot.post() print("Snapshot %s created successfully" % snapshot.name) except NetAppRestError as err: print("Error: Snapshot was not created: %s" % err)
def get_volume(volume_name: str) -> None: """Get the details of a volume""" volume = Volume.find(name=volume_name) try: volume.get() print(volume.name) print("Volume details for %s obtained successfully" % volume.name) except NetAppRestError as err: print("Error: Volume details not obtained: %s" % err) return
async def delete_volume(self, message): """ A skills function to delete a volume. The parser looks for the message argument. Arguments: message {str} -- delete volume {name} on svm {svm} """ name = message.regex.group('name') svm = message.regex.group('svm') volume = Volume.find(name=name, svm=svm) volume.delete() await message.respond('All done! Response: {}'.format(volume))
def resize_volume(volume_name: str, volume_resize: int) -> None: """Resize a volume in a SVM""" volume = Volume.find(name=volume_name) volume.size = volume_resize try: volume.patch() print("Volume %s resized successfully" % volume.name) except NetAppRestError as err: print("Error: Volume was not resized: %s" % err) return
def make_snap(vol_name: str, snapshot_name: str) -> Optional[Snapshot]: """Create a new snapshot with default settings for a given volume""" volume = Volume.find(name=vol_name) snapshot = Snapshot(volume.uuid, name=snapshot_name) try: snapshot.post() print("Snapshot %s created successfullys" % snapshot.name) return snapshot except NetAppRestError as err: print("Error: Snapshot was not created: %s" % err) return None
def move_volume(volume_name: str, move_aggr_name: str) -> None: """Move the volume to a new aggregate""" volume = Volume.find(name=volume_name) volume.movement = VolumeMovement( destination_aggregate={'name': move_aggr_name}) try: volume.patch() print("Volume %s moved successfully" % volume.name) except NetAppRestError as err: print("Error: Volume was not moved: %s" % err) return
def delete_volume(api, apiuser, apipass): config.CONNECTION = HostConnection(api, apiuser, apipass, verify=False) print("=============================================") print() show_volume(api, apiuser, apipass) print() volname = input("Enter the name of the volume that needs to be Deleted:- ") vol = Volume.find(name=volname) try: if (vol.delete(poll=True)): print("Volume has been deleted Successfully.") except NetAppRestError as e: print("HTTP Error Code is " % e.http_err_response.http_response.text) print("Exception caught :" + str(e)) return
async def create_snapshot(self, message): """ A skills function to take a snapshot of a volume. The parser looks for the message argument. Arguments: message {str} -- create a snapshot of {volume} on svm {svm} """ name = message.regex.group('name') svm = message.regex.group('svm') time = datetime.now() time = str(time) volume = Volume.find(name=name, svm={'name': svm}) volume.get() snapshot = Snapshot.from_dict({ 'name': 'snapshot_%s' % time, 'volume': volume.to_dict(), }) snapshot.post() await message.respond('All done! Response: {}'.format(snapshot))
def delete_volume() -> None: """Delete Volume""" print("=============================================") print() show_volume() print() volname = input("Enter the name of the volume that needs to be Deleted:- ") try: vol = Volume.find(name=volname) except NetAppRestError as error: print("Error:- " % error.http_err_response.http_response.text) print("Exception caught :" + str(error)) try: if vol.delete(poll=True): print("Volume has been deleted Successfully.") except NetAppRestError as error: print("Error:- " % error.http_err_response.http_response.text) print("Exception caught :" + str(error))
def patch_volume(api, apiuser, apipass): config.CONNECTION = HostConnection(api, apiuser, apipass, verify=False) print("=============================================") print() show_volume(api, apiuser, apipass) print() vol_name = input( "Enter the name of the volume that needs to be modified:- ") vol = Volume.find(name=vol_name) dataObj = {} print() nambool = input("Would you like to change the volume name (y/n):- ") if nambool == 'y': nam = input("Enter the new name of the Volume: ") vol.name = nam print() sizebool = input("Would you like to change the volume size (y/n) :- ") if sizebool == 'y': vol_size = input("Enter the new size of the Volume: ") vol_size_format = get_size(vol_size) vol.size = vol_size_format print() statebool = input("Would you like to change the volume state (y/n) :- ") if statebool == 'y': vol_state = input( "Enter the new state of the Volume [offline/online]: ") vol.state = vol_state try: if (vol.patch(poll=True)): print("The Volume has been updated/patched Successfully") except NetAppRestError as e: print("HTTP Error Code is " % e.http_err_response.http_response.text) print("Exception caught :" + str(e)) return
def patch_volume() -> None: """Update Volume""" print("=============================================") print() show_volume() print() vol_name = input( "Enter the name of the volume that needs to be modified:- ") try: vol = Volume.find(name=vol_name) except NetAppRestError as error: print("Error:- " % error.http_err_response.http_response.text) print("Exception caught :" + str(error)) print() nambool = input("Would you like to change the volume name (y/n):- ") if nambool == 'y': nam = input("Enter the new name of the Volume: ") vol.name = nam print() sizebool = input("Would you like to change the volume size (y/n) :- ") if sizebool == 'y': vol_size = input("Enter the new size of the Volume: ") vol_size_format = get_size(vol_size) vol.size = vol_size_format print() autosizebool = input( "Would you like to change the autosize options of the volume (y/n):- ") if autosizebool == 'y': print("Enter the following Details") grow_threshold = input("grow_threshold?:- ") maximum = input("maximum?:- ") minimum = input("minimum?:- ") mode = input("mode?:- ") shrink_threshold = input("shrink_threshold?:- ") autosizejson = { "grow_threshold": grow_threshold, "maximum": maximum, "minimum": minimum, "mode": mode, "shrink_threshold": shrink_threshold } vol.autosize = autosizejson print() efficiency = input("Would you like to enable Efficiency (y/n): ") if efficiency == 'y': print("Enter the following Details") compaction = input("compaction?:- ") compression = input("compression?:- ") cross_volume_dedupe = input("cross_volume_dedupe?:- ") dedupe = input("dedupe?:- ") policy_name_e = input("Efficiency Policy Name?:- ") efficiencyjson = { "compaction": compaction, "compression": compression, "cross_volume_dedupe": cross_volume_dedupe, "dedupe": dedupe, "policy": { "name": policy_name_e } } vol.efficiency = efficiencyjson print() encryption = input("Would you like to enable Encryption (y/n): ") if encryption == 'y': print("Enter the following Details") enabled_encry = input("Enable Encryption ?:- ") encryptionjson = {"enabled": bool(enabled_encry), "status": {}} vol.encryption = encryptionjson print() files = input("Would you like to enable Max File Count (y/n): ") if files == 'y': print("Enter the following Details") maximum_files = input("Max File Count?:- ") filesjson = {"maximum": maximum_files} vol.files = filesjson print() nas = input("Would you like to enable NAS parameters (y/n): ") if nas == 'y': print("Enter the following Details") export_policy_name = input("export_policy_name?:- ") path = input("path?:- ") security_style = input("security_style?:- ") unix_permissions = input("unix_permissions?:- ") nasjson = { "export_policy": { "name": export_policy_name }, "path": path, "security_style": security_style, "unix_permissions": unix_permissions } vol.nas = nasjson print() qos = input("Would you like to enable QoS (y/n): ") if qos == 'y': print("Enter the following Details") max_throughput_iops = input("max_throughput_iops?:- ") max_throughput_mbps = input("max_throughput_mbps?:- ") min_throughput_iops = input("min_throughput_iops?:- ") qosname = input("qosname?:- ") qosjson = { "policy": { "max_throughput_iops": max_throughput_iops, "max_throughput_mbps": max_throughput_mbps, "min_throughput_iops": min_throughput_iops, "name": qosname } } vol.qos = qosjson print() quota = input("Would you like to enable Quota (y/n): ") if quota == 'y': print("Enter the following Details") enable_quota = input("enable_quota?:- ") quotajson = {"enabled": bool(enable_quota)} vol.quota = quotajson try: if vol.patch(poll=True): print("The Volume has been updated/patched Successfully") except NetAppRestError as error: print("Error:- " % error.http_err_response.http_response.text) print("Exception caught :" + str(error))
import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) conn = HostConnection('192.168.1.200', username='******', password='******', verify=False) config.CONNECTION = conn name = 'rubrik' size = 20971520 aggr = 'ntap_study_data' svm = 'study' volume = Volume.from_dict({'name': name, 'svm': {'name': svm}, 'nas': {'path': '/'+name} , 'size': size, 'aggregates': [{'name': aggr}]}) volume.post() vol = Volume.find(name=name) vol.get(fields='nas.path') print(vol.nas.path) """ #volume = Volume.find(name=name, svm=svm) #volume.delete() #for svm in Svm.get_collection(): # svm.get() # print(svm.to_dict()) volumes = [] for vol in Volume.get_collection(svm=svm): vol.get(fields='name') volumes.append(vol.name)
from netapp_ontap import config from netapp_ontap import HostConnection from netapp_ontap.resources import Cluster, Aggregate, Port, Volume, Autosupport, IpInterface, Disk, Chassis, Account, Svm, Snapshot from datetime import datetime import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) conn = HostConnection('192.168.1.200', username='******', password='******', verify=False) config.CONNECTION = conn #vol = Volume.find(name='movies') #vol.get() #print(vol) #volume = Volume(name='vol1', svm={'name': 'study'}, aggregates=[{'name': 'ntap_study_data'}]) #volume.post() time = datetime.now() time = str(time) volume = Volume.find(name='soccer', svm={'name': 'study'}) volume.get() snapshot = Snapshot.from_dict({ 'name': 'snapshot_%s' % time, 'volume': volume.to_dict(), }) snapshot.post()
def get_volume(volume_name): return (Volume.find(name=volume_name))