import json
from socket import AF_INET, SOCK_DGRAM
import sys
import socket
import re
import subprocess
import struct, time
from baseCheck import baseCheck

# reference time (in seconds since 1900-01-01 00:00:00)
TIME1970 = 2208988800L # 1970-01-01 00:00:00

class checkNTP(baseCheck):

    ipregexp = re.compile("^(\d+)\.(\d+)\.(\d+)\.(\d+)$")
    hostregexp = re.compile("^.*\s+has address\s+(.*)\s*$")

    def resolveIP(self, host, nameserver):
        try:
            resolvestr = subprocess.Popen(['host',host,nameserver], stdout=subprocess.PIPE).communicate()[0]
            for line in resolvestr.split("\n"):
                m = self.hostregexp.match(line)
                if m != None:
                    return m.group(1)
            self.logMsg("Unable to resolve host %s on name server %s." % (host,nameserver))
        except Exception as e:
            self.logMsg("Unable to resolve host %s on name server %s." % (host,nameserver))
            self.logMsg("Exception: %s" % str(e))
        return ''

    def pingNTP(self, host):
        self.timedifference = 0.0
        port = 123
        msg = '\x1b' + 47 * '\0'

        # Try to connect to the NTP server
        try:
            client = socket.socket(AF_INET, SOCK_DGRAM)
            client.settimeout(5)
            client.sendto(msg, (host,port))
            msg, address = client.recvfrom(1024)
        except Exception as e:
            self.logMsg("Unable to connect to NTP server %s." % host)
            self.logMsg("Exception: %s" % str(e))
            return False

        t = struct.unpack( "!12I", msg )[10]
        t -= TIME1970
        self.timedifference = (time.time() - t)
        return True

    def runCheck(self,config, debug):

        nameserver1=config["environment"]["dns1"]
        nameserver2=config["environment"]["dns2"]

        ntp1=config["environment"]["ntp1"]
        if not self.ipregexp.match(ntp1):
            ntp1 = self.resolveIP(ntp1, nameserver1)
            if ntp1 == '':
                ntp1 = self.resolveIP(ntp1, nameserver2)

        if len(ntp1) == 0:
            self.addWarning("Unable to resolve Primary Time server %s.  Please verify the configuration." % config["environment"]["ntp1"])
        elif not self.pingNTP(ntp1):
            self.addWarning("Unable to contact Primary Time server %s.  Please verify the configuration." % ntp1)
        elif self.timedifference > 3600:
            self.addWarning("Time difference from Primary Time server %s is %ds.  Please synchronize time across KVM host servers." % (ntp1, self.timedifference))

        ntp2=config["environment"]["ntp2"]
        if not self.ipregexp.match(ntp2):
            ntp2 = self.resolveIP(ntp2, nameserver1)
            if ntp2 == '':
                ntp2 = self.resolveIP(ntp2, nameserver2)

        if len(ntp2) == 0:
            self.addWarning("Unable to resolve Secondary Time server %s.  Please verify the configuration." % config["environment"]["ntp2"])
        elif not self.pingNTP(ntp2):
            self.addWarning("Unable to contact Secondary Time server %s.  Please verify the configuration." % ntp2)
        elif self.timedifference > 3600:
            self.addWarning("Time difference from Secondary Time server %s is %ds.  Please synchronize time across KVM host servers." % (ntp2, self.timedifference))

        return 0

    def getHumanName(self):
        return "Check if NTP is alive"
