Friday, January 18, 2013

Monitor Hosts and Generate Command Line to Update DNS A Recorders

Scenario:

We have tow exchange 2010 servers with HAG. When one is offline, the another one will take all the server roles automatically.
But we do not have network load balancer.
We setup mail.xxxxx.com always point to xxmail01 IP address 192.168.x.25 in our LAN. We also setup mail.xxxxx.com alwasy point to xxmail01 NAT public IP address 208.1.x.25.
If xxmail01 offline, we have to change DNS mail.xxxxx.com record point to xxmail01 IP address ( LAN IP 192.168.x.35, WAN IP 208.1.x.35) manually.

The LAN DNS server is intDNS01, WAN DNS server is extDNS01.
Setup Schedule Task on Both DNS servers to run the command line to update DNS A records, if exchange server is offline. After run the cmd scritps successfully, delete them each time.
The DNS update command file store on share folder  \\intDNS01\taskscript\updateintdns.bat
\\extDNS01\taskscript\updateextdns.bat.


Prepare

List the monitor Hosts in file name testRecordList.txt like the following format.

#please the test informantion

#If have internal and external DNS Servers, one record point to one internal and one external IP, please use the following format.
#Int_dns_servername,Ext_dns_servername;full_test_DNS_name;First_Int_IP_Address,Frist_Ext_IP_Address;Second_Int_IP_Address,Second_Ext_IP_Address
intDNS01,extDNS01;mail.xxxxx.com;192.168.x.25,208.1.x.25;192.168.x.35,208.1.x.35

#If one has internal DNS Servers, please use the following format.
#Int_dns_servername;full_test_DNS_name;First_Int_IP_Address;Second_Int_IP_Address


Python Script

File Name:  gendnsupdatecmd.py

'''
Created on Jan 10, 2013

@author: chu
'''
import os, time


#Run nslookup to check if the A Record is list on the DNS server or not.
def getARecordIp(aName):
    os.popen("ipconfig /flushdns")
    nslookupcmd = "nslookup " + aName
    nslookupReturn = os.popen(nslookupcmd).readlines()
    if len(nslookupReturn) < 4:
        return "Failed"
    elif aName in nslookupReturn[3]:
        return nslookupReturn[4].split(' ')[2:]
    else:
        return "Failed"    
        

#Run Ping to check the A Record Host is alive or not. 
def pingTest(ip):
    pingcmd = "ping -n 1 -i 5 " + ip
    testResult = os.popen(pingcmd).readlines()
    if len(testResult) < 2:
        result = False
        return result
    if 'Request timed out.' in testResult[3]:
        result = False
        return result
    else:
        result = True
        return result
   

#Generate delete A Record command line.
def delRecord(record,intip):
    intdelRecordcmd = ''
    extdelRecordcmd = ''
    for i in range(2,len(record)):
        if intip in record[i].split(',')[0]:            
            hostname = record[1].split('.')[0]
            domainName = record[1].split('.')[1] + '.' + record[1].split('.')[2].strip(' ')
            intDnsServer = record[0].split(',')[0]            
            intdelRecordcmd = 'dnscmd ' + intDnsServer +' /RecordDelete ' + domainName + ' ' + hostname + ' 900 A ' + intip +' /f'
            if len(record[0].split(',')) == 2:
                extip = record[i].split(',')[1]
                extDnsServer = record[0].split(',')[1]
                extdelRecordcmd = 'dnscmd ' + extDnsServer +' /RecordDelete ' + domainName + ' ' + hostname + ' 900 A ' + extip +' /f'
    delRecordcmd = [intdelRecordcmd, extdelRecordcmd]
    return delRecordcmd
    

