snapsync 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/lib/snapsync.rb +1 -0
- data/lib/snapsync/auto_sync.rb +88 -34
- data/lib/snapsync/cleanup.rb +4 -4
- data/lib/snapsync/cli.rb +57 -10
- data/lib/snapsync/default_sync_policy.rb +2 -2
- data/lib/snapsync/local_sync.rb +15 -4
- data/lib/snapsync/local_target.rb +2 -1
- data/lib/snapsync/sync.rb +50 -0
- data/lib/snapsync/sync_all.rb +21 -29
- data/lib/snapsync/sync_last_policy.rb +2 -2
- data/lib/snapsync/timeline_sync_policy.rb +8 -5
- data/lib/snapsync/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f9224076ddb7de222c830cb7ad068742631d46b
|
4
|
+
data.tar.gz: b3ced85dbdc080938b61ec158e8d803f72ebeed1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c26502e714514d0d8f686c62a3d237ded6c85f0cd1a665b2d55d340d357c40aa139a36d5040f371fc719d80aa1c7010654199b6de47b3f2534bae1a3871bb56d
|
7
|
+
data.tar.gz: 0c67490d86f8ad9fc007e88a7c9054883be9f45ee94410ca18dd55dbc6e422620b90f33406693ff44817a13c70f262253cc9283f568035a50b2b029b2ae56aa8
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/lib/snapsync.rb
CHANGED
data/lib/snapsync/auto_sync.rb
CHANGED
@@ -11,13 +11,21 @@ module Snapsync
|
|
11
11
|
attr_reader :targets
|
12
12
|
attr_reader :partitions
|
13
13
|
|
14
|
+
DEFAULT_CONFIG_PATH = Pathname.new('/etc/snapsync.conf')
|
15
|
+
|
16
|
+
def self.load_default
|
17
|
+
result = new
|
18
|
+
result.load_config
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
14
22
|
def initialize(config_dir = SnapperConfig.default_config_dir)
|
15
23
|
@config_dir = config_dir
|
16
24
|
@targets = Hash.new
|
17
25
|
@partitions = PartitionsMonitor.new
|
18
26
|
end
|
19
27
|
|
20
|
-
def load_config(path)
|
28
|
+
def load_config(path = DEFAULT_CONFIG_PATH)
|
21
29
|
conf = YAML.load(path.read) || Array.new
|
22
30
|
parse_config(conf)
|
23
31
|
end
|
@@ -32,7 +40,7 @@ module Snapsync
|
|
32
40
|
end
|
33
41
|
|
34
42
|
def write_config(path)
|
35
|
-
data =
|
43
|
+
data = each_autosync_target.map do |target|
|
36
44
|
Hash['partition_uuid' => target.partition_uuid,
|
37
45
|
'path' => target.path.to_s,
|
38
46
|
'automount' => !!target.automount,
|
@@ -43,13 +51,86 @@ module Snapsync
|
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
46
|
-
|
54
|
+
# Enumerates the declared autosync targets
|
55
|
+
#
|
56
|
+
# @yieldparam [AutoSync] target
|
57
|
+
# @return [void]
|
58
|
+
def each_autosync_target
|
47
59
|
return enum_for(__method__) if !block_given?
|
48
60
|
targets.each_value do |targets|
|
49
61
|
targets.each { |t| yield(t) }
|
50
62
|
end
|
51
63
|
end
|
52
64
|
|
65
|
+
# Enumerates the available autosync targets
|
66
|
+
#
|
67
|
+
# It may mount partitions as needed
|
68
|
+
#
|
69
|
+
# @yieldparam [Pathname] path the path to the target's base dir
|
70
|
+
# (suitable to be processed by e.g. AutoSync)
|
71
|
+
# @yieldparam [AutoSyncTarget] target the target located at 'path'
|
72
|
+
# @return [void]
|
73
|
+
def each_available_autosync_target
|
74
|
+
return enum_for(__method__) if !block_given?
|
75
|
+
partitions.poll
|
76
|
+
|
77
|
+
partitions.known_partitions.each do |uuid, fs|
|
78
|
+
autosync_targets = targets[uuid]
|
79
|
+
next if autosync_targets.empty?
|
80
|
+
|
81
|
+
mp = fs['MountPoints'].first
|
82
|
+
if mp
|
83
|
+
mp = Pathname.new(mp[0..-2].pack("U*"))
|
84
|
+
end
|
85
|
+
|
86
|
+
begin
|
87
|
+
mounted = false
|
88
|
+
|
89
|
+
if !mp
|
90
|
+
if !autosync_targets.any?(&:automount)
|
91
|
+
Snapsync.info "partition #{uuid} is present, but not mounted and automount is false. Ignoring"
|
92
|
+
next
|
93
|
+
end
|
94
|
+
|
95
|
+
Snapsync.info "partition #{uuid} is present, but not mounted, automounting"
|
96
|
+
begin
|
97
|
+
mp = fs.Mount([]).first
|
98
|
+
rescue Exception => e
|
99
|
+
Snapsync.warn "failed to mount, ignoring this target"
|
100
|
+
next
|
101
|
+
end
|
102
|
+
mp = Pathname.new(mp)
|
103
|
+
mounted = true
|
104
|
+
end
|
105
|
+
|
106
|
+
autosync_targets.each do |target|
|
107
|
+
yield(mp + target.path, target)
|
108
|
+
end
|
109
|
+
|
110
|
+
ensure
|
111
|
+
if mounted
|
112
|
+
fs.Unmount([])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Enumerates the available synchronization targets
|
119
|
+
#
|
120
|
+
# It may mount partitions as needed
|
121
|
+
#
|
122
|
+
# @yieldparam [LocalTarget] target the available target
|
123
|
+
# @return [void]
|
124
|
+
def each_available_target
|
125
|
+
return enum_for(__method__) if !block_given?
|
126
|
+
each_available_autosync_target do |path, t|
|
127
|
+
op = SyncAll.new(path, config_dir: config_dir)
|
128
|
+
op.each_target do |target|
|
129
|
+
yield(target)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
53
134
|
def add(target)
|
54
135
|
targets[target.partition_uuid] ||= Array.new
|
55
136
|
targets[target.partition_uuid] << target
|
@@ -67,37 +148,10 @@ module Snapsync
|
|
67
148
|
|
68
149
|
def run(period: 60)
|
69
150
|
while true
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
if !mp
|
75
|
-
if t.automount
|
76
|
-
Snapsync.info "partition #{t.partition_uuid} is present, but not mounted, automounting"
|
77
|
-
begin
|
78
|
-
mp = fs.Mount([]).first
|
79
|
-
rescue Exception => e
|
80
|
-
Snapsync.warn "failed to mount, ignoring this target"
|
81
|
-
next
|
82
|
-
end
|
83
|
-
mp = Pathname.new(mp)
|
84
|
-
mounted = true
|
85
|
-
else
|
86
|
-
Snapsync.info "partition #{t.partition_uuid} is present, but not mounted and automount is false. Ignoring"
|
87
|
-
next
|
88
|
-
end
|
89
|
-
else
|
90
|
-
mp = Pathname.new(mp[0..-2].pack("U*"))
|
91
|
-
end
|
92
|
-
|
93
|
-
full_path = mp + t.path
|
94
|
-
Snapsync.info "sync-all on #{mp + t.path} (partition #{t.partition_uuid})"
|
95
|
-
op = SyncAll.new(mp + t.path, config_dir: config_dir)
|
96
|
-
op.run
|
97
|
-
if mounted
|
98
|
-
fs.Unmount([])
|
99
|
-
end
|
100
|
-
end
|
151
|
+
each_available_autosync_target do |path, t|
|
152
|
+
Snapsync.info "sync-all on #{path} (partition #{t.partition_uuid})"
|
153
|
+
op = SyncAll.new(path, config_dir: config_dir)
|
154
|
+
op.run
|
101
155
|
end
|
102
156
|
Snapsync.info "done all declared autosync partitions, sleeping #{period}s"
|
103
157
|
sleep period
|
data/lib/snapsync/cleanup.rb
CHANGED
@@ -10,7 +10,7 @@ module Snapsync
|
|
10
10
|
|
11
11
|
def cleanup(target, dry_run: false)
|
12
12
|
snapshots = target.each_snapshot.to_a
|
13
|
-
filtered_snapshots = policy.
|
13
|
+
filtered_snapshots = policy.filter_snapshots(snapshots).to_set
|
14
14
|
|
15
15
|
if filtered_snapshots.any? { |s| s.synchronization_point? }
|
16
16
|
raise InvalidPolicy, "#{policy} returned a snapsync synchronization point in its results"
|
@@ -23,9 +23,6 @@ module Snapsync
|
|
23
23
|
last_sync_point = snapshots.
|
24
24
|
sort_by(&:num).reverse.
|
25
25
|
find { |s| s.synchronization_point_for?(target) }
|
26
|
-
if !last_sync_point
|
27
|
-
binding.pry
|
28
|
-
end
|
29
26
|
filtered_snapshots << last_sync_point
|
30
27
|
filtered_snapshots = filtered_snapshots.to_set
|
31
28
|
|
@@ -34,6 +31,9 @@ module Snapsync
|
|
34
31
|
target.delete(s, dry_run: dry_run)
|
35
32
|
end
|
36
33
|
end
|
34
|
+
|
35
|
+
Snapsync.info "Waiting for subvolumes to be deleted"
|
36
|
+
IO.popen(["btrfs", "subvolume", "sync", err: '/dev/null']).read
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/snapsync/cli.rb
CHANGED
@@ -22,15 +22,48 @@ module Snapsync
|
|
22
22
|
Snapsync.logger.level = 'DEBUG'
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
# Resolves a path (or nil) into a list of snapsync targets and
|
27
|
+
# yields them
|
28
|
+
#
|
29
|
+
# @param [String,nil] dir the path the user gave, or nil if all
|
30
|
+
# available auto-sync paths should be processed. If the directory is
|
31
|
+
# a target, it is yield as-is. It can also be the root of a sync-all
|
32
|
+
# target (with proper snapsync target as subdirectories whose name
|
33
|
+
# matches the snapper configurations)
|
34
|
+
#
|
35
|
+
# @yieldparam [LocalTarget] target
|
36
|
+
def each_target(dir = nil)
|
37
|
+
return enum_for(__method__) if !block_given?
|
38
|
+
if dir
|
39
|
+
dir = Pathname.new(dir)
|
40
|
+
begin
|
41
|
+
return yield(LocalTarget.new(dir, create_if_needed: false))
|
42
|
+
rescue LocalTarget::InvalidTargetPath
|
43
|
+
end
|
44
|
+
|
45
|
+
SyncAll.new(dir).each_target do |target|
|
46
|
+
yield(target)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
autosync = AutoSync.load_default
|
50
|
+
autosync.each_available_target do |target|
|
51
|
+
yield(target)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
25
55
|
end
|
26
56
|
|
27
57
|
desc 'sync CONFIG DIR', 'synchronizes the snapper configuration CONFIG with the snapsync target DIR'
|
58
|
+
option :autoclean, type: :boolean, default: nil,
|
59
|
+
desc: 'whether the target should be cleaned of obsolete snapshots',
|
60
|
+
long_desc: "The default is to use the value specified in the target's configuration file. This command line option allows to override the default"
|
28
61
|
def sync(config_name, dir)
|
29
62
|
handle_class_options
|
30
63
|
|
31
64
|
config = config_from_name(config_name)
|
32
65
|
target = LocalTarget.new(Pathname.new(dir))
|
33
|
-
|
66
|
+
Sync.new(config, target, autoclean: options[:autoclean]).run
|
34
67
|
end
|
35
68
|
|
36
69
|
desc 'sync-all DIR', 'synchronizes all snapper configurations into corresponding subdirectories of DIR'
|
@@ -120,7 +153,7 @@ policy for more information
|
|
120
153
|
|
121
154
|
autosync = AutoSync.new
|
122
155
|
autosync.load_config(conf_path)
|
123
|
-
exists = autosync.
|
156
|
+
exists = autosync.each_autosync_target.find do |t|
|
124
157
|
t.partition_uuid == uuid && t.path.cleanpath == relative.cleanpath
|
125
158
|
end
|
126
159
|
if exists
|
@@ -163,15 +196,10 @@ for 10 days). snapsync understands the following period names: year month day ho
|
|
163
196
|
EOD
|
164
197
|
def policy(dir, type, *options)
|
165
198
|
handle_class_options
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
dir.mkpath
|
199
|
+
each_target(dir) do |target|
|
200
|
+
target.change_policy(type, options)
|
201
|
+
target.write_config
|
170
202
|
end
|
171
|
-
|
172
|
-
target = LocalTarget.new(dir)
|
173
|
-
target.change_policy(type, options)
|
174
|
-
target.write_config
|
175
203
|
end
|
176
204
|
|
177
205
|
desc 'destroy DIR', 'destroys a snapsync target'
|
@@ -193,10 +221,29 @@ While it can easily be done manually, this command makes sure that the snapshots
|
|
193
221
|
option :config_file, desc: "path to the config file (defaults to /etc/snapsync.conf)",
|
194
222
|
default: '/etc/snapsync.conf'
|
195
223
|
def auto_sync
|
224
|
+
handle_class_options
|
196
225
|
auto = AutoSync.new(SnapperConfig.default_config_dir)
|
197
226
|
auto.load_config(Pathname.new(options[:config_file]))
|
198
227
|
auto.run
|
199
228
|
end
|
229
|
+
|
230
|
+
desc 'list [DIR]', 'list the snapshots present on DIR. If DIR is omitted, tries to access all targets defined as auto-sync targets'
|
231
|
+
def list(dir = nil)
|
232
|
+
handle_class_options
|
233
|
+
each_target(dir) do |target|
|
234
|
+
puts "== #{target.dir}"
|
235
|
+
puts "UUID: #{target.uuid}"
|
236
|
+
puts "Enabled: #{target.enabled?}"
|
237
|
+
puts "Autoclean: #{target.autoclean?}"
|
238
|
+
print "Policy: "
|
239
|
+
pp target.sync_policy
|
240
|
+
|
241
|
+
puts "Snapshots:"
|
242
|
+
target.each_snapshot do |s|
|
243
|
+
puts " #{s.num} #{s.to_time}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
200
247
|
end
|
201
248
|
end
|
202
249
|
|
@@ -8,7 +8,7 @@ module Snapsync
|
|
8
8
|
#
|
9
9
|
# Synchronization policy objects are used by the synchronization passes to
|
10
10
|
# decide which snapshots to copy and which to not copy. They have to provide
|
11
|
-
# {#
|
11
|
+
# {#filter_snapshots}.
|
12
12
|
#
|
13
13
|
# This default policy is to copy everything but the snapsync-created
|
14
14
|
# synchronization points that are not involving the current target
|
@@ -27,7 +27,7 @@ module Snapsync
|
|
27
27
|
# @param [#uuid] target the target object
|
28
28
|
# @param [Array<Snapshot>] the snapshot candidates
|
29
29
|
# @return [Array<Snapshot>] the snapshots that should be copied
|
30
|
-
def
|
30
|
+
def filter_snapshots(snapshots)
|
31
31
|
# Filter out any snapsync-generated snapshot
|
32
32
|
snapshots.find_all { |s| !s.synchronization_point? }
|
33
33
|
end
|
data/lib/snapsync/local_sync.rb
CHANGED
@@ -179,17 +179,28 @@ module Snapsync
|
|
179
179
|
sync_snapshot ||= create_synchronization_point
|
180
180
|
|
181
181
|
target_snapshots = target.each_snapshot.sort_by(&:num)
|
182
|
+
nums_on_target = target_snapshots.map(&:num).to_set
|
182
183
|
|
183
184
|
last_common_snapshot = source_snapshots.find do |s|
|
184
|
-
|
185
|
+
nums_on_target.include?(s.num)
|
185
186
|
end
|
186
187
|
if !last_common_snapshot
|
187
188
|
Snapsync.warn "no common snapshot found, will have to synchronize the first snapshot fully"
|
188
189
|
end
|
189
190
|
|
190
|
-
|
191
|
-
|
192
|
-
|
191
|
+
# Merge source and target snapshots to find out which are needed on
|
192
|
+
# the target, and then remove the ones that are already present.
|
193
|
+
all_snapshots = source_snapshots.find_all { |s| !nums_on_target.include?(s.num) } +
|
194
|
+
target_snapshots
|
195
|
+
nums_required = target.sync_policy.filter_snapshots(all_snapshots).
|
196
|
+
map(&:num).to_set
|
197
|
+
source_snapshots.each do |src|
|
198
|
+
if !nums_required.include?(src.num)
|
199
|
+
if nums_on_target.include?(src.num)
|
200
|
+
last_common_snapshot = src
|
201
|
+
end
|
202
|
+
next
|
203
|
+
elsif synchronize_snapshot(target.dir + src.num.to_s, src, parent: last_common_snapshot)
|
193
204
|
last_common_snapshot = src
|
194
205
|
end
|
195
206
|
end
|
@@ -30,7 +30,8 @@ module Snapsync
|
|
30
30
|
# Defaults to true
|
31
31
|
def autoclean?; !!@autoclean end
|
32
32
|
|
33
|
-
class
|
33
|
+
class InvalidTargetPath < RuntimeError; end
|
34
|
+
class InvalidUUIDError < InvalidTargetPath; end
|
34
35
|
class NoUUIDError < InvalidUUIDError; end
|
35
36
|
|
36
37
|
def initialize(dir, create_if_needed: true)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Snapsync
|
2
|
+
# Single-target synchronization
|
3
|
+
class Sync
|
4
|
+
attr_reader :config
|
5
|
+
|
6
|
+
attr_reader :target
|
7
|
+
|
8
|
+
def initialize(config, target, autoclean: nil)
|
9
|
+
@config = config
|
10
|
+
@target = target
|
11
|
+
@autoclean =
|
12
|
+
if autoclean.nil? then target.autoclean?
|
13
|
+
else autoclean
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Whether the target should be cleaned after synchronization.
|
18
|
+
#
|
19
|
+
# This is determined either by {#autoclean?} if {.new} was called with
|
20
|
+
# true or false, or by the target's own autoclean flag if {.new} was
|
21
|
+
# called with nil
|
22
|
+
def autoclean?
|
23
|
+
@autoclean
|
24
|
+
end
|
25
|
+
|
26
|
+
# The method that performs synchronization
|
27
|
+
#
|
28
|
+
# One usually wants to call {#run}, which also takes care of running
|
29
|
+
# cleanup if {#autoclean?} is true
|
30
|
+
def sync
|
31
|
+
LocalSync.new(config, target).sync
|
32
|
+
end
|
33
|
+
|
34
|
+
def run
|
35
|
+
sync
|
36
|
+
|
37
|
+
if autoclean?
|
38
|
+
if target.cleanup
|
39
|
+
Snapsync.info "running cleanup for #{target.dir}"
|
40
|
+
target.cleanup.cleanup(target)
|
41
|
+
else
|
42
|
+
Snapsync.info "#{target.sync_policy.class.name} policy set, no cleanup to do for #{target.dir}"
|
43
|
+
end
|
44
|
+
else
|
45
|
+
Snapsync.info "autoclean not set on #{target.dir}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
data/lib/snapsync/sync_all.rb
CHANGED
@@ -23,43 +23,35 @@ module Snapsync
|
|
23
23
|
@autoclean = autoclean
|
24
24
|
end
|
25
25
|
|
26
|
-
# Whether the
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
@autoclean
|
36
|
-
end
|
26
|
+
# Whether the target should be forced to autoclean(true), force to not
|
27
|
+
# run cleanup (false) or use their own config file to decide (nil)
|
28
|
+
#
|
29
|
+
# The default is nil
|
30
|
+
#
|
31
|
+
# @return [Boolean,nil]
|
32
|
+
def autoclean?
|
33
|
+
@autoclean
|
37
34
|
end
|
38
35
|
|
39
|
-
|
36
|
+
# Enumerate the targets available under {#target_dir}
|
37
|
+
def each_target
|
40
38
|
SnapperConfig.each_in_dir(config_dir) do |config|
|
41
39
|
dir = target_dir + config.name
|
42
40
|
if !dir.exist?
|
43
|
-
Snapsync.warn "
|
41
|
+
Snapsync.warn "no directory for configuration #{config.name} in #{target_dir}"
|
44
42
|
else
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
43
|
+
yield(LocalTarget.new(dir))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
else
|
57
|
-
Snapsync.info "#{target.sync_policy.class.name} policy set, no cleanup to do for #{config.name}"
|
58
|
-
end
|
59
|
-
else
|
60
|
-
Snapsync.info "autoclean not set on #{config.name}"
|
61
|
-
end
|
48
|
+
def run
|
49
|
+
each_target do |target|
|
50
|
+
if !target.enabled?
|
51
|
+
Snapsync.warn "not synchronizing to #{target.dir}, it is disabled"
|
52
|
+
next
|
62
53
|
end
|
54
|
+
Sync.new(config, target, autoclean: autoclean?).run
|
63
55
|
end
|
64
56
|
end
|
65
57
|
end
|
@@ -14,8 +14,8 @@ module Snapsync
|
|
14
14
|
pp.text "will keep only the latest snapshot"
|
15
15
|
end
|
16
16
|
|
17
|
-
# (see DefaultSyncPolicy#
|
18
|
-
def
|
17
|
+
# (see DefaultSyncPolicy#filter_snapshots)
|
18
|
+
def filter_snapshots(snapshots)
|
19
19
|
last = snapshots.sort_by(&:num).reverse.
|
20
20
|
find { |s| !s.synchronization_point? }
|
21
21
|
[last]
|
@@ -91,6 +91,8 @@ module Snapsync
|
|
91
91
|
def compute_required_snapshots(target_snapshots)
|
92
92
|
keep_flags = Hash.new { |h,k| h[k] = [false, []] }
|
93
93
|
|
94
|
+
target_snapshots = target_snapshots.sort_by(&:num)
|
95
|
+
|
94
96
|
# Mark all important snapshots as kept
|
95
97
|
target_snapshots.each do |s|
|
96
98
|
if s.user_data['important'] == 'yes'
|
@@ -122,7 +124,7 @@ module Snapsync
|
|
122
124
|
|
123
125
|
# Finally, guard against race conditions. Always keep all snapshots
|
124
126
|
# between the last-to-keep and the last
|
125
|
-
target_snapshots.
|
127
|
+
target_snapshots.reverse.each do |s|
|
126
128
|
break if keep_flags[s.num][0]
|
127
129
|
keep_flags[s.num][0] = true
|
128
130
|
keep_flags[s.num][1] << "last snapshot"
|
@@ -130,9 +132,10 @@ module Snapsync
|
|
130
132
|
keep_flags
|
131
133
|
end
|
132
134
|
|
133
|
-
def
|
135
|
+
def filter_snapshots(snapshots)
|
134
136
|
Snapsync.debug do
|
135
137
|
Snapsync.debug "Filtering snapshots according to timeline"
|
138
|
+
Snapsync.debug "Snapshots: #{snapshots.map(&:num).sort.join(", ")}"
|
136
139
|
timeline.each do |t|
|
137
140
|
Snapsync.debug " #{t}"
|
138
141
|
end
|
@@ -140,10 +143,10 @@ module Snapsync
|
|
140
143
|
end
|
141
144
|
|
142
145
|
default_policy = DefaultSyncPolicy.new
|
143
|
-
|
146
|
+
snapshots = default_policy.filter_snapshots(snapshots)
|
144
147
|
|
145
|
-
keep_flags = compute_required_snapshots(
|
146
|
-
|
148
|
+
keep_flags = compute_required_snapshots(snapshots)
|
149
|
+
snapshots.sort_by(&:num).find_all do |s|
|
147
150
|
keep, reason = keep_flags.fetch(s.num, nil)
|
148
151
|
if keep
|
149
152
|
Snapsync.debug "Timeline: selected snapshot #{s.num} #{s.date.to_time}"
|
data/lib/snapsync/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snapsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Joyeux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logging
|
@@ -186,6 +186,7 @@ files:
|
|
186
186
|
- lib/snapsync/partitions_monitor.rb
|
187
187
|
- lib/snapsync/snapper_config.rb
|
188
188
|
- lib/snapsync/snapshot.rb
|
189
|
+
- lib/snapsync/sync.rb
|
189
190
|
- lib/snapsync/sync_all.rb
|
190
191
|
- lib/snapsync/sync_last_policy.rb
|
191
192
|
- lib/snapsync/test.rb
|