Advertisement
Guest User

Untitled

a guest
May 4th, 2018
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.00 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import os
  4. import subprocess
  5. import sys
  6. import datetime
  7. from datetime import datetime, timedelta
  8.  
  9. import glob
  10. import string
  11. import re
  12. import shlex
  13.  
  14. import smtplib
  15. import email
  16.  
  17. #must be set manually to avoid additional python modules
  18. DATADIR = '/home/mysql/data'
  19. ISSLAVE = False #can be True or False
  20. #
  21.  
  22. #basic config - please do not change
  23. HOSTNAME = os.uname()[1]
  24. LOCKDIR = "/tmp/rn-innobackup.lock" #LOCKDIR
  25. LOGFILE = "/var/log/rn-mysqlbackup.log" #LOGFILE
  26. INNOBACKUPEX = "/usr/bin/innobackupex"
  27. ALERTMAIL = "mmaros@reflected.net" #to use multiple recepients, this needs to be turned into a list ["email1@bla.com", "email2@bla.com", "email3@bla.com", ...]
  28. #ALERTMAIL = "support@reflected.net" #to use multiple recepients, this needs to be turned into a list ["email1@bla.com", "email2@bla.com", "email3@bla.com", ...]
  29.  
  30.  
  31. #backup configuration
  32. #to use one binary over other, please put it at the start of the list, if it doesnt exist it will get skipped
  33. COMPRESS = ["/usr/bin/pbzip2","/usr/local/sbin/pbzip2","/usr/bin/pigz","/usr/local/sbin/pigz"]
  34. BACKUPDIR = '/home/backups/mysql/'
  35. RETENTION =int(7)
  36. STREAMING = False
  37. PARALEL = "4"
  38. USEMEMORY = "1G"
  39. CUSTOMOPT = "" #separate them with a space between, use syntax same as on the cli "--option=value --option2=value"
  40.  
  41.  
  42.  
  43. ########Bunch of checks that need to be ran before we proceed
  44. ########
  45. #check which compression to use
  46. compression = ""
  47. for i in range(0, len(COMPRESS)):
  48. if os.path.isfile(COMPRESS[i]):
  49. compression = COMPRESS[i]
  50. break
  51. #exit if compression is not set up
  52. if compression == "":
  53. print ("none of compressions are available, please check which ones are available and which ones are provided")
  54. sys.exit()
  55. #exit if datadir doesnt exist
  56. if os.path.isdir(DATADIR) is False:
  57. print (DATADIR + "does not exit")
  58. sys.exit()
  59.  
  60. #compression being used:
  61. if ("pbzip2" in compression):
  62. backupSuffix = ".tar.bz2"
  63. elif ("pigz" in compression):
  64. backupSuffix = ".tar.gz"
  65. else:
  66. print ("wrong compression")
  67. sys.exit()
  68.  
  69.  
  70. #set backupname
  71. createDate = datetime.today().strftime("%Y%m%d-%H%M%S")
  72. if STREAMING:
  73. createName = "mysql_backups_" + HOSTNAME + "_" + createDate + "-streaming"
  74. createNameCompressed = "mysql_backups_" + HOSTNAME + "_" + createDate + "-streaming" + backupSuffix
  75. else:
  76. createName = "mysql_backups_" + HOSTNAME + "_" + createDate
  77. createNameCompressed = "mysql_backups_" + HOSTNAME + "_" + createDate + backupSuffix
  78.  
  79. #if the machine is a slave add --slave-info to options
  80. if ISSLAVE:
  81. CUSTOMOPT += " --no-timestamp --slave-info "
  82. else:
  83. CUSTOMOPT += " --no-timestamp "
  84.  
  85.  
  86.  
  87. #skip disk check if .skipcheck is present in backupdir, remove after the run
  88. def skipCheck():
  89. if os.path.isfile(BACKUPDIR + ".skipcheck"):
  90. now = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
  91. print(now + ": Skipping prerun disk space checks and running backups. skipcheck file will be removed")
  92. #function that runs backups
  93. os.remove(BACKUPDIR + ".skipcheck")
  94. else:
  95. isRunnable()
  96.  
  97. #check total freeDisk disk space on partition containting BACKUPDIR, in bytes
  98. def freeSpace(BACKUPDIR):
  99. st = os.statvfs(BACKUPDIR)
  100. freeDisk = int(st.f_bavail * st.f_frsize)
  101. return freeDisk
  102.  
  103. #get the size of the backup specified
  104. def listBackups(BACKUPDIR, backupSuffix):
  105. backupNameRegex = os.path.join(BACKUPDIR + 'mysql_backups_' + HOSTNAME + '_' + '*' + backupSuffix)
  106. listBackups = glob.glob(backupNameRegex)
  107. return listBackups
  108.  
  109. def lastBackupSize():
  110. backupNames = listBackups(BACKUPDIR, backupSuffix)
  111. print (backupNames)
  112. if not backupNames:
  113. lastSize = 0
  114. else:
  115. lastSize = os.path.getsize(max(backupNames , key = os.path.getctime))
  116. return lastSize
  117.  
  118. #get size of the mysql datadir
  119. def dirSize(path):
  120. total_size = 0
  121. for dirpath, dirnames, filenames in os.walk(path):
  122. for f in filenames:
  123. fp = os.path.join(dirpath, f)
  124. total_size += os.path.getsize(fp)
  125. return total_size
  126.  
  127. #prerun checks
  128. def isRunnable():
  129. oldAge = 1
  130. lastSize = lastBackupSize()
  131. freeDisk = freeSpace(BACKUPDIR)
  132. #if streaming backup, we dont care about size of the datadir
  133. if STREAMING:
  134. datadirSize = 0
  135. else:
  136. datadirSize = dirSize(DATADIR)
  137. print("Size of last backup")
  138. print(lastSize)
  139. print("Free disk size")
  140. print(freeDisk)
  141. print("Datadir size")
  142. print(datadirSize)
  143. if ((freeDisk - lastSize - datadirSize) * 1.1) < (lastSize + datadirSize):
  144. msgBody = "Cant run backups as there is not enough free disk space"
  145. sendMail(msgBody)
  146. print("All gucci")
  147. runBackup()
  148.  
  149. def runBackup():
  150. #how to split it
  151. #https://docs.python.org/2/library/subprocess.html
  152. #
  153. print("runBackup")
  154. if not STREAMING:
  155. commandToRun = "nice -n 19 " + INNOBACKUPEX + " " + CUSTOMOPT + "--parallel=" + PARALEL + " " + BACKUPDIR + createName
  156. #parse it into a list for the popen to work properly
  157. args = shlex.split(commandToRun)
  158. with open("/tmp/innobackupex.stdout.log", "a+") as f_stdout, open("/tmp/innobackupex.stderr.log", "a+") as f_stderr:
  159. p = subprocess.Popen(args, stdout=f_stdout, stderr=f_stderr)
  160. p.communicate()
  161. #check if backup was successful
  162. lastline = file("/tmp/innobackupex.stderr.log", "r").readlines()[-1]
  163. if not re.search("completed OK!", lastline):
  164. msgBody = "Innobackupex failed, more information can be found in the log"
  165. sendMail(msgBody)
  166. print("innobackupex made it to the otherside")
  167. print("apply log now")
  168. commandToRun = "nice -n 19 " + INNOBACKUPEX + " " + "--apply-log " + "--use-memory=" + USEMEMORY + " " + BACKUPDIR + createName
  169. print(commandToRun)
  170. args = shlex.split(commandToRun)
  171. print(args)
  172. with open("/tmp/apply.innobackupex.stdout.log", "a+") as f_stdout, open("/tmp/apply.innobackupex.stderr.log", "a+") as f_stderr:
  173. p = subprocess.Popen(args, stdout=f_stdout, stderr=f_stderr)
  174. p.communicate()
  175. lastline = file("/tmp/apply.innobackupex.stderr.log", "r").readlines()[-1]
  176. if not re.search("completed OK!", lastline):
  177. msgBody = "Innobackupex failed at applying log, more information can be found in the log"
  178. sendMail(msgBody)
  179. #compress mysql configs as well
  180. commandToRun = "tar -cz /etc/mysql/"
  181. print (commandToRun)
  182. args = shlex.split(commandToRun)
  183. print(args)
  184. with open(BACKUPDIR + createName + "/etc-mysql.tar.gz", "a+") as f_stdout, open("/tmp/tar_error.log", "a+") as f_stderr:
  185. p = subprocess.Popen(args, stdout=f_stdout, stderr=f_stderr)
  186. p.communicate()
  187. else:
  188. print("stuff")
  189. #$innobackupex $innobackupex_backup_options --stream=tar $WORKDIR 2> $lockdir/innobackupex-run.log | $COMPRESS $COMPRESS_ARGS -c > $BACKUPDIR/$FILEPREFIX.$FILESUFFIX
  190. #bashCommand = ['ls', '-lah', '/home/backups']
  191. #subprocess.run(bashCommand)
  192. #when the innobackupex compresses the data to workdir add apply log.
  193. #if streaming, no apply log!
  194. #when this is done, compress the directory using COMPRESSION
  195. #add checks if the backup finished fine
  196.  
  197. #sendmail and exit function
  198. def sendMail(msgBody):
  199. sender = 'root@' + HOSTNAME + '.ded.reflected.net'
  200. receivers = ALERTMAIL
  201. msgBody = msgBody
  202.  
  203. #print ("this works")
  204. #message = """From: """ + sender + """\nTo: """ + receivers + """\nSubject: backup failed on """ + HOSTNAME + """\n\n""" + msgBody + """\n"""
  205.  
  206. #its still ugly, but ugly in mutliple lines
  207. message = ("From: " + sender + "\n"
  208. "To:" + receivers + "\n"
  209. "Subject: Backup failed on " + HOSTNAME + "\n\n"
  210. + msgBody + "\n")
  211.  
  212. #smtpObj = smtplib.SMTP('smtp-out.reflected.net')
  213. #smtpObj.sendmail(sender, receivers, message)
  214. print ("Successfully sent email")
  215. sys.exit()
  216.  
  217.  
  218. skipCheck()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement