Merge lp:~longbow/kewpie/xb_manager into lp:kewpie

Proposed by Valentine Gostev
Status: Merged
Merged at revision: 126
Proposed branch: lp:~longbow/kewpie/xb_manager
Merge into: lp:kewpie
Diff against target: 335 lines (+272/-2)
5 files modified
kewpie.py (+4/-1)
lib/test_mgmt/execution_management.py (+2/-1)
lib/test_mgmt/test_execution.py (+1/-0)
lib/util/xb_manager.py (+203/-0)
percona_tests/xbm/xb_incremental_test.py (+62/-0)
To merge this branch: bzr merge lp:~longbow/kewpie/xb_manager
Reviewer Review Type Date Requested Status
Valentine Gostev Approve
Review via email: mp+109727@code.launchpad.net

Description of the change

Added xtrabackup management library and a sample test in 'xmb' suite

To post a comment you must log in.
Revision history for this message
Valentine Gostev (longbow) :
review: Approve
Revision history for this message
Patrick Crews (patrick-crews) wrote :

You rock! Glad to see you are still finding use for the tools : )
I'm currently working on some updates myself...just been locked in a basement for a few weeks ; )

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'kewpie.py'
--- kewpie.py 2012-02-20 20:49:50 +0000
+++ kewpie.py 2012-06-11 20:30:31 +0000
@@ -44,6 +44,7 @@
44from lib.sys_mgmt.system_management import systemManager44from lib.sys_mgmt.system_management import systemManager
45from lib.test_mgmt.execution_management import executionManager45from lib.test_mgmt.execution_management import executionManager
46from lib.opts.matrix_manager import matrixManager46from lib.opts.matrix_manager import matrixManager
47from lib.util.xb_manager import xtrabackupManager
4748
48# functions49# functions
49def handle_sys_config(input_args, defaults):50def handle_sys_config(input_args, defaults):
@@ -93,6 +94,8 @@
93 # Create our server_manager94 # Create our server_manager
94 server_manager = serverManager(system_manager, variables)95 server_manager = serverManager(system_manager, variables)
9596
97 # Create XtraBackup manager
98 xtrabackup_manager = xtrabackupManager(system_manager, server_manager, variables)
96 # Get our mode-specific test_manager and test_executor99 # Get our mode-specific test_manager and test_executor
97 (test_manager,test_executor) = handle_mode(variables, system_manager)100 (test_manager,test_executor) = handle_mode(variables, system_manager)
98101
@@ -102,7 +105,7 @@
102 # Initialize test execution manager105 # Initialize test execution manager
103 execution_manager = executionManager(server_manager, system_manager106 execution_manager = executionManager(server_manager, system_manager
104 , test_manager, test_executor107 , test_manager, test_executor
105 , variables, matrix_manager)108 , variables, matrix_manager, xtrabackup_manager)
106109
107 # Execute our tests!110 # Execute our tests!
108 execution_manager.execute_tests()111 execution_manager.execute_tests()
109112
=== modified file 'lib/test_mgmt/execution_management.py'
--- lib/test_mgmt/execution_management.py 2012-02-20 20:49:50 +0000
+++ lib/test_mgmt/execution_management.py 2012-06-11 20:30:31 +0000
@@ -39,11 +39,12 @@
39 """39 """
4040
41 def __init__(self, server_manager, system_manager, test_manager41 def __init__(self, server_manager, system_manager, test_manager
42 , executor_type, variables, matrix_manager):42 , executor_type, variables, matrix_manager, xtrabackup_manager):
4343
44 self.server_manager = server_manager44 self.server_manager = server_manager
45 self.system_manager = system_manager45 self.system_manager = system_manager
46 self.matrix_manager = matrix_manager46 self.matrix_manager = matrix_manager
47 self.xtrabackup_manager = xtrabackup_manager
47 self.logging = system_manager.logging48 self.logging = system_manager.logging
48 self.test_manager = test_manager49 self.test_manager = test_manager
49 if variables['verbose']:50 if variables['verbose']:
5051
=== modified file 'lib/test_mgmt/test_execution.py'
--- lib/test_mgmt/test_execution.py 2012-02-20 20:49:50 +0000
+++ lib/test_mgmt/test_execution.py 2012-06-11 20:30:31 +0000
@@ -58,6 +58,7 @@
58 self.server_manager = self.execution_manager.server_manager58 self.server_manager = self.execution_manager.server_manager
59 self.time_manager = self.system_manager.time_manager59 self.time_manager = self.system_manager.time_manager
60 self.matrix_manager = self.execution_manager.matrix_manager60 self.matrix_manager = self.execution_manager.matrix_manager
61 self.xtrabackup_manager = self.execution_manager.xtrabackup_manager
61 self.name = name62 self.name = name
62 self.working_environment = {} # we pass env dict to define what we need63 self.working_environment = {} # we pass env dict to define what we need
63 self.dirset = { self.name : { 'log': None } }64 self.dirset = { self.name : { 'log': None } }
6465
=== added file 'lib/util/xb_manager.py'
--- lib/util/xb_manager.py 1970-01-01 00:00:00 +0000
+++ lib/util/xb_manager.py 2012-06-11 20:30:31 +0000
@@ -0,0 +1,203 @@
1#! /usr/bin/env python
2# -*- mode: python; indent-tabs-mode: nil; -*-
3# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4#
5# Copyright (C) 2011-2012 Patrick Crews, Valentine Gostev
6#
7#
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.
12#
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.
17#
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
21
22import os
23import shutil
24import re
25import subprocess
26
27""" Xtrabackup manager class handles all mysql backup operations
28 it creates a backup object from server objects
29"""
30
31class xtrabackupManager:
32 def __init__(self, server_manager, system_manager, variables):
33 self.system_manager = system_manager
34 self.code_manager = system_manager.code_manager
35 self.server_manager = server_manager
36 self.env_manager = system_manager.env_manager
37 self.logging = system_manager.logging
38 self.xb_bin_path = variables['xtrabackuppath']
39 self.ib_bin_path = variables['innobackupexpath']
40 self.backup_dir = os.path.join(variables['workdir'],'backups')
41 if not os.path.isdir(self.backup_dir):
42 os.makedirs(self.backup_dir)
43
44 """ clean_dir method is used to wipe out data from server object's
45 data directory in order to restore a prepared backup
46 Usage clean_dir()
47 """
48 def clean_dir(self,path):
49 for top,dirs,files in os.walk(path):
50 for file in files:
51 os.unlink(os.path.join(top,file))
52 for dir in dirs:
53 shutil.rmtree(os.path.join(top,dir))
54
55 """ alloc_dir returns a directory name for next backup
56 """
57 def alloc_dir(self, topdir, dir_pattern='backup'):
58 dir_pattern_obj = '%s(\\d+)' %dir_pattern
59 dir_pattern_obj = re.compile(dir_pattern_obj)
60 dir_list = [list(dirs)[1] for dirs in os.walk(topdir) if list(dirs)[0] == topdir][0]
61 dir_list = [b for b in dir_list if dir_pattern_obj.match(b)]
62 if not dir_list:
63 dir_suffix = '0'
64 else:
65 dir_suffix = str(max([int(re.split(dir_pattern,b)[1]) for b in dir_list])+1)
66
67 return '%s%s' %(dir_pattern,dir_suffix)
68
69 """ execute_cmd executes backup program to create backup object
70 """
71 def execute_cmd(self, cmd, exec_path, outfile_path):
72 outfile = open(outfile_path,'w')
73 cmd_subproc = subprocess.Popen( cmd
74 , cwd = exec_path
75 , shell=True
76 , stdout = outfile
77 , stderr = subprocess.STDOUT
78 )
79 cmd_subproc.wait()
80 retcode = cmd_subproc.returncode
81 outfile.close
82 in_file = open(outfile_path,'r')
83 output = ''.join(in_file.readlines())
84 return retcode,output
85
86 """ method creates full backup from server object
87 new_backup_object = backup_full(server_object)
88 """
89 def backup_full(self,server_object):
90 self.datadir = server_object.datadir
91 self.ib_bin = self.ib_bin_path
92 self.xb_bin = self.xb_bin_path
93 self.b_root_dir = self.backup_dir
94 allocated_dir = self.alloc_dir(self.b_root_dir)
95 self.b_path = os.path.join(self.b_root_dir, allocated_dir)
96 temp_log = os.path.join(self.b_root_dir, '%s.log' %allocated_dir)
97 self.xb_log = os.path.join(self.b_path, '%s.log' %allocated_dir)
98 cmd = [self.ib_bin
99 , "--defaults-file=%s" %server_object.cnf_file
100 , "--no-timestamp"
101 , "--user=root"
102 , "--port=%d" %server_object.master_port
103 , "--host=127.0.0.1"
104 , "--ibbackup=%s" %self.xb_bin
105 , self.b_path
106 ]
107 cmd = " ".join(cmd)
108 self.retcode, self.output = self.execute_cmd(cmd, self.b_root_dir, temp_log)
109 shutil.move(temp_log, self.xb_log)
110 self.status = 'full-backup'
111 return self
112
113 """ Create incremental backup from full backup and server objects
114 Usage: incremental_backup_object = backup_inc(server_obj,previous_backup_object)
115 """
116 def backup_inc(self,server_object,backup_object):
117 self.ib_bin = self.ib_bin_path
118 self.xb_bin = self.xb_bin_path
119 self.b_root_dir = self.backup_dir
120 allocated_dir = self.alloc_dir(self.b_root_dir)
121 self.b_path = os.path.join(self.b_root_dir, allocated_dir)
122 temp_log = os.path.join(self.b_root_dir, '%s.log' %allocated_dir)
123 self.xb_log = os.path.join(self.b_path, '%s.log' %allocated_dir)
124 cmd = [self.ib_bin
125 , '--defualts-file=%s' %server_object.cnf_file
126 , '--no-timestamp'
127 , '--user=root'
128 , '--port=%d' %server_object.master_port
129 , '--host=127.0.0.1'
130 , '--ibbackup=%s' %self.xb_bin
131 , '--incremental'
132 , '--incremental-basedir=%s' %backup_object.b_path
133 , self.b_path
134 ]
135 cmd = " ".join(cmd)
136 self.retcode, self.output = self.execute_cmd(cmd, self.b_root_dir, temp_log)
137 shutil.move(temp_log, self.xb_log)
138 self.status = 'inc-backup'
139 return self
140
141 """ Method to prepare a backup
142 Usage prepare(unprepared_backup_object)
143 """
144 def prepare(self,backup_object,rollback=True):
145 if rollback:
146 rollback = ''
147 else:
148 rollback = '--redo-only'
149
150 cmd = [backup_object.ib_bin
151 , "--apply-log"
152 , " %s" %rollback
153 , "--ibbackup=%s" %backup_object.xb_bin
154 , backup_object.b_path
155 ]
156 cmd = " ".join(cmd)
157 temp_log = os.path.join(backup_object.b_path, self.alloc_dir(backup_object.b_path,dir_pattern='prepare'))
158 retcode, output = self.execute_cmd(cmd, backup_object.b_path, temp_log)
159 if rollback and retcode==0:
160 backup_object.status = 'prepared-redo-only'
161 elif not rollback and retcode==0:
162 backup_object.status = 'prepared'
163 else:
164 backup_object.status = 'prepare-failed'
165
166 return retcode, output
167
168 """ Method restores server_object's data from backup
169 If backup is not ready for restore an appropriate error
170 message will be returned.
171 Usage: restore(prepared_backup_object,server_object)
172 """
173 def restore(self,backup_object,server_object):
174 if backup_object.status=='prepared-redo-only' or backup_object.status=='prepared':
175 pass
176 elif backup_object.status=='full-backup':
177 retcode = 1
178 output = 'Backup has to be prepared before restore!\n'
179 return retcode, output
180 elif backup_object.status=='inc-backup':
181 retcode = 1
182 output = 'You have to apply incrementals to full backup to restore it!\n'
183 elif backup_object.status=='prepare-failed':
184 retcode = 1
185 output = 'Backup failed to prepare, see prepare log for details.\n'
186 else:
187 retcode = 1
188 output = 'CRITICAL ERROR: Unknown backup status!\n'
189
190 cmd = [backup_object.ib_bin
191 , "--defaults-file=%s" %server_object.cnf_file
192 , "--copy-back"
193 , "--ibbackup=%s" %backup_object.xb_bin
194 , backup_object.b_path
195 ]
196 cmd = " ".join(cmd)
197 server_object.stop()
198 self.clean_dir(server_object.datadir)
199 temp_log = os.path.join(backup_object.b_path, self.alloc_dir(backup_object.b_path,dir_pattern='restore'))
200 retcode, output = self.execute_cmd(cmd, backup_object.b_path, temp_log)
201 server_object.start()
202 return retcode, output
203
0204
=== added directory 'percona_tests/xbm'
=== added file 'percona_tests/xbm/xb_incremental_test.py'
--- percona_tests/xbm/xb_incremental_test.py 1970-01-01 00:00:00 +0000
+++ percona_tests/xbm/xb_incremental_test.py 2012-06-11 20:30:31 +0000
@@ -0,0 +1,62 @@
1#! /usr/bin/env python
2# -*- mode: python; indent-tabs-mode: nil; -*-
3# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4#
5# Copyright (C) 2011 Patrick Crews
6#
7#
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.
12#
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.
17#
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
21
22import os
23import shutil
24
25from lib.util.mysqlBaseTestCase import mysqlBaseTestCase
26
27server_requirements = [['--innodb-file-per-table'],['--innodb-file-per-table']]
28servers = []
29server_manager = None
30test_executor = None
31# we explicitly use the --no-timestamp option
32# here. We will be using a generic / vanilla backup dir
33backup_path = None
34
35class basicTest(mysqlBaseTestCase):
36
37
38 def test_ib_incremental(self):
39 master_server = servers[0]
40 slave_server = servers[1]
41 self.servers = servers
42 logging = test_executor.logging
43 xb_manager = test_executor.xtrabackup_manager
44 # backup0 = xb_manager.backup_full(master_server)
45 # xb_manager.prepare(backup0)
46 # xb_manager.restore(backup0,master_server)
47 randgen_manager = test_executor.randgen_manager
48 randgen_manager.create_test_bed(master_server, optional_parameters)
49 backup0 = xb_manager.backup_full(master_server)
50 load0 = randgen_manager.create_load(master_server, runtime_options)
51 load0.start()
52 backup1 = xb_manager.backup_inc(master_server, backup0)
53 xb_manager.prepare(backup0,rollback=False)
54 xb_manager.prepare_inc(backup0,backup1)
55 xb_manager.restore(slave_server)
56 slave_server.start_repl(master_server)
57 load0.wait()
58 compare_checksums(master_server,slave_server,db1="test",db2="test2")
59
60
61
62

Subscribers

People subscribed via source and target branches