#!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import time, pyinotify, os, logging, logging.handlers, re, subprocess, smtplib,sys
    from email.MIMEText import MIMEText
    from datetime import datetime, time as d_time
     
     
    LOG_FILENAME = "/tmp/pysync.log"
    LOG_LEVEL = logging.DEBUG
     
    tempo = 900
    pidfile = "/var/run/pysync.pid"
    srv_bkp = "mimic.hectorpablo.fr"
    path_to_datas = "/media/datas"
    filter_file = "^\.syncthing.*|^\.stfolder|^\._|^~\$|^\..*\.sw[px]$|^.*~$"
    filter_folder = "\.TemporaryItems"
    mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MOVED_TO
    folder_plan_1 = ["/documents","/images","/photos","/videos","/book"]
    folder_plan_2 = ["/applis","/formations","/jeux"]
    lst_plan_1 = [path_to_datas+elt for elt in folder_plan_1]
    lst_plan_2 = [path_to_datas+elt for elt in folder_plan_2]
    plan_1 = {'heure':('12h00','23h00'), 'jour':('0123456')}
    plan_2 = {'heure':('01h00',), 'jour':('06')}
    mail_param = {"usr":"<@mail>",
                "pwd":"<password>",
                "srv":"SSL0.OVH.NET",
                "template_success":"/usr/scripts/pysync/mail_rsync.html",
                "port":465,
                "From":"Backup mimic <@mail>",
                "To":"thomas.sanson@live.fr"}
    bypass = False
    source = "/media/datas"
    cible = "/media/backup/sauvegardes/courante"
    user = "admlan"
    nas = "mimic.hectorpablo.fr"
    port = 4807
    exclus = "/usr/scripts/pysync/liste.txt"
    cmd = """rsync\
        -ahv\
        -e "ssh -p %i -o 'ConnectTimeout 10'"\
        --stats\
        --delete\
        --delete-excluded\
        --force\
        --exclude-from=%s\
        %s %s@%s:%s""" % (port,exclus,source,user,nas,cible)
     
    logger = logging.getLogger(__name__)
    logger.setLevel(LOG_LEVEL)
     
    handler = logging.handlers.RotatingFileHandler(LOG_FILENAME,
                                                   maxBytes=1000000,
                                                   backupCount=5,
                                                   )
    formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
     
    def print_params():
        print "cmd_rsync : %s" % cmd
        print "tempo : %s" % tempo
        print "folder_plan_1 : %s" % folder_plan_1
        print "folder_plan_2 : %s" % folder_plan_2
     
    def create_flag(plan):
        flag = "/tmp/" + str(plan) + "_" + srv_bkp
        if os.path.isfile(flag):
            logger.info("svg de type %i deja flagee sur %s" % (plan, srv_bkp))
        else:
            logger.info("\"flagage\" svg de type %i sur %s" % (plan, srv_bkp))
            file_flag = open(flag,"w").close()
     
    def sendmail(mail_param,tab,rsync_time):
        list_file = ""
        resume_rsync = ""
        stats_rsync = []
        del tab[0][0]
        for line in tab[0]:
            if line.startswith("deleting"):
                list_file += "<span style='color:red;'>%s</span><br>" % line
            else:
                list_file += "%s<br>" % line
        for line in tab[1]:
            stats_rsync.append(":".join(line.split(":")[1:]).strip())
        for line in tab[2]:
            resume_rsync += "%s<br>" % line
        end_date = datetime.now().strftime("%d/%m/%Y")
        end_time = datetime.now().strftime("%X")
        file_mail = open(mail_param['template_success'],"r")
        message = eval(repr(file_mail.read().format(stats_rsync[0],stats_rsync[1],stats_rsync[2],stats_rsync[3],stats_rsync[4],stats_rsync[5],stats_rsync[6],stats_rsync[7],stats_rsync[8],stats_rsync[9],stats_rsync[10],stats_rsync[11],stats_rsync[12],resume_rsync,list_file,end_date,end_time,str(rsync_time))))
        file_mail.close()
        msg=""
        msg = MIMEText(message.decode('latin-1').encode('utf-8'),'html')
        msg.set_charset('utf-8')
        msg['Subject']="[OK] Rapport de sauvegarde "
        sender=mail_param['From']
        recever=mail_param['To']
        msg['From']=sender
        msg['to']=recever
        sMsg=smtplib.SMTP_SSL(mail_param['srv'],mail_param['port'])
        sMsg.login(mail_param['usr'],mail_param['pwd'])
        sMsg.sendmail(sender,recever.split(","),msg.as_string())
        sMsg.quit()
        logger.info("mail envoye avec succes")
     
    def check_flag(ptype,plan):
        now = datetime.now()
        dow = now.strftime('%w')
        flag = "/tmp/" + str(ptype) + "_" + srv_bkp
        if os.path.isfile(flag):
            logger.debug("une svg flag doit etre lancee")
            #if datetime.strptime(time_plan[0],"%Hh%M").time() <= now_time <= datetime.strptime(time_plan[1],"%Hh%M").time():
            if dow in plan['jour']:
                logger.debug("jour de sauvegarde !!!")
                for hour in plan['heure']:
                    tdelta = (now - datetime.strptime(hour,"%Hh%M") \
                    .replace(year=now.date().year, month=now.date().month, day=now.date().day))\
                    .total_seconds()
                    if -(tempo/2.0) < tdelta <= tempo/2.0 or bypass:
                        logger.info("svg dans creneau --> lancement sauvegarde....")
                        time.sleep(3)
                        #start_time = datetime.now()
                        #retval = rsync(ptype,cmd)
                        retcode = rsync(ptype,cmd)
                        #end_time = datetime.now()
                        #rsync_time = end_time - start_time
                        #logger.info("duree de la sauvegarde : %s" % str(rsync_time))
                        #logger.info("code retour rsync : %i" % retval[0])
                        if retcode == 0:
                        #    sendmail(mail_param,retval[1],rsync_time)
                            os.remove(flag)
                            logger.info("flag remove")
                        break
     
    def rsync(ptype,cmd):
        start_time = datetime.now()
        if ptype == 1 :
            for folder in folder_plan_2 :
                cmd += " --exclude %s" % folder
        else :
            for folder in folder_plan_1 :
                cmd += " --exclude %s" % folder
        p = subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        result = p.stdout.read().split("\n")
        result_err = p.stderr.read().split("\n")
        tab = [ [], [], [] ]
        i = 0
        for line in result_err:
            if line != "":
                logger.error(line)
        for line in result:
            if line == "":
                i += 1
            else :
                tab[i].append(line)
            logger.info(line)
        end_time = datetime.now()
        rsync_time = end_time - start_time
        logger.info("duree de la sauvegarde : %s" % str(rsync_time))
        logger.info("code retour rsync : %i" % p.wait())
        if p.wait() == 0:
            sendmail(mail_param,tab,rsync_time)
            flag = "/tmp/" + str(ptype) + "_" + srv_bkp
            if os.path.isfile(flag):
                os.remove(flag)
                logger.info("flag remove")
        return (p.wait())
     
    class Identity(pyinotify.ProcessEvent):
        def process_default(self, event):
            if not re.search(filter_file, event.name) \
            and not re.search(filter_folder, event.path):
                if "/".join(event.pathname.split("/")[:4]) in lst_plan_1:
                    logger.info("modif detected on plan 1: %s " % event.pathname)
                    create_flag(1)
     
                elif "/".join(event.pathname.split("/")[:4]) in lst_plan_2:
                    logger.info("modif detected on plan 2: %s " % event.pathname)
                    create_flag(2)
     
                else:
                    logger.info("modif detected on none plan: %s " % event.pathname)
                    create_flag(2)
     
    def main():
        logger.info("Pysync started")
        wm1 = pyinotify.WatchManager()
        notifier1 = pyinotify.ThreadedNotifier(wm1, default_proc_fun=Identity())
        notifier1.start()
        wm1.add_watch(path_to_datas, mask, rec=True, auto_add=True)
        logger.info("Pynotify launched on %s" % path_to_datas)
     
        while True:
            try:
                logger.debug("blablabla")
                check_flag(1,plan_1)
                check_flag(2,plan_2)
                time.sleep(tempo)
            except KeyboardInterrupt:
                notifier1.stop()
                logger.error("Pynotify has stopped")
                break
            except:
                notifier1.stop()
                logger.error("Pynotify has stopped")
                raise
     
    if len(sys.argv) >= 2:
        if sys.argv[1] == "-p":
            logger.info("Pysync called with param '-p' : show params")
            print_params()
        if sys.argv[1] == "-n":
            logger.info("Pysync called with param '-n' : run rsync now")
            rsync(1,cmd)
     
    else:
        if os.path.exists(pidfile):
            pid = str(os.getpid())
            pid_daemon = open(pidfile,"r").read().strip()
            if pid_daemon == pid:
                main()
            else:
                logger.error("Pysync already started !!")
                print("Pysync already started !!")
        else:
            main()