#!/usr/bin/python
#posix, md5
import os, sys, time, binascii, socket, select, time, datetime, posix, md5, shutil


class ApiRos:
    "Routeros api"
    def __init__(self, sk):
        self.sk = sk
        self.currenttag = 0

    def login(self, username, pwd):
        for repl, attrs in self.talk(["/login"]):
            chal = binascii.unhexlify(attrs['=ret'])
        md = md5.new()
        md.update('\x00')
        md.update(pwd)
        md.update(chal)
        self.talk(["/login", "=name=" + username,
                   "=response=00" + binascii.hexlify(md.digest())])

    def talk(self, words):
        if self.writeSentence(words) == 0: return
        r = []
        while 1:
            i = self.readSentence();
            if len(i) == 0: continue
            reply = i[0]
            attrs = {}
            for w in i[1:]:
                j = w.find('=', 1)
                if (j == -1):
                    attrs[w] = ''
                else:
                    attrs[w[:j]] = w[j+1:]
            r.append((reply, attrs))
            if reply == '!done': return r

    def writeSentence(self, words):
        ret = 0
        for w in words:
            self.writeWord(w)
            ret += 1
        self.writeWord('')
        return ret

    def readSentence(self):
        r = []
        while 1:
            w = self.readWord()
            if w == '': return r
            r.append(w)

    def writeWord(self, w):
#        print ("<<< " + w)
        self.writeLen(len(w))
        self.writeStr(w)

    def readWord(self):
        ret = self.readStr(self.readLen())
#        print ">>> " + ret
        return ret

    def writeLen(self, l):
        if l < 0x80:
            self.writeStr(chr(l))
        elif l < 0x4000:
            l |= 0x8000
            self.writeStr(chr((l >> 8) & 0xFF))
            self.writeStr(chr(l & 0xFF))
        elif l < 0x200000:
            l |= 0xC00000
            self.writeStr(chr((l >> 16) & 0xFF))
            self.writeStr(chr((l >> 8) & 0xFF))
            self.writeStr(chr(l & 0xFF))
        elif l < 0x10000000:
            l |= 0xE0000000
            self.writeStr(chr((l >> 24) & 0xFF))
            self.writeStr(chr((l >> 16) & 0xFF))
            self.writeStr(chr((l >> 8) & 0xFF))
            self.writeStr(chr(l & 0xFF))
        else:
            self.writeStr(chr(0xF0))
            self.writeStr(chr((l >> 24) & 0xFF))
            self.writeStr(chr((l >> 16) & 0xFF))
            self.writeStr(chr((l >> 8) & 0xFF))
            self.writeStr(chr(l & 0xFF))

    def readLen(self):              
        c = ord(self.readStr(1))    
        if (c & 0x80) == 0x00:      
            pass                    
        elif (c & 0xC0) == 0x80:    
            c &= ~0xC0              
            c <<= 8                 
            c += ord(self.readStr(1))    
        elif (c & 0xE0) == 0xC0:    
            c &= ~0xE0              
            c <<= 8                 
            c += ord(self.readStr(1))    
            c <<= 8                 
            c += ord(self.readStr(1))    
        elif (c & 0xF0) == 0xE0:    
            c &= ~0xF0              
            c <<= 8                 
            c += ord(self.readStr(1))    
            c <<= 8                 
            c += ord(self.readStr(1))    
            c <<= 8                 
            c += ord(self.readStr(1))    
        elif (c & 0xF8) == 0xF0:    
            c = ord(self.readStr(1))     
            c <<= 8                 
            c += ord(self.readStr(1))    
            c <<= 8                 
            c += ord(self.readStr(1))    
            c <<= 8                 
            c += ord(self.readStr(1))    
        return c                    

    def writeStr(self, str):        
        n = 0;                      
        while n < len(str):         
            r = self.sk.send(str[n:])
            if r == 0:
                with open(ErrorFile, 'a') as f:
                    f.write(str(time.strftime(" %H:%M:%S %Y"))+"connection closed by remote end -> writeStr"+fon)
                    f.closed
                raise (RuntimeError, "connection closed by remote end")
            n += r                  

    def readStr(self, length):      
        ret = ''                    
        while len(ret) < length:    
            s = self.sk.recv(length - len(ret))
            if s == '':
                with open(ErrorFile, 'a') as f:
                    f.write(str(time.strftime(" %H:%M:%S %Y"))+"connection closed by remote end -> readStr"+fon)
                    f.closed
                raise (RuntimeError, "connection closed by remote end")
            ret += s
        return ret

