#!/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})
