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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c62d36f1e86965f89d7733040c0ed8d6a70054be
4
- data.tar.gz: 30e45d4efff41f0813b14a1a113b33daab257f41
3
+ metadata.gz: 62c41bd18a3cbb71c5371a5173dea68f58d36424
4
+ data.tar.gz: f6746f30e90bb026ecb23bcdfdbc84fce247b25d
5
5
  SHA512:
6
- metadata.gz: d434a18fa189acf1ba449b49a6cce5e9058614c5cb35e0eb62c44a26ca9f43a34b0290122fa2b139134f2e8a8fd52d1883e2453b5fb258b54e6af6348f25efad
7
- data.tar.gz: 089ba5066f153d6b1d8c542372c626d1dd17e8e9f251a719a7f6053bca980be34c0744fd23279f7ca0c4b0f0e8b9e06029d9d8054690d3d617256d4761de1f21
6
+ metadata.gz: 4dab5f0340738c8bc137fd46b03b84fafee0281f40ffd6078fbc48e2ffe236916caf6a5fa06c45376b4ddb98dcf0cbf37b8a9eb79916d47343c70dab57e0af1a
7
+ data.tar.gz: af3ae2147a22fcac3759934a2f4b10e0d56dd6dde19bb5b9e6c0a9f64f0bd2e9ab6be4014f175e4b55a0a86a7cb03eabd89c1e7c782784801dc1f5ec2d95e9db
@@ -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
@@ -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
@@ -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
- begin
12
- system 'sync'
13
- attached_volumes.each do |vol|
14
- dir = device_to_directory device_name vol
15
- fs_freeze dir if options[:fs_freeze]
16
- next unless should_snap vol
17
- logger.debug "Snapping #{vol.id}"
18
- begin
19
- snapshot = compute.snapshots.new
20
- snapshot.volume_id = vol.id
21
- snapshot.description = snapshot_name(vol)
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
- rescue StandardError => e
31
- logger.warn "Received error while walking volumes:"
32
- logger.warn e
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 information normally auto-detected from AWS is injected with dummy
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
- @attached_volumes ||= compute.volumes.select { |vol| vol.server_id == instance_id }
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
- @instance_id ||= JSON.parse(HTTParty.get(AWS_INSTANCE_ID_URL))["instanceId"]
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
@@ -1,3 +1,3 @@
1
1
  class SnapEbs
2
- VERSION = '0.0.22'
2
+ VERSION = '0.0.23'
3
3
  end
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 if plugin.options.enable
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
- run
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snap-ebs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.22
4
+ version: 0.0.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Conrad