#Generate Add A Record command line.    
def addRecord(record):
    intaddRecordcmd = ''
    extaddRecordcmd = ''
    #ping Hostname
    pingResult = pingTest(record[1])
    if pingResult:
        addRecordcmd = [intaddRecordcmd, extaddRecordcmd]
        return addRecordcmd
    time.sleep(10)
    if pingResult:
        addRecordcmd = [intaddRecordcmd, extaddRecordcmd]
        return addRecordcmd
    for i in range(2,len(record)):
        #Ping IP address
        pingResult = pingTest(record[i].split(',')[0])
        if pingResult:
            hostname = record[1].split('.')[0]
            domainName = record[1].split('.')[1] + '.' + record[1].split('.')[2].strip(' ')
            intIp = record[i].split(',')[0]            
            intDnsServer = record[0].split(',')[0]            
            intaddRecordcmd = 'dnscmd ' + intDnsServer + ' /RecordAdd ' + domainName + ' ' + hostname + ' 900 A ' + intIp
            if len(record[0].split(',')) == 2:                
                extIp =  record[i].split(',')[1]
                extDnsServer = record[0].split(',')[1]
                extaddRecordcmd = 'dnscmd ' + extDnsServer + ' /RecordAdd ' + domainName + ' ' + hostname + ' 900 A ' + extIp
            addRecordcmd = [intaddRecordcmd, extaddRecordcmd]
            return addRecordcmd
      

def main():
    intcmdLines = []
    extcmdLines = []
    try:
        recordFile = open('testRecordList.txt','r')
        recordLines = recordFile.readlines()        
    finally:
        recordFile.close()
    for recordLine in recordLines:
        if recordLine.startswith('#'):
            continue
        if len(recordLine.strip(' ').strip('\n'))== 0:
            continue        
        record = recordLine.strip('\n').split(';')
        currentAIp = getARecordIp(record[1])
        if currentAIp == 'Failed':
            time.sleep(10)
            currentAIp = getARecordIp(record[1])
        if currentAIp == 'Failed':
            addRecordcmd = addRecord(record)            
            if addRecordcmd[0]:
                intcmdLines.append(addRecordcmd[0])
            if addRecordcmd[1]:
                extcmdLines.append(addRecordcmd[1])
            continue
        pingResult = pingTest(record[1])
        if pingResult:
            continue
        time.sleep(10)
        if pingResult:
            continue
        delRecordcmd = delRecord(record,currentAIp[0].strip('\n'))
        if delRecordcmd[0]:
            intcmdLines.append(delRecordcmd[0])
        if delRecordcmd[1]:
            extcmdLines.append(delRecordcmd[1])
        addRecordcmd = addRecord(record)
        if addRecordcmd[0]:
            intcmdLines.append(addRecordcmd[0])
        if addRecordcmd[1]:
            extcmdLines.append(addRecordcmd[1])
    if intcmdLines:
        try:
            logFile = open("changeintdnslog.txt","a")
            cmdFile = open("updateintdns.bat","w")
            for line in intcmdLines:
                cmdFile.write(line+'\n')
                logFile.write(time.strftime("%m-%d-%Y %H:%M:%S",time.localtime()) + '\n')
                logFile.write(line+'\n\n')
        finally:
            logFile.close()
            cmdFile.close()
        intDnsServer = intcmdLines[0].split(' ')[1].strip(' ')
        cpCmd = r"copy /V /Y updateintdns.bat \\" + intDnsServer + r"\taskscript"
        os.popen(cpCmd)
        
    if extcmdLines:
        try:
            logFile = open("changeextdnslog.txt","a")
            cmdFile = open("updateextdns.bat","w")
            for line in extcmdLines:
                cmdFile.write(line+'\n')
                logFile.write(time.strftime("%m-%d-%Y %H:%M:%S",time.localtime()) + '\n')
                logFile.write(line+'\n\n')
        finally:
            logFile.close()
            cmdFile.close()
        extDnsServer = extcmdLines[0].split(' ')[1].strip(' ')
        cpCmd = r"copy /V /Y updateextdns.bat \\" + extDnsServer + r"\taskscript"
        os.popen(cpCmd)

    
if __name__ == "__main__":      
    main()