You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

188 lines
5.4 KiB

  1. """
  2. This module handles the On Demand Backup utility
  3. """
  4. #Imports
  5. import os, webnotes
  6. from datetime import datetime
  7. #Global constants
  8. from webnotes.defs import backup_path, backup_link_path, backup_url
  9. verbose = 0
  10. #-------------------------------------------------------------------------------
  11. class BackupGenerator:
  12. """
  13. This class contains methods to perform On Demand Backup
  14. To initialize, specify (db_name, user, password, db_file_name=None)
  15. If specifying db_file_name, also append ".sql.gz"
  16. """
  17. def __init__(self, db_name, user, password, db_file_name=None):
  18. self.db_name = db_name
  19. self.user = user
  20. self.password = password
  21. self.db_file_name = db_file_name and db_file_name \
  22. or (backup_path + db_name + ".sql.gz")
  23. def take_dump(self):
  24. """
  25. Dumps a db via mysqldump
  26. """
  27. os.system("""mysqldump -u %(user)s -p%(password)s %(db_name)s |
  28. gzip -c > %(db_file_name)s""" % self.__dict__)
  29. def copy_to_backup_link(self):
  30. """
  31. Copies the backup file from backup path to shared link path
  32. It also gives the file a random name, thus hiding the db_name
  33. """
  34. import random
  35. todays_date = "".join(str(datetime.date(datetime.today())).split("-"))
  36. random_number = str(int(random.random()*99999999))
  37. #Generate a random name using today's date and a 8 digit random number
  38. random_name = todays_date + "_" + random_number + ".sql.gz"
  39. os.system("""cp -f %(src_file)s %(dest_file)s""" % \
  40. {"src_file":self.db_file_name,
  41. "dest_file":(backup_link_path + random_name)})
  42. if verbose: print "file copied"
  43. return random_name
  44. def get_recipients(self):
  45. """
  46. Get recepient's email address
  47. """
  48. import webnotes.db
  49. webnotes.conn = webnotes.db.Database(use_default = 1)
  50. recipient_list = webnotes.conn.sql("""SELECT parent FROM tabUserRole
  51. WHERE role='System Manager'
  52. AND parent!='Administrator'""")
  53. return [i[0] for i in recipient_list]
  54. def send_email(self, backup_file):
  55. """
  56. Sends the link to backup file located at erpnext/backups
  57. """
  58. file_url = backup_url + backup_file
  59. from webnotes.utils.email_lib import sendmail
  60. recipient_list = self.get_recipients()
  61. msg = """<a href=%(file_url)s>Click here to begin downloading\
  62. your backup</a>
  63. This link will be valid for 24 hours.
  64. Also, a new backup will be available for download (if requested)\
  65. only after 24 hours.""" % {"file_url":file_url}
  66. datetime_str = datetime.fromtimestamp(os.stat(self.db_file_name).st_ctime)
  67. subject = datetime_str.strftime("%d/%m/%Y %H:%M:%S") + """ - Backup ready to be downloaded"""
  68. sendmail(recipients=recipient_list, msg=msg, subject=subject)
  69. return recipient_list
  70. def get_backup(self):
  71. """
  72. Takes a new dump if existing file is old
  73. and sends the link to the file as email
  74. """
  75. #Check if file exists and is less than a day old
  76. #If not Take Dump
  77. if is_file_old(self.db_file_name):
  78. self.take_dump()
  79. #Copy file to backup_link_path
  80. #This is a security hole. When the user calls get_backup repeatedly
  81. #a file will be generated each time.
  82. backup_file = self.copy_to_backup_link()
  83. #Email Link
  84. recipient_list = self.send_email(backup_file)
  85. return recipient_list
  86. #-------------------------------------------------------------------------------
  87. def get_backup():
  88. """
  89. This function is executed when the user clicks on
  90. Toos > Download Backup
  91. """
  92. #if verbose: print webnotes.conn.cur_db_name + " " + webnotes.defs.db_password
  93. odb = BackupGenerator(webnotes.conn.cur_db_name, webnotes.conn.cur_db_name,\
  94. webnotes.defs.db_password)
  95. recipient_list = odb.get_backup()
  96. delete_temp_backups()
  97. webnotes.msgprint("""A download link to your backup will be emailed \
  98. to you shortly on the following email address:
  99. %s""" % (str(recipient_list),))
  100. def delete_temp_backups():
  101. """
  102. Cleans up the backup_link_path directory by deleting files older than 24 hours
  103. """
  104. file_list = os.listdir(backup_link_path)
  105. for this_file in file_list:
  106. this_file_path = backup_link_path + this_file
  107. if is_file_old(this_file_path):
  108. os.remove(this_file_path)
  109. def is_file_old(db_file_name, older_than=24):
  110. """
  111. Checks if file exists and is older than specified hours
  112. Returns ->
  113. True: file does not exist or file is old
  114. False: file is new
  115. """
  116. if os.path.isfile(db_file_name):
  117. from datetime import timedelta
  118. import time
  119. #Get timestamp of the file
  120. file_datetime = datetime.fromtimestamp\
  121. (os.stat(db_file_name).st_ctime)
  122. if datetime.today() - file_datetime >= timedelta(hours = older_than):
  123. if verbose: print "File is old"
  124. return True
  125. else:
  126. if verbose: print "File is recent"
  127. return False
  128. else:
  129. if verbose: print "File does not exist"
  130. return True
  131. #-------------------------------------------------------------------------------
  132. if __name__ == "__main__":
  133. """
  134. is_file_old db_name user password
  135. get_backup db_name user password
  136. """
  137. import sys
  138. cmd = sys.argv[1]
  139. if cmd == "is_file_old":
  140. odb = BackupGenerator(sys.argv[2], sys.argv[3], sys.argv[4])
  141. is_file_old(odb.db_file_name)
  142. if cmd == "get_backup":
  143. odb = BackupGenerator(sys.argv[2], sys.argv[3], sys.argv[4])
  144. odb.get_backup()
  145. if cmd == "take_dump":
  146. odb = BackupGenerator(sys.argv[2], sys.argv[3], sys.argv[4])
  147. odb.take_dump()
  148. if cmd == "send_email":
  149. odb = BackupGenerator(sys.argv[2], sys.argv[3], sys.argv[4])
  150. odb.send_email("abc.sql.gz")
  151. if cmd == "delete_temp_backups":
  152. delete_temp_backups()