12
12
import tempfile
13
13
import datetime
14
14
import subprocess
15
+ import rotatebackups
15
16
16
17
from operator import itemgetter
17
18
33
34
"""
34
35
class MysqlBackup :
35
36
36
- def __init__ (self , keep = 90 , databases = None , backup_root = None , user = "root" ,
37
+ def __init__ (self , keep = 90 , databases = None , store = None , user = "root" ,
37
38
password = None , host = None ):
38
39
self .host = host
39
40
self .keep = keep
40
41
self .databases = databases
41
- self .backup_root = backup_root
42
+ self .store = store
42
43
self .user = user
43
44
self .password = password
44
45
self .host = host
@@ -65,63 +66,33 @@ def get_databases(self):
65
66
66
67
def backup (self ):
67
68
69
+ padding = len (str (self .keep ))
68
70
backups = []
69
-
70
- # add the backup directories to a list, dirs are the form num.prefix.date
71
- for backup_dump in os .listdir (self .backup_root ):
72
- bparts = backup_dump .split ("." )
73
- if len (bparts ) == 5 and bparts [0 ].isdigit ():
74
- bparts .append (backup_dump )
75
- backups .append (bparts )
76
-
71
+
72
+ # rotate the backups
73
+ rotater = rotatebackups .RotateBackups (self .keep , self .store )
74
+ rotater .rotate_backups ()
75
+
77
76
# get the current date and timestamp and the zero backup name
78
77
now = datetime .datetime .now ()
79
78
tstamp = now .strftime ("%Y%m%d%H%M%S" )
80
79
81
- # only need to process backup directories if we have some
82
- if len (backups ) > 0 :
83
-
84
- # order the backups in the list by reverse number, highest first
85
- backups = sorted (backups , key = itemgetter (0 ), reverse = True )
86
- logging .debug (backups )
87
-
88
- # perform shifting and processing on the backup directories
89
- for bparts in backups :
90
-
91
- # remove backups >= number to keep
92
- bnum = int (bparts [0 ])
93
- if bnum >= self .keep :
94
- bpath = self .backup_root + os .sep + bparts [- 1 ]
95
- logging .debug (["rm" , "-f" , bpath ])
96
- self .run_command (["rm" , "-f" , bpath ])
97
- else :
98
-
99
- # above 0 gets shifted to one number higher and moved, 0 gets hardlink
100
- # copied to 1
101
- old_bpath = self .backup_root + os .sep + bparts [- 1 ]
102
- num_prefix = str (bnum + 1 ).zfill (4 )
103
- new_backup_name = string .join ([num_prefix ] + bparts [1 :5 ], "." )
104
- new_bpath = self .backup_root + os .sep + new_backup_name
105
- if bnum >= 0 :
106
- logging .debug ([bnum , "mv" , old_bpath , new_bpath ])
107
- self .run_command (["mv" , old_bpath , new_bpath ])
108
-
109
80
databases = self .get_databases ()
110
81
skip = ["information_schema" , "performance_schema" , "test" ]
111
- for database in databases :
112
- if database in skip :
82
+ for db in databases :
83
+ if db in skip :
113
84
continue
114
85
115
- dbbackup_name = string .join (["0000" , database , tstamp , "sql" ], "." )
116
- dbbackup_path = self .backup_root + os .sep + dbbackup_name
86
+ dbbackup_name = string .join (["" . zfill ( padding ), tstamp , db , "sql" ], "." )
87
+ dbbackup_path = self .store + os .sep + dbbackup_name
117
88
118
89
dump_cmd = "mysqldump -u " + self .user
119
90
if self .host != None :
120
91
dump_cmd += " -h " + "'" + self .host + "'"
121
92
if self .password != None :
122
93
dump_cmd += " -p" + self .password
123
- dump_cmd += " -e --opt -c " + database + " | gzip > " + dbbackup_path + ".gz"
124
- logging .info ("Dump db, %s to %s." % (database , dbbackup_path ))
94
+ dump_cmd += " -e --opt -c " + db + " | gzip > " + dbbackup_path + ".gz"
95
+ logging .info ("Dump db, %s to %s." % (db , dbbackup_path ))
125
96
os .popen (dump_cmd )
126
97
127
98
"""
@@ -151,13 +122,13 @@ def main(argv):
151
122
user = None
152
123
password = None
153
124
host = None
154
- backup_root = None
125
+ store = None
155
126
156
127
try :
157
128
158
129
# process the command line options
159
- opts , args = getopt .getopt (argv , "hn:k:d:b :u:p:s:" , ["help" , "keep=" ,
160
- "databases=" , "backup-root =" , "user=" , "password=" , "host=" ])
130
+ opts , args = getopt .getopt (argv , "hn:k:d:t :u:p:s:" , ["help" , "keep=" ,
131
+ "databases=" , "store =" , "user=" , "password=" , "host=" ])
161
132
162
133
# if no arguments print usage
163
134
if len (argv ) == 0 :
@@ -174,8 +145,8 @@ def main(argv):
174
145
keep = int (arg )
175
146
elif opt in ("-d" , "--databases" ):
176
147
server = arg
177
- elif opt in ("-b " , "--backup-root " ):
178
- backup_root = arg
148
+ elif opt in ("-t " , "--store " ):
149
+ store = arg
179
150
elif opt in ("-u" , "--user" ):
180
151
user = arg
181
152
elif opt in ("-p" , "--password" ):
@@ -190,8 +161,8 @@ def main(argv):
190
161
sys .exit (errno .EIO )
191
162
192
163
# check options are set correctly
193
- if user == None or backup_root == None :
194
- logging .warning ("Backup root (-b) is required" )
164
+ if user == None or store == None :
165
+ logging .warning ("Backup store directory (-t) and user (-u) are required" )
195
166
usage ()
196
167
sys .exit (errno .EPERM )
197
168
@@ -210,14 +181,14 @@ def main(argv):
210
181
f .close ()
211
182
212
183
# create the backup object and call its backup method
213
- mysql_backup = MysqlBackup (keep , databases , backup_root , user , password , host )
184
+ mysql_backup = MysqlBackup (keep , databases , store , user , password , host )
214
185
mysql_backup .backup ()
215
186
216
187
except (Exception ):
217
188
logging .exception ("Mysql backups failed." )
218
189
finally :
219
190
os .remove (pid_file )
220
191
221
- # if we are running the script from the command line
192
+ # if we are running the script from the command line, run the main function
222
193
if __name__ == "__main__" :
223
194
main (sys .argv [1 :])
0 commit comments