def collector(IP,User,Password,command1,command2,FirstTurn):

    inputsentence = command1 + command2

#    Interval	= 70
    RxNew	= []
    TxNew	= []
    RxOld	= []
    TxOld	= []
    RxData	= 0
    TxData	= 0
    DLine 	= []
    Offset	= 0

    q = 0
    qd = 0
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
	s.connect((IP, 8728))  
    except (Exception, e):
#	print (e)
	with open(ErrorFile, 'a') as f:
	    f.write(str(time.strftime(" %H:%M:%S %Y"))+str(e)+fon)
	    f.closed
#	break
    apiros = ApiRos(s);
#    time.sleep(1)
    apiros.login(User, Password);
#    time.sleep(2)
    apiros.writeSentence(inputsentence)
    time.sleep(1.5)
    while 1 :
	time1    = str(int(time.time()))
	month    = str(time.strftime("%b"))
	date     = str(int(time.strftime("  %d")))
	timeyear = str(time.strftime(" %H:%M:%S %Y"))
	minutes  = str(time.strftime("%M"))
#	print "Queue -> ",q," Min -> ", minutes
	r = select.select([s, sys.stdin], [], [], None)
#	print "r  ->  ",r
	if s in r[0]:
#	something to read in socket, read sentence
	    try:
		x = apiros.readSentence()
#		print "x  ->  ",x
#		print "len(x) -> ",len(x)
#		print "x[35] -> ",x[35]
		if x[0] == '!done' : break
		
		PositionIP = 0
		PosCount = 1
		while PosCount < len(x):
		    TempValue = x[PosCount]
		    if TempValue[0:6]	== '=name=' 		: 
#			print TempValue[0:6] 
			PositionName = PosCount
		    if TempValue[0:7]	== '=bytes=' 		: 
#			print TempValue[0:7] 
			PositionRxTx = PosCount
		    if TempValue[0:18] == '=target-addresses='	: 
#			print TempValue[0:18]
			Offset = 18 
			PositionIP = PosCount
		    if TempValue[0:8] == '=target='		: 
#			print TempValue[0:8] 
			PositionIP = PosCount
			Offset = 8
		    if TempValue[0:10]	== '=disabled='		: 
#			print TempValue[0:10] 
			PositionDisabled = PosCount
		    PosCount = PosCount + 1
#		print "PosName-----------> ",q,"  ",x[PositionName]
#		print "PosRxTx-----------> ",q,"  ",x[PositionRxTx]
#		print "PosIP-------------> ",q,"  ",x[PositionIP]
#		print "PosDisabled-------> ",q,"  ",x[PositionDisabled]
#		time.sleep(0.1)

#	Generirane na flag detectvasht PPPoE
#		flag = x[PositionFlag]
#		flag = flag[:5]
#		print "flag  - ",q,"  ",flag

#	Preskachane na Disabled Queues
		if x[PositionDisabled] == '=disabled=true' :
#			print  "Queue status - ",q,"  ",x[PositionDisabled]
			q = q + 1
			qd = qd + 1
			continue

# 	Generating Queue name
		WorkName = x[PositionName]
#		print WorkName
		lenqName = len(WorkName)-1
		pName = WorkName[7: 10]
#		print("pName",pName)
		if pName == "ppp" :
		    qName = WorkName[7:lenqName]
		else:
		    qName = WorkName[6:]
