197 lines
8.2 KiB
Python
197 lines
8.2 KiB
Python
#!/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})
|