snap-ebs 0.0.22 → 0.0.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/plugins/mongo_plugin.rb +3 -1
- data/lib/snap_ebs/options.rb +18 -1
- data/lib/snap_ebs/snapshotter.rb +61 -25
- data/lib/snap_ebs/version.rb +1 -1
- data/lib/snap_ebs.rb +11 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62c41bd18a3cbb71c5371a5173dea68f58d36424
|
4
|
+
data.tar.gz: f6746f30e90bb026ecb23bcdfdbc84fce247b25d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4dab5f0340738c8bc137fd46b03b84fafee0281f40ffd6078fbc48e2ffe236916caf6a5fa06c45376b4ddb98dcf0cbf37b8a9eb79916d47343c70dab57e0af1a
|
7
|
+
data.tar.gz: af3ae2147a22fcac3759934a2f4b10e0d56dd6dde19bb5b9e6c0a9f64f0bd2e9ab6be4014f175e4b55a0a86a7cb03eabd89c1e7c782784801dc1f5ec2d95e9db
|
data/lib/plugins/mongo_plugin.rb
CHANGED
@@ -37,7 +37,7 @@ class SnapEbs::Plugin::MongoPlugin < SnapEbs::Plugin
|
|
37
37
|
def before
|
38
38
|
require 'mongo'
|
39
39
|
Mongo::Logger.logger = logger
|
40
|
-
return unless safe_to_operate?
|
40
|
+
return false unless safe_to_operate?
|
41
41
|
|
42
42
|
if wired_tiger?
|
43
43
|
logger.info "Wired Tiger storage engine detected"
|
@@ -46,6 +46,8 @@ class SnapEbs::Plugin::MongoPlugin < SnapEbs::Plugin
|
|
46
46
|
logger.info "MMAPv1 storage engine detected"
|
47
47
|
carefully('lock mongo') { lock_mongo }
|
48
48
|
end
|
49
|
+
|
50
|
+
true
|
49
51
|
end
|
50
52
|
|
51
53
|
def after
|
data/lib/snap_ebs/options.rb
CHANGED
@@ -43,6 +43,14 @@ class SnapEbs
|
|
43
43
|
options.directory = d
|
44
44
|
end
|
45
45
|
|
46
|
+
o.on("-r", "--retry-count COUNT", "Retry AWS API calls COUNT times before failing (default: #{options.retry_count})") do |count|
|
47
|
+
options.retry_count = count
|
48
|
+
end
|
49
|
+
|
50
|
+
o.on("-i", "--retry-interval SECONDS", "Wait the given number of seconds between API retries (default: #{options.retry_interval})") do |seconds|
|
51
|
+
options.retry_interval = seconds.to_i
|
52
|
+
end
|
53
|
+
|
46
54
|
o.on("", "--version", "Show version and exit") do |d|
|
47
55
|
puts "snap-ebs v#{::SnapEbs::VERSION}"
|
48
56
|
exit 0
|
@@ -58,6 +66,15 @@ class SnapEbs
|
|
58
66
|
|
59
67
|
# Get the root `options` object, and instance of OpenStruct
|
60
68
|
def options
|
61
|
-
@options ||= OpenStruct.new
|
69
|
+
@options ||= OpenStruct.new(default_options)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def default_options
|
75
|
+
{
|
76
|
+
retry_count: 100,
|
77
|
+
retry_interval: 10
|
78
|
+
}
|
62
79
|
end
|
63
80
|
end
|
data/lib/snap_ebs/snapshotter.rb
CHANGED
@@ -8,43 +8,40 @@ module SnapEbs::Snapshotter
|
|
8
8
|
# Takes snapshots of attached volumes (optionally filtering by volumes
|
9
9
|
# mounted to the given directories)
|
10
10
|
def take_snapshots
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
snapshot.save
|
23
|
-
snapshot
|
24
|
-
rescue StandardError => e
|
25
|
-
logger.warn "Received error while snapping #{vol.id}:"
|
26
|
-
logger.warn e
|
27
|
-
end
|
28
|
-
fs_unfreeze dir if options[:fs_freeze]
|
11
|
+
snapped_volumes = []
|
12
|
+
logger.debug "Issuing sync command"
|
13
|
+
system 'sync'
|
14
|
+
|
15
|
+
logger.debug "Walking attached volumes"
|
16
|
+
attached_volumes.each do |vol|
|
17
|
+
dir = device_to_directory device_name vol
|
18
|
+
logger.debug "Found #{vol.id} mounted on #{dir}"
|
19
|
+
unless should_snap vol
|
20
|
+
logger.debug "Skipping #{vol.id}"
|
21
|
+
next
|
29
22
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
|
24
|
+
fs_freeze dir if options[:fs_freeze]
|
25
|
+
take_snapshot vol
|
26
|
+
snapped_volumes.push vol
|
27
|
+
fs_unfreeze dir if options[:fs_freeze]
|
33
28
|
end
|
29
|
+
snapped_volumes
|
34
30
|
end
|
35
31
|
|
36
32
|
# Get the Fog compute object. When `--mock` is given, `Fog.mock!` is called
|
37
|
-
# and
|
33
|
+
# and information normally auto-detected from AWS is injected with dummy
|
38
34
|
# values to circumvent the lazy loaders.
|
39
35
|
def compute
|
40
36
|
require 'fog/aws'
|
37
|
+
logger.debug "Mock: #{options[:mock]}"
|
41
38
|
if options[:mock]
|
42
39
|
Fog.mock!
|
43
40
|
@region = 'us-east-1'
|
44
|
-
@instance_id = 'i-deadbeef'
|
45
41
|
@instance_name = 'totally-not-the-cia'
|
46
42
|
end
|
47
43
|
|
44
|
+
logger.debug "AWS region auto-detected as #{region}"
|
48
45
|
@compute ||= Fog::Compute.new({
|
49
46
|
:aws_access_key_id => access_key,
|
50
47
|
:aws_secret_access_key => secret_key,
|
@@ -55,8 +52,22 @@ module SnapEbs::Snapshotter
|
|
55
52
|
|
56
53
|
private
|
57
54
|
|
55
|
+
def take_snapshot vol
|
56
|
+
logger.debug "Snapping #{vol.id}"
|
57
|
+
snapshot = compute.snapshots.new
|
58
|
+
snapshot.volume_id = vol.id
|
59
|
+
snapshot.description = snapshot_name(vol)
|
60
|
+
|
61
|
+
if retry_on_transient_error { snapshot.save }
|
62
|
+
logger.debug "Done saving snapshot for #{vol.id}"
|
63
|
+
else
|
64
|
+
logger.warn "Problems saving snapshot, see above"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
58
68
|
def attached_volumes
|
59
|
-
|
69
|
+
logger.debug "Querying for volumes attached to this instance #{instance_id}"
|
70
|
+
@attached_volumes ||= (retry_on_transient_error { compute.volumes.select { |vol| vol.server_id == instance_id } } || [])
|
60
71
|
end
|
61
72
|
|
62
73
|
def access_key
|
@@ -72,7 +83,11 @@ module SnapEbs::Snapshotter
|
|
72
83
|
end
|
73
84
|
|
74
85
|
def instance_id
|
75
|
-
|
86
|
+
if options[:mock]
|
87
|
+
@instance_id = 'i-deadbeef'
|
88
|
+
else
|
89
|
+
@instance_id ||= JSON.parse(HTTParty.get(AWS_INSTANCE_ID_URL))["instanceId"]
|
90
|
+
end
|
76
91
|
end
|
77
92
|
|
78
93
|
def instance_name
|
@@ -120,12 +135,33 @@ module SnapEbs::Snapshotter
|
|
120
135
|
end
|
121
136
|
|
122
137
|
def fs_freeze dir
|
138
|
+
logger.debug "Preparing to freeze #{dir}"
|
123
139
|
return logger.warn "Refusing to freeze #{dir}, which is the root device (#{directory_to_device dir})" if is_root_device? dir
|
124
140
|
system("#{fs_freeze_command} -f #{dir}")
|
125
141
|
end
|
126
142
|
|
127
143
|
def fs_unfreeze dir
|
144
|
+
logger.debug "Preparing to unfreeze #{dir}"
|
128
145
|
return logger.warn "Refusing to unfreeze #{dir}, which is the root device (#{directory_to_device dir})" if is_root_device? dir
|
129
146
|
system("#{fs_freeze_command} -u #{dir}")
|
130
147
|
end
|
148
|
+
|
149
|
+
# Retries the given block options.retry_count times while it raises transient AWS
|
150
|
+
# API errors. Returns nil if the number of attempts has been exceeded
|
151
|
+
def retry_on_transient_error
|
152
|
+
(options.retry_count.to_i + 1).times do |n|
|
153
|
+
logger.debug "Attempt ##{n}"
|
154
|
+
begin
|
155
|
+
result = yield
|
156
|
+
rescue Fog::Compute::AWS::Error => e
|
157
|
+
sleep_seconds = options.retry_interval * (n+1)
|
158
|
+
logger.warn "Received AWS error: #{e}"
|
159
|
+
logger.warn "Sleeping #{sleep_seconds} seconds before retrying"
|
160
|
+
sleep sleep_seconds
|
161
|
+
else
|
162
|
+
return result
|
163
|
+
end
|
164
|
+
end
|
165
|
+
nil
|
166
|
+
end
|
131
167
|
end
|
data/lib/snap_ebs/version.rb
CHANGED
data/lib/snap_ebs.rb
CHANGED
@@ -41,16 +41,19 @@ class SnapEbs
|
|
41
41
|
# standard exceptions (i.e. out of memory or keyboard interrupt) will still
|
42
42
|
# cause a execution to abort.
|
43
43
|
def run
|
44
|
+
ok = true
|
44
45
|
plugins.each do |plugin|
|
46
|
+
next unless plugin.options.enable
|
45
47
|
begin
|
46
|
-
plugin.before
|
48
|
+
# we don't snap unless all plugin.before calls return a truthy value
|
49
|
+
ok = ok && plugin.before
|
47
50
|
rescue => e
|
48
51
|
logger.error "Encountered error while running the #{plugin.name} plugin's before hook"
|
49
52
|
logger.error e
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
53
|
-
take_snapshots
|
56
|
+
take_snapshots if ok
|
54
57
|
|
55
58
|
plugins.each do |plugin|
|
56
59
|
begin
|
@@ -66,7 +69,12 @@ class SnapEbs
|
|
66
69
|
def execute
|
67
70
|
option_parser.parse!
|
68
71
|
logger.debug "Debug logging enabled"
|
69
|
-
|
72
|
+
begin
|
73
|
+
run
|
74
|
+
rescue Exception => e
|
75
|
+
logger.fatal "Encountered exception #{e}"
|
76
|
+
e.backtrace.map { |x| logger.fatal x }
|
77
|
+
end
|
70
78
|
end
|
71
79
|
|
72
80
|
# Get the global logger instance
|