#		print("qName",qName)

#	 Generirane na IP
		RawIP = x[PositionIP]
		RawIP = RawIP[Offset:]
#		print "RawIP -> ",RawIP
#		time.sleep(0.2)
#	 Generirane na Rx / Tx
#		print(pName)
#		if pName =="ppp":
#		    pos = PositionRxTx
#		else: pos = PositionCorection
		RxTx = x[PositionRxTx]
#		print(RxTx)
		RxTx = RxTx[7:]
#		print(RxTx)
		pp = len(RxTx)
		kk = 0
		while (RxTx[kk: kk+1] != '/'):
		    kk = kk + 1
		    Rx = RxTx[:kk]
		    Tx = RxTx[kk+1 :pp]
		RxNew.append(Rx)
		TxNew.append(Tx)
		RxStr = str(Rx)
		TxStr = str(Tx)
#		print 'Rx = ',Rx,'   Tx = ',Tx
#		print 'RxStr = ',RxStr,'   TxStr = ',TxStr

#	Generirane na imeto na faila

		p = len(x[PositionIP]) - Offset
		k = 0
		d = ''
		while k < p :
		    if RawIP[k :k+1] == '/':
			d = d + '_'
			k = k + 1
			if RawIP[k :k+2] == '24':
			    d = d + '255_255_255_0-0'
			elif RawIP[k :k+2] == '25':
			    d = d + '255_255_255_128-0'
			elif RawIP[k :k+2] == '26':
			    d = d + '255_255_255_192-0'
			elif RawIP[k :k+2] == '27':
			    d = d + '255_255_255_224-0'
			elif RawIP[k :k+2] == '28':
			    d = d + '255_255_255_240-0'
			elif RawIP[k :k+2] == '29':
			    d = d + '255_255_255_248-0'
			elif RawIP[k :k+2] == '30':
			    d = d + '255_255_255_252-0'
			elif RawIP[k :k+2] == '31':
			    d = d + '255_255_255_254-0'
			else : d = d + '255_255_255_255-0'
			k = len(RawIP)
		    elif RawIP[k :k+1] != '.':
			d = d + RawIP[k :k+1]
		    else : d = d + '_'
		    k = k + 1
#		print ("generirano ime d = ",d)
#		print("p ===> ",p)
#		print ("RawIP",RawIP[:7])

#		if (PositionIP != 0) and (p>0) and (p<=18) and (RawIP[:7] != '<pppoe-'):
		if (1 > 2):
		    FileName = TrfDIR + '0_0_0_0_0_0_0_0-' + d + '.trf'
		    FileNameRxOld = TmpDIR + '/0_0_0_0_0_0_0_0-' + d + '_old.rx'
		    FileNameTxOld = TmpDIR + '/0_0_0_0_0_0_0_0-' + d + '_old.tx'
#		    print ("IP FileNameTxOld = ",FileNameRxOld)

		else :
		    FileName = TrfDIR + qName + '.trf'
		    FileNameRxOld = TmpDIR + '/' + qName + '_old.rx'
		    FileNameTxOld = TmpDIR + '/' + qName + '_old.tx'
#		    print ("PPPoE FileNameRxOld = ",FileNameRxOld)

# Generirane na stringa za zapisvane v faila

		RxInit = "0"
		TxInit = "0"
		try:
		    with open(FileNameRxOld, 'r') as f:
		        RxOld = f.readline()
		        f.closed
#		        print ("ot Fail - ",FileNameRxOld," prochetoh -> ",RxOld)
		except IOError, (errno,strerror):
#		    print "I/O Error read RxOld errno -> ",errno," -> ",strerror
		    with open(FileNameRxOld, 'w') as f:
		        f.write(RxInit)
		        f.closed
		        RxOld = "0"
#		        print ("v fail - ",FileNameRxOld," zapisah INIT VALUE - ",RxInit)
		    pass

		try:
		    with open(FileNameTxOld, 'r') as f:
		        TxOld = f.readline()
		        f.closed
