-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathincremental_backup_example
executable file
·133 lines (108 loc) · 3.9 KB
/
incremental_backup_example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env ruby
require 'config'
require 'lib/device-mapper/dm'
require 'lib/log'
require 'lib/utils'
require 'lib/fs'
require 'lib/git'
require 'lib/status'
require 'lib/tags'
require 'lib/thinp-mixin'
require 'lib/xml_format'
#----------------------------------------------------------------
# This test assumes you have a linux git repo at /root/linux-github
class IncrementalBackup
include ThinpTestMixin
include Tags
include Utils
include XMLFormat
def initialize
setup
end
def show_mappings(ms)
count = 0
ms.each do |m|
if count > 10
puts "and many more ..."
return
end
puts "[#{m.origin_begin} -> #{m.data_begin} * #{m.length}], "
count += 1
end
end
# |pool| should be the pool device, |dev_id| should be the id of the
# thin device that you wish to back up. This device should not be
# changing. Take backups of live thins by taking snapshots. You do
# not have to activate a thin within dm to back it up.
def take_full_backup(pool, dev_id)
puts "Full backup mappings:"
pool.message(0, "reserve_metadata_snap")
held_metadata = read_held_root(pool, @metadata_dev)
# after this call you can't access the metadata, but you can still
# act upon what you read in 'held_metadata'. eg, copy data
pool.message(0, "release_metadata_snap")
# normally you'd copy the data blocks, but we'll just list them.
show_mappings(get_device(held_metadata, 1).mappings)
end
def take_incremental_backup(pool, old_snap, new_snap)
puts "Incremental backup mappings:"
pool.message(0, "reserve_metadata_snap")
held_metadata = read_held_root(pool, @metadata_dev)
pool.message(0, "release_metadata_snap")
# We need to compare the mappings in the old and new snaps ...
old_dev = get_device(held_metadata, old_snap)
new_dev = get_device(held_metadata, new_snap)
old, common, new = compare_devs(old_dev, new_dev)
# now we should back up the mappings unique to the new snap, again
# we'll just display them
show_mappings(new)
end
# Creates a thin, puts a file system on it, then plonks a big git
# repo on that, takes full backup, checks out an old version of the
# git repo, takes an incremental backup. The file system being
# backed up remains mounted an live at all times, except for quick
# suspend/resume cycles when taking snapshots.
def run
setup
# create my standard pool that I use for testing.
with_standard_pool(@size) do |pool|
# create a new thin with dev_id 0, and activate it, |thin| is
# the resultant device.
with_new_thin(pool, @size / 2, 0) do |thin|
puts "formatting ..."
fs = FS::file_system(:ext4, thin)
fs.format
fs.with_mount('./kernel_builds') do
Dir.chdir('./kernel_builds') do
repo = Git.clone('/root/linux-github', 'linux')
Dir.chdir('linux') do
# temporarily suspend the thin device, since we're
# taking a snap of it. This forces an fs sync, among
# other things.
thin.pause do
# We create a snapshot for the initial full backup. This snap
# is kept around to compare for incremental backups.
pool.message(0, "create_snap 1 0")
end
# backup this snapshot
take_full_backup(pool, 1)
# change the data
repo.checkout('v2.6.23')
# take a second snapshot of dev 0
thin.pause do
pool.message(0, "create_snap 2 0")
end
take_incremental_backup(pool, 1, 2)
# The second snap is now what we will compare against in
# future, so we can drop the first.
pool.message(0, 'delete 1')
# ...
end
end
end
end
end
end
end
ib = IncrementalBackup.new
ib.run