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 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