#		        print ("ot Fail - ",FileNameTxOld," prochetoh -> ",str(TxOld))
		except IOError, (errno,strerror):
#		    print "I/O Error read TxOld errno -> ",errno," -> ",strerror
		    with open(FileNameTxOld, 'w') as f:
		        f.write(TxInit)
		        f.closed
		        TxOld = "0"
#		        print ("v fail - ",FileNameTxOld," zapisah INIT VALUE - ",str(TxInit))
		    pass                    	    
                    	    
		if   long(RxStr) > long(RxOld) : RxData = long(RxStr) - long(RxOld)
		elif long(RxStr) < long(RxOld) : RxData = long(RxStr)
		else : RxData = 0

		if   long(TxStr) > long(TxOld) : TxData = long(TxStr) - long(TxOld)
		elif long(TxStr) < long(TxOld) : TxData = long(TxStr)
		else : TxData = 0

#		print 'RxStr  = ',RxStr,'   TxStr',TxStr
#		print 'RxOld  = ',RxOld,'   TxOld',TxOld
#		print 'RxData = ',str(RxData),'     TxData  ',str(TxData)

		with open(FileNameRxOld, 'w') as f:
		    f.write(RxStr)
		    f.closed
#		    print "In FILE - ",FileNameRxOld," zapisah TxStr - ",RxStr
		with open(FileNameTxOld, 'w') as f:
		    f.write(TxStr)
		    f.closed
#		    print "In FILE - ",FileNameTxOld," zapisah TxStr - ",TxStr

		if FirstTurn :
		    RxData = '0'
		    TxData = '0'
			
		if len(date) == 1:
		    DLine = 'U  ' + time1 + ' ' + month + '  ' + date + timeyear + '  Rx ' + str(RxData) + '  Tx ' + str(TxData) + fot + 't   300' + fon
		else : 
		    DLine = 'U  ' + time1 + ' ' + month + ' ' + date + timeyear + '  Rx ' + str(RxData) + '  Tx ' + str(TxData) + fot + 't   300' + fon

#		print "FileName = ",FileName
#		print (DLine)

		with open(FileName, 'a') as f:
		    f.write(DLine)
		    f.closed

	    except Exception, e:
		print e
		with open(ErrorFile, 'a') as f:
		    f.write(str(time.strftime("%d  %H:%M:%S %Y"))+str(e)+fon)
		    f.closed
		break
	else: 
	    print ("Not something to read in socket")
	    with open(ErrorFile, 'a') as f:
		f.write(str(time.strftime("%d  %H:%M:%S %Y"))+'   Not something to read in socket '+fon)
	    break 
	q = q + 1
	inputsentence = ["/quit"]
    apiros.writeSentence(inputsentence)
    s.close()
    print 'Obraboteni Queues - ',q,' ot koito ',q-qd, ' - ENABLED     ',qd,' -  DISABLED'
#    time.sleep(3)




