#!/usr/bin/python """ Allows for the registration of a SQL Server VM to Cohesity """ import sys import argparse import json import time sys.path.insert(0, './classes/') import cohesityAPI as cohesity import itdSnow as snow import automationsAPI as dashboard def GetArgs(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--server', '-s', type=str, action='store') parser.add_argument('--cluster', '-c', type=str, action='store') parser.add_argument('--protectGroup', '-p', type=str, action='store') parser.add_argument('--help', '-h', action='store_true') parser.add_argument('--debug', '-d', action='store_true') parser.add_argument('--lookupGroup', '-l', action='store_true') parser.add_argument('--audit', '-a', action='store_true') return (parser.parse_args()) def PrintHelp(): print("\nBasic Usage:") print("\npython3 sqlServerRegistration.py -s hostname.nd.gov -p MyApp@SQL") print("\t -a: Audit SQL objects and re-apply permissions") print("\t -c: The FQDN of the cluster to register the client to") print("\t -d: Run the registration in debug mode") print("\t -l: Lookup appName in Sharepoint and propose Protection Group name") print("\t -s: Fully qualified domain name of the Virtualized SQL Server") print("\t -p: Protection Group the server will be in") print("\t -h Prints this help message") args = GetArgs() protectionGroup = '' sqlHost='' # Establish a connection to ServiceNow if args.debug: ticketSystem = snow.SnowAPI("northdakotadev.service-now.com") else: ticketSystem = snow.SnowAPI("northdakota.service-now.com") if args.help: PrintHelp() exit(1) if not ((args.server and (args.lookupGroup or args.protectGroup)) or (args.audit)): PrintHelp() exit(1) # Get the AppName from the VM List in SharePoint if args.server and args.lookupGroup: sqlHost = args.server cmdb_record = ticketSystem.getCMDBItemByFQDN(sqlHost) print(json.dumps(cmdb_record,indent=4)) appName = cmdb_record[0]['u_nd_application_svc']['name'] # shpt = sharePoint.API() # vmRecord = shpt.get_Node(sqlHost) # appName = shpt.get_AppName(vmRecord[0]['AppNameId']) appName = appName + "@SQL" print("\nSuggested protection group name is: " + appName) menuControl = 0 while menuControl == 0: contRegistration = input("Would you like to continue? [y/n]") if contRegistration == 'y' or contRegistration == 'Y': menuControl = 1 print("\nProceeding with registration.") protectionGroup = appName elif contRegistration == 'n' or contRegistration == 'N': menuControl = 1 print("\nAuto lookup registration has been cancelled.") print("\nPlease relaunch application with -s & -p parameters to specify a custom protection group.") exit(1) else: contRegistration = input("Would you like to continue? [y/n]") # Proceed with registration using either the SharePoint lookup value or the user specified value if (((args.server or sqlHost) and (args.protectGroup or protectionGroup)) or args.audit): try: mdn = cohesity.API(args.cluster) mdnToken = mdn.GetAuthToken() mdn.UpdateHeaders(mdnToken['accessToken']) if (not sqlHost) and (not protectionGroup): sqlHost = args.server protectionGroup = args.protectGroup isSQLRegistered = bool() isPhysicalRegistered = bool() # Get the VMs and SQL objects in Cohesity #vms = mdn.GetRequest("/public/protectionSources/virtualMachines") registeredSQL = mdn.GetFilteredRequest("/public/protectionSources/applicationServers", "?application=kSQL") physicalServers = mdn.GetFilteredRequest("/public/protectionSources/registrationInfo", "?environments=kPhysical") for nodes in physicalServers['rootNodes']: if nodes['rootNode']['name'] == sqlHost: print(sqlHost + " is already registerd as a physical server.") isPhysicalRegistered = bool("true") physicalSourceId = nodes['rootNode']['id'] break # Check to see if the source is already registered as a SQL Server for sqlServer in registeredSQL: if sqlServer['applicationServer']['protectionSource']['name'] == sqlHost: isSQLRegistered = bool("true") print(sqlHost + " is already registerd as a SQL server.") break if (sqlHost): if not isPhysicalRegistered: attempt = mdn.RegisterPhysical(sqlHost) print("Registering " + sqlHost + " as a Physical Server ") time.sleep(20) try: physicalSourceId = attempt['id'] except: print("\nCould not reach " + sqlHost + " on port 50051. Please verify the agent is running and that all firewall rules are accounted for.") exit(1) if not isSQLRegistered: print("Registering " + sqlHost + " as a SQL Server ") attempt = mdn.RegisterSQL(physicalSourceId) time.sleep(20) # Verify DBAs have permissions to all SQL objects, including newly registered objects registeredSQL = mdn.GetFilteredRequest("/public/protectionSources/applicationServers", "?application=kSQL") # Filter out unique objects uniqueSQLSources = {sql['applicationServer']['protectionSource']['id'] : sql for sql in registeredSQL}.values() # Array to hold protection source IDs sqlProtectionSourceIds = [] for sqlServer in uniqueSQLSources: sqlProtectionSourceIds.append(sqlServer['applicationServer']['protectionSource']['id']) # Send protection source IDs for DBA group dbaGroup = mdn.GetFilteredRequest("/public/groups", "?name=ITD-COHESITY-DBA") dbaSid = dbaGroup[0]['sid'] print("Sending Request to Cohesity to update DBA permissions") attempt = mdn.UpdatePermissions(sqlProtectionSourceIds, dbaSid) # Get the list of protection groups & add the new one if necessary if (sqlHost): sqlProtectionJobs = mdn.GetFilteredRequest("/public/protectionJobs", "?environments=kSQL") uniqueJobs = {job['id'] : job for job in sqlProtectionJobs}.values() jobExists = bool() isProtected = bool() isPaused=bool() jobSources = [] for job in uniqueJobs: # Source ID cannot be in more then on protection group for SQL if ('sourceIds' in job) and (physicalSourceId in job['sourceIds'] and ("DELETED" not in job['name']) ): print(sqlHost + " is already in " + job['name'] + " and cannot be in multiple groups.") isProtected = bool("true") jobExists = bool("true") break # The source ID was not found in any other SQL job, but a job name already exsits, so lets collect all sources in the job. elif (job['name'] == protectionGroup) and ( physicalSourceId not in job['sourceIds']): jobExists = bool("true") break if jobExists == bool('true') and isProtected != bool('true'): isPaused=bool('true') job["sourceIds"].append(physicalSourceId) resp = mdn.UpdateProtectionJob(job) print(resp.content) if jobExists == False: print("Creating protection job for " + protectionGroup + " and adding " + sqlHost) ################ TO DO ############### # Defaults from JSON dump of jobs objects if args.cluster == 'itdazdpc02.nd.gov': resp = mdn.CreateAZSQLProtectionJob(physicalSourceId, protectionGroup) else: resp = mdn.CreateSQLProtectionJob(physicalSourceId, protectionGroup) print(resp.content) except OSError as cohesityError: print('Cohesity Error: ' + cohesityError) dashboard.send_automation({'AutomationName': 'Infra-Cohesity', 'Action': 'Provisioning', 'Platform': 'Python-sqlServerRegistration.py', 'Units': 30})