#!/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()