snap-ebs 0.0.22 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|