import sys,argparse,json,time sys.path.insert(0, './classes/') import cohesityAPI as cohesity # Global variables that will be used across all functions global tagid tagid = None global tagName tagName = None # Begin Functions def GetArgs(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--cluster', '-c', type=str, action='store') parser.add_argument('--vcenter', '-v', type=str, action='store') parser.add_argument('--tag', '-t', type=str, action='store') parser.add_argument('--group', '-g', type=str, action='store') parser.add_argument('--action', '-a', type=str, action='store') parser.add_argument('--list', '-l', type=str, action='store') return (parser.parse_args()) def GetTagID(sources): globalList = globals() for source in sources: if globalList['tagid'] is None: GetNode(sources) def GetNode(record): globalList = globals() # A non 'node' element was found, check each child key to see if one contains 'kTag' if "protectionSource" in record: if "vmWareProtectionSource" in record['protectionSource']: if record['protectionSource']['vmWareProtectionSource']['type'] == "kTag": # Tag elements have been found, look for the correct tag and assign the id to the global variable if record['protectionSource']['vmWareProtectionSource']['name'] == globalList['tagName']: # Tag was found based on the name globalList['tagid'] = record['protectionSource']['id'] # Recurse through all 'nodes' elements looking for kTag if "nodes" in record: for node in record['nodes']: # The tag hasn't been found, search the next record if globalList['tagid'] is None: GetNode(node) # The tag was found and the global id value was set, stop iterating. else: break def UpdateProtectionGroupExcludes(group, action): globalList = globals() isExcluded = False tagArray = [] if "excludeVmTagIds" in group: for index in group['excludeVmTagIds']: for tag in index: tagArray.append(tag) if tag == globalList['tagid']: isExcluded = True # Add the tag to the exclusion if action == 'add': if isExcluded == True: print(globalList['tagName'] + " tag is already excluded for " + group['name']) else: print("Adding exclusion tag '" + globalList['tagName'] + "' to group " + group['name']) tagArray.append(globalList['tagid']) # Remove the tag from the exclusion elif action == 'remove': if isExcluded == True: print("Removing exclusion tag '" + globalList['tagName'] + "' from group " + group['name']) tagArray.remove(globalList['tagid']) else: print(globalList['tagName'] + " tag is not excluded for " + group['name']) return(tagArray) def UpdateProtectionGroupIncludes(group, action): globalList = globals() isIncluded = False tagArray = [] if "vmTagIds" in group: for index in group['vmTagIds']: for tag in index: tagArray.append(tag) if tag == globalList['tagid']: isIncluded = True # Add the tag to the inclusion if action == 'add': if isIncluded == True: print(globalList['tagName'] + " tag is already included for " + group['name']) else: print("Adding inclusion tag '" + globalList['tagName'] + "' to group " + group['name']) tagArray.append(globalList['tagid']) # Remove the tag from the inclusion elif action == 'remove': if isIncluded == True: print("Removing inclusion tag '" + globalList['tagName'] + "' from group " + group['name']) tagArray.remove(globalList['tagid']) else: print(globalList['tagName'] + " tag is not included for " + group['name']) return(tagArray) # Begin Main globalList = globals() sourceFound = False vCenter = None vCenterID = None tagIds = [] args = GetArgs() # Validate arguments & assign variables if necessary if not args.cluster: sys.exit("Error: Specify a Cohesity cluster fqdn with -c parameter.") else: globalList['tagName'] = args.tag if not args.vcenter: sys.exit("Error: Specify a vCenter with -v parameter") if not args.tag: sys.exit("Error: Specify a tag with the -t parameter.") if not args.action: sys.exit("Error: Specify an action [add|remove] with -a parameter.") elif args.action != 'add' and args.action != 'remove': sys.exit("Error: Use only 'add' or 'remove' with -a parameter.") if not args.list: sys.exit("Error: Specify a list [include|exclude] with -l parameter.") elif args.list != 'exclude' and args.list != 'include': sys.exit("Error: Use only 'include' or 'exclude' with -l parameter.") # Connect to the Cohesity cluster cluster = cohesity.API(args.cluster) authToken = cluster.GetAuthToken() cluster.UpdateHeaders(authToken['accessToken']) # Locate the correct vCenter and capture the id, this will be useful to validate child objects vmSources = cluster.GetFilteredRequest("/public/protectionSources", "?environments=kVMware") for source in vmSources: if source['protectionSource']['name'] == args.vcenter: sourceFound = True vCenter = source vCenterID = source['protectionSource']['id'] break # The vCenter we are looking for was not in the list of kVMware environments, stop processing. if sourceFound == False: sys.exit("Error: " + args.vcenter + " is not registered to " + args.cluster) # Look up the tag id based on the tagName and set a global variable when found # IMPROVEMENT TO GET AWAY FROM GLOBAL VAR GetTagID(vCenter) if globalList['tagid'] is None: sys.exit("Error: The tag '" + args.tag + "' does not exist in " + vCenter['protectionSource']['name']) if args.group: # Replace '@' symbol with '%40' for URL encoding in the REST API protectionGroup = args.group.replace("@","%40") job = cluster.GetFilteredRequest("/public/protectionJobs", "?names=" + protectionGroup) print(json.dumps(job[0], indent=4)) if job[0]['parentSourceId'] != vCenterID: sys.exit(job[0]['name'] + " does not belong to source " + vCenter['protectionSource']['name']) else: if (args.list == 'exclude'): excludeTagIds = UpdateProtectionGroupExcludes(job[0], args.action) if "excludeVmTagIds" in job[0]: job[0]['excludeVmTagIds'][0] = excludeTagIds else: job[0].update({"excludeVmTagIds": [ excludeTagIds ]}) else: includeTagIds = UpdateProtectionGroupIncludes(job[0], args.action) if "vmTagIds" in job[0]: job[0]['vmTagIds'][0] = includeTagIds else: job[0].update({"includeVmTagIds": [ includeTagIds ]}) # FIX the screw up # Temp code to grab start time from previous runs run = cluster.GetFilteredRequest("/public/protectionRuns","?numRuns=10&jobId=" + str(job[0]['id'])) try: hour = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) hour = time.strftime("%H", time.localtime(hour)) minute = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) minute = time.strftime("%M", time.localtime(minute)) hour = int(hour) minute = int(minute) except: hour = 21 minute = 00 job[0]['startTime']['hour'] = hour job[0]['startTime']['minute'] = minute # EndTime # Temp code to build indexing job[0].update({"indexingPolicy":{ "disableIndexing": False, "allowPrefixes": [ "/" ], "denyPrefixes": [ "/$Recycle.Bin", "/Windows", "/ProgramData", "/System Volume Information", "/Users/*/AppData", "/Recovery", "/usr", "/sys", "/proc", "/lib", "/grub", "/grub2", "/opt/splunk", "/splunk", ] }}) # Temp code to set SLA job[0].update({"incrementalProtectionSlaTimeMins": 480}) job[0].update({"fullProtectionSlaTimeMins": 480}) job[0].update({"abortInBlackoutPeriod": False}) job[0].update({"quiesce": False}) job[0].update({"qosType": "kBackupHDD"}) job[0].update({"environmentParameters":{ "vmwareParameters": { "fallbackToCrashConsistent": False, "skipPhysicalRdmDisks": False } }}) job[0].update({"cloudParameters":{"failoverToCloud": False}}) job[0].update({"leverageStorageSnapshots": False}) job[0].update({"leverageStorageSnapshotsForHyperFlex": False}) job[0].update({"description": ""}) # End Fix # Take acion on group(s) resp = cluster.UpdateVMProtectionJob(job[0]) print(resp.content) else: vmJobs = cluster.GetFilteredRequest("/public/protectionJobs", "?environments=kVMware") uniqueJobs = {job['id'] : job for job in vmJobs}.values() for job in uniqueJobs: if "isPaused" in job: if job['isPaused']: continue # If the job is marked for deletion, skip if 'isDeleted' in job: continue # If the job does not belong to this vCetner, skip if job['parentSourceId'] != vCenterID: continue else: if (args.list == 'exclude'): excludeTagIds = UpdateProtectionGroupExcludes(job, args.action) if "excludeVmTagIds" in job: job['excludeVmTagIds'][0] = excludeTagIds else: job.update({"excludeVmTagIds": [ excludeTagIds ]}) else: includeTagIds = UpdateProtectionGroupIncludes(job, args.action) if "vmTagIds" in job: job['vmTagIds'][0] = includeTagIds else: job.update({"includeVmTagIds": [ includeTagIds ]}) # FIX the screw up # Temp code to grab start time from previous runs run = cluster.GetFilteredRequest("/public/protectionRuns","?numRuns=10&jobId=" + str(job['id'])) try: hour = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) hour = time.strftime("%H", time.localtime(hour)) minute = round(run[7]['backupRun']['stats']['startTimeUsecs']/1000000,0) minute = time.strftime("%M", time.localtime(minute)) hour = int(hour) minute = int(minute) except: hour = 21 minute = 00 job['startTime']['hour'] = hour job['startTime']['minute'] = minute # EndTime # Temp code to build indexing job.update({"indexingPolicy":{ "disableIndexing": False, "allowPrefixes": [ "/" ], "denyPrefixes": [ "/$Recycle.Bin", "/Windows", "/ProgramData", "/System Volume Information", "/Users/*/AppData", "/Recovery", "/usr", "/sys", "/proc", "/lib", "/grub", "/grub2", "/opt/splunk", "/splunk", ] }}) # Temp code to set SLA job.update({"incrementalProtectionSlaTimeMins": 480}) job.update({"fullProtectionSlaTimeMins": 480}) job.update({"abortInBlackoutPeriod": False}) job.update({"quiesce": False}) job.update({"qosType": "kBackupHDD"}) job.update({"environmentParameters":{ "vmwareParameters": { "fallbackToCrashConsistent": False, "skipPhysicalRdmDisks": False } }}) job.update({"cloudParameters":{"failoverToCloud": False}}) job.update({"leverageStorageSnapshots": False}) job.update({"leverageStorageSnapshotsForHyperFlex": False}) job.update({"description": ""}) # Take acion on group(s) print("Updating: " + job['name']) resp = cluster.UpdateVMProtectionJob(job) print(resp.content)