#!/usr/bin/python
#-*- coding: utf-8 -*-
import mysql.connector
import os
import sys
import socket
import ssl
import threading
import time
import logging
import errno
import signal
import daemon

from socket import error as socket_error
from mysql.connector import errorcode

context = daemon.DaemonContext(
	working_directory='/tmp',
	umask=0o002,
)

context.signal_map = {
	signal.SIGTERM: 'terminate',
	signal.SIGHUP: 'terminate',
	signal.SIGUSR1: 'terminate'
}

context.open()

### Your settings ###
JOBS_CONTROLER = 'jobcontroler' # Remote controler to run the jobs, leave blank to use localhost
JOBS_CONTROLER_TCP_PORT = 1111
WAIT_FOR = 300 # Sleep time to next loop. Each loop send the whole jobs list in DB.
TIMEOUT = 10 # Socket time out in seconds
AUTH_OK_FLAG = 'OK'
AUTH_FAILED_FLAG = 'AuthFailed'
DBCONFIG = {
  'user': 'root',
  'password': 'YOUR_PASSWORD_HERE',
  'host': 'localhost',
  'database': 'netupdate',
  'raise_on_warnings': True,
}
#####################


class createThread(threading.Thread):
		
		def __init__(self, task = [], DBCONFIG = [], passph = None):

			super(createThread, self).__init__()
			self.task = task
			self.DBconnexion = mysql.connector.connect(**DBCONFIG)
			self.passph = passph

		def run(self):

			value = '{0} {1} {2} {3}'.format(self.task[1], self.task[2], self.task[3], self.task[0]) # The task format is: jobName.sh param1 param2 job_id
			job_id = int(self.task[0])

			try:
				
				# CREATE SOCKET
				s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
				s.settimeout(TIMEOUT)

				# WRAP SOCKET
				wrappedSocket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers="ADH-AES256-SHA")

				wrappedSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # each job as his socket
				wrappedSocket.connect((JOBS_CONTROLER, JOBS_CONTROLER_TCP_PORT))

			except Exception, e:
				logging.error('Can not connect to the jobs controler %s:%d. Error is %s' % (JOBS_CONTROLER, JOBS_CONTROLER_TCP_PORT, e))
				exit()

			try:			
		        	wrappedSocket.send(self.passph)					
				
			except socket_error as serr:
				logging.error('Job %s: socket error while sending: %s', job_id, serr.errno)
				exit()

			try:
				r = wrappedSocket.recv(9999999)
				
				if r == AUTH_OK_FLAG:
				
					try:
						wrappedSocket.send(value.encode())
						logging.info('Sending task %s as job %s',value, job_id) # The task format is: jobName.sh param1 param2 job_id						
					
					except socket_error as serr:
						logging.error('Job %s: socket error while sending: %s', job_id, serr.errno)
						exit()	
					
					try:
						r = wrappedSocket.recv(9999999)	

					except socket_error as serr:
						logging.error('Job %s: socket error while sending: %s', job_id, serr.errno)
						exit()		
					try: 
						self.cursUpdate = self.DBconnexion.cursor()
						#self.cursUpdate.execute("""UPDATE jobs SET `status` = %s WHERE `id` = %s""", ( str(r), job_id) )
						self.cursUpdate.execute("""UPDATE jobs SET `status` = %s, date = null WHERE `id` = %s""", ( str(r), job_id) )
						self.cursUpdate.close()
						self.DBconnexion.commit()
						self.DBconnexion.close()
						logging.info('Job n° %d database updated to status %s',job_id, str(r))

					except  Exception, e:			
						logging.error(e)
						exit()
				
				else:
					logging.error('Job n° %d returns %s',job_id,r)
					exit()											
									
			except socket.error as rerr:
				logging.error('Running job %s: receiving socket error: %s',job_id,rerr.errno)
				exit()						


with context:
	while 1:

		try:
			TRACE_FILE = '/var/log/netupdate/netupdate.log'
			fp = open(TRACE_FILE, 'a').close()
			logging.basicConfig(filename=TRACE_FILE,level=logging.DEBUG,\
			format='%(asctime)s -- %(pathname)s[%(process)d]: -- %(levelname)s -- %(message)s')
			logging.info('Started main loop.')	

		except IOError:
			print u'ERROR: can not open file', TRACE_FILE, '!'
			exit("Bye")

		try:
			DBconnexion = mysql.connector.connect(**DBCONFIG)
			curs = DBconnexion.cursor()
			curs.execute("""SELECT passphrase FROM authentication WHERE id = 1""") # Get the passwd from DB
			sendpassph = str(curs.fetchone()[0]) 
					
			curs.execute("""SELECT id,file,param1,param2 FROM jobs WHERE status <> '0'""") # Get the jobs list from DB
			rows = curs.fetchall()
			curs.close()
 			DBconnexion.close()				
			
			# Now start a thread for each job
			for row in rows:			
				myThread = createThread(row, DBCONFIG,sendpassph)
				myThread.start()		
			time.sleep(WAIT_FOR)
			logging.info('Stopped main loop.')# Wait for the next loop
				
		except mysql.connector.Error as err:
 		
			if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
				logging.error('Something is wrong with your Mysql authentication !')
				exit()
		
			elif err.errno == errorcode.ER_BAD_DB_ERROR:
				logging.error('Database does not exist')
				exit()

			else:
				logging.error('Error: %s',err)
				exit()
							
		except KeyboardInterrupt:
			logging.info('Stopped by user')																
		        exit('Stopped by user')																		
context.close()
