2
# -*- mode: python; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5
# Copyright (C) 2011 Patrick Crews
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, write to the Free Software
20
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
from lib.util.mysqlBaseTestCase import mysqlBaseTestCase
27
server_requirements = [['--innodb-file-per-table --innodb_file_format=Barracuda']]
31
# we explicitly use the --no-timestamp option
32
# here. We will be using a generic / vanilla backup dir
35
class basicTest(mysqlBaseTestCase):
38
master_server = servers[0] # assumption that this is 'master'
39
backup_path = os.path.join(master_server.vardir, 'backup')
41
for del_path in [backup_path]:
42
if os.path.exists(del_path):
43
shutil.rmtree(del_path)
45
def create_test_table(self, table_name, server):
46
queries = ["DROP TABLE IF EXISTS %s" %(table_name)
48
"(`a` int(11) DEFAULT NULL, "
49
"`number` int(11) DEFAULT NULL) "
50
" ENGINE=InnoDB DEFAULT CHARSET=latin1"
54
retcode, result = self.execute_queries(queries, server)
55
self.assertEqual(retcode, 0, msg = result)
57
def load_table(self, table_name, row_count, server):
59
for i in range(row_count):
60
queries.append("INSERT INTO %s VALUES (%d, %d)" %(table_name,i, row_count))
61
retcode, result = self.execute_queries(queries, server)
62
self.assertEqual(retcode, 0, msg=result)
65
def test_xb_export(self):
66
self.servers = servers
67
logging = test_executor.logging
68
server_comment = servers[0].code_tree.server_compile_comment
69
if server_comment and "with XtraDB" not in server_comment:
70
logging.warning("Test requires XtraDB, skipping test...")
73
innobackupex = test_executor.system_manager.innobackupex_path
74
xtrabackup = test_executor.system_manager.xtrabackup_path
75
master_server = servers[0] # assumption that this is 'master'
76
backup_path = os.path.join(master_server.vardir, 'backup')
77
output_path = os.path.join(master_server.vardir, 'innobackupex.out')
78
exec_path = os.path.dirname(innobackupex)
83
# This is a bit hacky. We have a version-dependent server
84
# option and no clean mechanism for doing this at test-collection
86
import_option = "--innodb_expand_import=1"
87
if master_server.version.startswith("5.5"):
88
import_option = "--innodb_import_table_from_xtrabackup=1"
89
master_server.server_options.append(import_option)
93
# populate our server with a test bed
94
self.create_test_table(table_name, master_server)
96
self.load_table(table_name, row_count, master_server)
100
, "--defaults-file=%s" %master_server.cnf_file
101
, "--datadir=%s" %master_server.datadir
103
, "--target-dir=%s" %backup_path
106
retcode, output = self.execute_cmd(cmd, output_path, exec_path, True)
107
self.assertTrue(retcode==0,output)
111
self.load_table(table_name, row_count, master_server)
113
# Get a checksum for our table
114
query = "CHECKSUM TABLE %s" %table_name
115
retcode, checksum1 = self.execute_query(query, master_server)
116
self.assertEqual(retcode, 0, msg=checksum1)
117
logging.test_debug("Checksum1: %s" %checksum1)
119
# Reset the server to treat it as the 'importing' server
120
# We clean the datadir + create a table w/ similar
122
# TODO: see how things fail if we skip / mess up this step
124
master_server.restore_snapshot()
125
master_server.start()
127
# recreate the table:
128
self.create_test_table(table_name, master_server)
129
logging.test_debug("Server reinitialized")
131
# discard the tablespace
132
query = "ALTER TABLE %s DISCARD TABLESPACE" %(table_name)
133
retcode, result = self.execute_query(query, master_server)
134
self.assertEqual(retcode,0,msg=result)
136
# prepare our main backup
137
# Test the with innodb_file_per_table=0 --export bails out with an error
141
, "--datadir=%s" %master_server.datadir
142
, "--use-memory=500M"
143
, "--target-dir=%s" %backup_path
145
, "--innodb-file-per-table=0"
148
retcode, output = self.execute_cmd(cmd, output_path, exec_path, True)
149
self.assertEqual(retcode,1,output)
151
# prepare our main backup
154
, "--datadir=%s" %master_server.datadir
155
, "--use-memory=500M"
156
, "--target-dir=%s" %backup_path
158
, "--innodb-file-per-table=1"
161
retcode, output = self.execute_cmd(cmd, output_path, exec_path, True)
162
self.assertEqual(retcode,0,output)
164
# copy our data files back
165
db_path = os.path.join(backup_path,schema_name)
166
for bkp_file in os.listdir(db_path):
167
if bkp_file.startswith('test'):
168
shutil.copy(os.path.join(db_path,bkp_file)
169
,os.path.join(master_server.datadir,schema_name)
172
# import the tablespace
173
query = "ALTER TABLE %s IMPORT TABLESPACE" %(table_name)
174
retcode, result = self.execute_query(query, master_server)
175
self.assertEqual(retcode,0,msg=result)
176
logging.test_debug("Tablespace imported...")
178
# Tablespace import is asynchronous, so shutdown the server to have
179
# consistent backup results. Otherwise we risk ending up with no test.ibd
180
# in the backup in case importing has not finished before taking backup
182
master_server.start()
183
self.assertTrue(master_server.status==1, 'Server failed restart from restored datadir...')
185
query="SELECT COUNT(*) FROM %s" %(table_name)
186
retcode, result = self.execute_query(query, master_server)
187
self.assertEqual(retcode,0,result)
188
expected_result = ((100L,),)
189
self.assertEqual(expected_result, result, msg = "%s || %s" %(expected_result, result))
191
query = "SHOW CREATE TABLE %s" %(table_name)
192
retcode, result = self.execute_query(query, master_server)
193
self.assertEqual(retcode,0,result)
194
expected_result = (('test', 'CREATE TABLE `test` (\n `a` int(11) DEFAULT NULL,\n `number` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=latin1'),)
195
self.assertEqual(expected_result, result, msg = "%s || %s" %(expected_result, result))
197
# Get a checksum for our table
198
query = "CHECKSUM TABLE %s" %table_name
199
retcode, checksum2 = self.execute_query(query, master_server)
200
self.assertEqual(retcode, 0, msg=checksum2)
201
logging.test_debug("Checksum2: %s" %checksum2)
202
if checksum1 != checksum2:
203
logging.warning("Initial and exported/restored checksums do not match!")
204
logging.warning("Checksum1: %s" %checksum1)
205
logging.warning("Checksum2: %s" %checksum2)
206
#self.assertEqual(checksum1,checksum2,msg="%s || %s" %(checksum1,checksum2))
208
# create a dir to hold the new backup
209
backup_path = os.path.join(backup_path,'new_backup')
210
# take a backup of the imported table
212
, "--defaults-file=%s" %master_server.cnf_file
213
, "--datadir=%s" %master_server.datadir
215
, "--target-dir=%s" %backup_path
218
retcode, output = self.execute_cmd(cmd, output_path, exec_path, True)
219
self.assertTrue(retcode==0,output)
221
# Clear our table so we know the backup restored
222
for del_table in [table_name]:
223
query = "DELETE FROM %s" %del_table
224
retcode, result = self.execute_query(query,master_server)
225
self.assertEqual(retcode, 0, result)
227
# shutdown our server
230
# prepare our main backup
234
, "--datadir=%s" %master_server.datadir
235
, "--use-memory=500M"
236
, "--target-dir=%s" %backup_path
239
retcode, output = self.execute_cmd(cmd, output_path, exec_path, True)
240
self.assertTrue(retcode==0,output)
242
# do final prepare on main backup
245
, "--datadir=%s" %master_server.datadir
246
, "--use-memory=500M"
247
, "--target-dir=%s" %backup_path
250
retcode, output = self.execute_cmd(cmd, output_path, exec_path, True)
251
self.assertTrue(retcode==0,output)
253
# copy our data files back
254
for root, dirs, files in os.walk(backup_path):
256
file_info = root.split(backup_path)[1]
257
for file_name in files:
258
# We do a quick check to make sure
259
# no names start with '/' as os.path
260
# throws a hissy when it sees such things
261
if file_info.startswith('/'):
262
file_info = file_info[1:]
263
if file_name.startswith('/'):
264
file_name = file_name[1:]
265
to_path = os.path.join(master_server.datadir
268
new_dir = os.path.dirname(to_path)
270
if not os.path.exists(new_dir):
273
logging.error("Could not create directory: %s | %s" %(new_dir, e))
275
shutil.copy(os.path.join(root,file_name),to_path)
277
logging.error( "ERROR: Could not copy file: %s | %s" %(file_name, e))
279
# restart server (and ensure it doesn't crash)
280
master_server.start()
281
self.assertTrue(master_server.status==1, 'Server failed restart from restored datadir...')
283
# Get a checksum for our table
284
query = "CHECKSUM TABLE %s" %table_name
285
retcode, checksum3 = self.execute_query(query, master_server)
286
self.assertEqual(retcode, 0, msg=checksum3)
287
logging.test_debug("Checksum3: %s" %checksum3)
288
self.assertEqual(checksum2,checksum3,msg="%s || %s" %(checksum2,checksum3))
293
server_manager.reset_servers(test_executor.name)