def main():

    FirstTurn	= True
    TURN	= 1

    while 1:
	minutes  = str(time.strftime("%M"))
	WorkFlagTime = str(int(time.time()))

	with open(WorkFlag, 'w') as f:
	    f.write(str(WorkFlagTime))
	    print ('WorkFlag - OK')
	    f.closed

	#For Debug
	#minutes = '04'

	print 'main minute - ',minutes
	while ((minutes == '4') or (minutes == '04') or  (minutes == '9')  or  (minutes == '09') or (minutes == '14') or (minutes == '19') or (minutes == '24') or (minutes == '29') or (minutes == '34') or (minutes == '39') or (minutes == '44')or (minutes == '49') or (minutes == '54') or (minutes == '59')):
    	    minutes  = str(time.strftime("%M"))
    	    InitTime = time.time()
    	    CurrSrv = 1

    	    while (CurrSrv <= Servers):
    		print (SrvIP[CurrSrv-1])
		collector(SrvIP[CurrSrv-1],SrvUser[CurrSrv-1],SrvPassword[CurrSrv-1],cmd1,cmd2,FirstTurn)
		CurrSrv = CurrSrv + 1
		with open(ErrorFile, 'a') as f:
		    f.write(str(time.strftime("%d %b %Y  %H:%M:%S"))+'   NO ERRORS - TURN '+str(TURN)+'   '+SrvIP[CurrSrv-2]+'   OK'+fon)
		    print 'uspeshen cikyl ',fon
		    f.closed

	    FirstTurn = False
	    WorkFlagTime = str(int(time.time()))

	    with open(WorkFlag, 'w') as f:
		f.write(str(WorkFlagTime))
		print ('WorkFlag - OK')
		f.closed

	    print "TURN -> ",TURN,fon,fon
	    TURN = TURN + 1


	    #Generira intervala za izchakvane
	    EndTime = time.time()
	    WorkTime = EndTime - InitTime
	    Interval = 290 - WorkTime

	    #For Debug
	    #Interval = 10
	    
	    print "WorkTime-",WorkTime,"sec"
	    print "Wait Interval-",Interval,"sec"
	    TaI = str(time.strftime("%H:%M:%S"))
	    print "Time Before Interval- ",TaI
	    time.sleep(Interval)
	    TaI = str(time.strftime(":%H%M:%S"))
	    print "Time after Interval- ",TaI

	    minutes  = str(time.strftime("%M"))
	    print 'minute - ',minutes
	time.sleep(1)



Servers		= 18

#For Debug
#Servers		= 1

#ROS		= ["4.11"		]
#SrvIP		= ["109.121.223.18"	]
#SrvUser	= ["admin"		]
#SrvPassword	= ["kontrolnew"		]



ROS		= ["6.19 - RB-Pan_Kula"	,"6.26 - RB-SZ_Kula"	,"5.26 - RB-Kyn"	,"6.19 - x86-Myglij"	,"6.20 - RB-Gur2"	,"6.20 - x86-Nik"	,"6.19 - RB-Gur1"	,"5.8 - x86-Shiv"	,"6.26 - x86-Mejdenik"	,"6.20 - RB-TV_OU"	,"6.5 - RB-PPPoE_Mor"	,"6.3 - RB-Sul_Kula"	,"6.20 - RB-Mogilovo"	,"6.20 - RB-Zmeevo"	,"6.20 - RB-Borilovo"	,"6.20 - RB-Banya"	,"6.27 - RB-ShanovoUlievo"	,"6.27 - RB-Morulei"	]
SrvIP		= ["185.96.164.6"	,"185.96.164.33"	,"185.96.164.46"	,"185.96.164.42"	,"185.96.164.54"	,"185.96.164.14"	,"185.96.164.50"	,"185.96.164.26"	,"185.96.164.18"	,"185.96.164.22"	,"185.96.164.10"	,"185.96.164.62"	,"185.96.164.118"	,"185.96.164.38"	,"185.96.164.34"	,"185.96.164.150"	,"185.96.164.58"		,"185.96.164.166"	]
SrvUser		= ["admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"		,"admin"			,"admin"		]
SrvPassword	= ["kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew22"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew22"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"		,"kontrolnew"			,"kontrolnew"		]


cmd1		= ["/queue/simple/print"]
cmd2		= ["=stats="]

#ForDebug
#TrfDIR		= '/ip_log_temp/'

TrfDIR		= '/ip_log/'
TmpDIR		= TrfDIR+'pppoe_tmp'
ErrorFile	= TrfDIR+'errors.log'
WorkFlag	= TrfDIR+'workflag.log'

fon		= "\n"
fot		= "\t"



##  Clear TEMP DIR
shutil.rmtree(TmpDIR)
os.mkdir(TmpDIR+'/')


if __name__ == '__main__':
    main()
