do_snapshot 0.0.4 → 0.0.5

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: f4c4999ce47e4ce7b2466c14205933af0cbdc961
4
- data.tar.gz: 0403072d2dd494b8f03090e7c4b7624414c9d7b8
3
+ metadata.gz: 33604b56b4b901f20645dd6a6ac8f6530bb3c3b7
4
+ data.tar.gz: 57b7c547a40af585b4d28314a274d759ffad9559
5
5
  SHA512:
6
- metadata.gz: 6c9866805ad171483316b5dd4fbb1e674dff9d779b097e23757167af90f99cb4acd39fd9827b1fbe3d52a5f4a8aae06578c49fa81ad9defea6f535be4183bb26
7
- data.tar.gz: 5ac4d9c275029df7a2300c258ba7b75268657353e906c01cfc375189a12c4d5be64e27253bb49e52df39a5656e67259f126ca28c4659a58a78cc5922837c6eee
6
+ metadata.gz: 72ea4af26a82e76649593595ca079ef18ea651b153344915ac246fc915a2ddbec8330ff7ed42d89a7e23c56828b6644e213eddc3b0aa137045a298687200b41e
7
+ data.tar.gz: b2afa75459cfe9fff4dd52aedb5c1b05ba509532433132f149ac539d311addfea1fe881d5851ab98ae280f5121dd762facffcd571a87ea7d70ae7e26b78b0765
data/README.md CHANGED
@@ -1,16 +1,17 @@
1
1
  # DoSnapshot
2
2
 
3
- You can use this gem to backup's DigitalOcean droplet's via snapshot.
3
+ You can use this gem to backup's DigitalOcean droplet's via snapshot method.
4
4
 
5
5
  Here some features:
6
6
 
7
- - Multiple threads out of the box.
8
- - Binary for cron and command-line.
9
- - Mail notification when maximum of snapshots for droplet reached.
7
+ - Multiple threads out of the box. No matter how much droplet's you have.
8
+ - Auto-cleanup for old snapshots.
9
+ - Binary special for cron and command-line.
10
+ - Mail notifications when fail or maximum of snapshots is reached for one or multiple droplets.
10
11
  - Custom mail settings (You can set [Pony](https://github.com/benprew/pony) mail settings).
11
12
  - Stop mode (when you don't want to create new snapshots when maximum is reached).
12
13
  - Logging into selected directory.
13
- - Trace mode for research.
14
+ - Verbose mode for research.
14
15
  - Quiet mode for silence.
15
16
 
16
17
  There not so much of dependencies:
@@ -35,64 +36,96 @@ Or install it yourself as:
35
36
 
36
37
  ## Usage
37
38
 
38
- First you may need to set DigitalOcean API keys:
39
-
40
-
41
- $ export DIGITAL_OCEAN_CLIENT_ID = "SOMEID"
42
- $ export DIGITAL_OCEAN_API_KEY = "SOMEKEY"
39
+ First you may need to set DigitalOcean API keys:
43
40
 
41
+ $ export DIGITAL_OCEAN_CLIENT_ID="SOMEID"
42
+ $ export DIGITAL_OCEAN_API_KEY="SOMEKEY"
44
43
 
45
- If you want to set keys without environment, than set it via options:
44
+ If you want to set keys without environment, than set it via options when you run do_snapshot:
46
45
 
47
46
  $ do_snapshot --digital-ocean-client-id YOURLONGAPICLIENTID --digital-ocean-api-key YOURLONGAPIKEY
48
47
 
48
+ #### Basic usage
49
+
50
+ Keep latest 5 and cleanup older if maximum is reached.
51
+ Here we `keeping` only 5 `latest` snapshots and `cleanup` older after new one is created.
52
+ **If creation of snapshots failed no one will be deleted.**
53
+
54
+ **By default we `keep` 10 droplets.**
55
+
56
+ $ do_snapshot --keep 5 -c
57
+
58
+ Keep latest 3 from selected droplets:
59
+
60
+ $ do_snapshot --only 123456 1234567 --keep 3
61
+
62
+ Working with all except selected droplets:
63
+
64
+ $ do_snapshot --exclude 123456 123457
65
+
66
+ Keep latest 5 snapshots, send mail notification instead of creating new one:
67
+
68
+ $ do_snapshot --keep 10 --stop --mail to:yourmail@example.com
69
+
49
70
  E-mail notifications disabled out of the box.
50
71
  For working mailer you need to set e-mail settings via run options.
51
72
 
52
- ```shell
53
- Usage:
54
- do_snapshot create
55
-
56
- Options:
57
- -o, [--only=123456 123456 123456] # Use only selected droplets.
58
- -e, [--exclude=123456 123456 123456] # Except some droplets.
59
- -k, [--keep=5] # How much snapshots you want to keep?
60
- # Default: 10
61
- -s, [--stop], [--no-stop] # Stop creating snapshots if maximum is reached.
62
- -m, [--mail=to:yourmail@example.com] # Receive mail if maximum is reached.
63
- -t, [--smtp=user_name:yourmail@example.com password:password] # SMTP options.
64
- -l, [--log=/Users/someone/.do_snapshot/main.log] # Log file path. By default logging is disabled.
65
- -d, [--trace], [--no-trace] # Debug mode.
66
- -q, [--quiet], [--no-quiet] # Quiet mode. If don't need any messages and log's
67
- [--digital-ocean-client-id=YOURLONGAPICLIENTID] # DIGITAL_OCEAN_CLIENT_ID. if you can't use environment.
68
- [--digital-ocean-api-key=YOURLONGAPIKEY] # DIGITAL_OCEAN_API_KEY. if you can't use environment.
69
-
70
- Description:
71
- `do_snapshot create` will create and cleanup snapshots on your droplets.
72
-
73
- You can optionally specify parameters to select or exclude some droplets.
74
-
75
- Advanced options example for MAIL feature:
76
-
77
- --mail to:mail@somehost.com from:from@host.com
78
- --smtp address:smtp.gmail.com user_name:someuser password:somepassword
79
-
80
- For more details look here: [https://github.com/benprew/pony](https://github.com/benprew/pony)
81
-
82
- Example:
83
-
84
- > $ do_snapshot --keep 5 --quiet
85
-
86
- > $ do_snapshot --only 123456 1234567 --store 3
87
-
88
- > $ do_snapshot --exclude 123456 123457
89
-
90
- > $ do_snapshot --keep 10 --stop true --mail to:yourmail@example.com
91
- ```
73
+ --mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com port:25 user_name:someuser password:somepassword
74
+
75
+ #### Cron example
76
+
77
+ 0 4 * * 7 /.../bin/do_snapshot -k 5 -m to:TO from:FROM -t address:HOST user_name:LOGIN password:PASSWORD port:2525 -q -c
78
+
79
+ #### Real world example
80
+
81
+ $ bin/do_snapshot --only 123456 -k 3 -c -m to:TO from:FROM -t address:HOST user_name:LOGIN password:PASSWORD port:2525 -v
82
+
83
+ Checking DigitalOcean Id's.
84
+ Start performing operations
85
+ Setting DigitalOcean Id's.
86
+ Loading list of DigitalOcean droplets
87
+ Working with list of DigitalOcean droplets
88
+ Preparing droplet id: 123456 name: mrcr.ru to take snapshot.
89
+ Shutting down droplet.
90
+ Start creating snapshot for droplet id: 123456 name: mrcr.ru.
91
+ Wait until snapshot will be created.
92
+ Snapshot name: mrcr.ru_2014_07_18 created successfully.
93
+ Droplet id: 123456 name: mrcr.ru snapshots: 4.
94
+ For droplet with id: 123456 and name: mrcr.ru the maximum number 3 of snapshots is reached.
95
+ Cleaning up snapshots for droplet id: 123456 name: mrcr.ru.
96
+ Snapshot name: mrcr.ru_2014_07_17 delete requested.
97
+ All operations has been finished.
98
+ Sending e-mail notification.
99
+
100
+ ### All options:
101
+
102
+ > $ do_snapshot c
103
+
104
+ aliases: s, snap, create
105
+
106
+ Options:
107
+ -o, [--only=123456 123456 123456] # Select some droplets.
108
+ -e, [--exclude=123456 123456 123456] # Except some droplets.
109
+ -k, [--keep=5] # How much snapshots you want to keep?
110
+ # Default: 10
111
+ -m, [--mail=to:yourmail@example.com] # Receive mail if fail or maximum is reached.
112
+ -t, [--smtp=user_name:yourmail@example.com password:password] # SMTP options.
113
+ -l, [--log=/Users/someone/.do_snapshot/main.log] # Log file path. By default logging is disabled.
114
+ -c, [--clean], [--no-clean] # Cleanup snapshots after create. If you have more images than you want to `keep`, older will be deleted.
115
+ -s, [--stop], [--no-stop] # Stop creating snapshots if maximum is reached.
116
+ -v, [--trace], [--no-trace] # Verbose mode.
117
+ -q, [--quiet], [--no-quiet] # Quiet mode. If don't need any messages in console.
118
+ [--digital-ocean-client-id=YOURLONGAPICLIENTID] # DIGITAL_OCEAN_CLIENT_ID. if you can't use environment.
119
+ [--digital-ocean-api-key=YOURLONGAPIKEY] # DIGITAL_OCEAN_API_KEY. if you can't use environment.
120
+
121
+ Description:
122
+ `do_snapshot` able to create and cleanup snapshots on your droplets.
123
+
124
+ You can optionally specify parameters to select or exclude some droplets.
92
125
 
93
126
  ## Contributing
94
127
 
95
- 1. Fork it ( https://github.com/[my-github-username]/do_snapshot/fork )
128
+ 1. Fork it ( https://github.com/merqlove/do_snapshot/fork )
96
129
  2. Create your feature branch (`git checkout -b my-new-feature`)
97
130
  3. Commit your changes (`git commit -am 'Add some feature'`)
98
131
  4. Push to the branch (`git push origin my-new-feature`)
data/do_snapshot.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = DoSnapshot::VERSION
9
9
  spec.authors = ['Alexander Merkulov']
10
10
  spec.email = ['sasha@merqlove.ru']
11
- spec.summary = %q{Snapshot creator for Digital Ocean droplets. Multi-threading inside. Use it with Cron or other tools.}
12
- spec.description = %q{Snapshot creator for Digital Ocean droplets. Multi-threading inside. Use it with Cron or other tools.}
11
+ spec.summary = %q{Snapshot creator for Digital Ocean droplets. Multi-threading. Auto-cleanup. Cron optimized.}
12
+ spec.description = %q{Snapshot creator for Digital Ocean droplets. Multi-threading inside. Auto-cleanup feature. No matter how much droplets you have. Cron optimized.}
13
13
  spec.homepage = 'http://github.com/merqlove/do_snapshot'
14
14
  spec.license = 'MIT'
15
15
 
@@ -1,23 +1,27 @@
1
1
  require 'do_snapshot'
2
2
  require 'do_snapshot/command'
3
- require 'thor'
4
3
 
5
4
  module DoSnapshot
6
5
  # CLI is here
7
6
  #
8
7
  class CLI < Thor
9
- default_task :create
8
+ default_task :snap
9
+
10
+ map %w( c s create ) => :snap
11
+ map %w( -V ) => :version
10
12
 
11
13
  def initialize(*args)
12
14
  super
13
15
 
14
- # Use Thor log especially
15
- Log.thor_log = Thor::Shell::Color.new unless options.include?('quiet')
16
+ Log.quiet = options['quiet']
17
+ # Use Thor shell
18
+ Log.shell = shell unless Log.quiet
19
+ Log.verbose = options['trace']
16
20
 
17
- if options.include?('log')
18
- Log.logger = Logger.new(options['log'])
19
- Log.logger.level = options.include?('trace') ? Logger::DEBUG : Logger::INFO
20
- end
21
+ logger if options.include?('log')
22
+
23
+ Log.mail = options['mail']
24
+ Log.smtp = options['smtp']
21
25
 
22
26
  # Check for keys via options
23
27
  ENV['DIGITAL_OCEAN_CLIENT_ID'] = options['digital_ocean_client_id'] if options.include? 'digital_ocean_client_id'
@@ -26,49 +30,84 @@ module DoSnapshot
26
30
  try_keys_first
27
31
  end
28
32
 
29
- desc 'create', 'create and cleanup snapshot\'s'
33
+ desc 'c / s / snap / create', 'DEFAULT. Create and cleanup snapshot\'s'
30
34
  long_desc <<-LONGDESC
31
- `do_snapshot create` will create and cleanup snapshots on your droplets.
35
+ `do_snapshot` able to create and cleanup snapshots on your droplets.
32
36
 
33
37
  You can optionally specify parameters to select or exclude some droplets.
34
38
 
35
- Advanced options example for MAIL feature:
39
+ ### Advanced options example for MAIL feature:
36
40
 
37
- --mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com user_name:someuser password:somepassword
41
+ --mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com port:25 user_name:someuser password:somepassword
38
42
 
39
43
  For more details look here: https://github.com/benprew/pony
40
44
 
41
- Example:
45
+ ### Examples
46
+
47
+ Keep latest 5 and cleanup older if maximum is reached:
48
+
49
+ $ do_snapshot --keep 5 -c
50
+
51
+ Keep latest 3 from selected droplets:
52
+
53
+ $ do_snapshot --only 123456 1234567 --keep 3
54
+
55
+ Working with all except selected droplets:
56
+
57
+ $ do_snapshot --exclude 123456 123457
42
58
 
43
- > $ do_snapshot --keep 5
59
+ Keep latest 5 snapshots, not create new if we have more, send mail notification instead:
44
60
 
45
- > $ do_snapshot --only 123456 1234567 --store 3
61
+ $ do_snapshot --keep 10 --stop --mail to:yourmail@example.com
46
62
 
47
- > $ do_snapshot --exclude 123456 123457
63
+ ### Cron example
48
64
 
49
- > $ do_snapshot --keep 10 --stop true --mail to:yourmail@example.com
65
+ 0 4 * * 7 /.../bin/do_snapshot -k 5 -m to:TO from:FROM -t address:HOST user_name:LOGIN password:PASSWORD port:2525 -q -c
66
+
67
+ VERSION: #{DoSnapshot::VERSION}
50
68
  LONGDESC
51
- option :only, type: :array, default: [], aliases: ['-o'], banner: '123456 123456 123456', desc: 'Use only selected droplets.'
52
- option :exclude, type: :array, default: [], aliases: ['-e'], banner: '123456 123456 123456', desc: 'Except some droplets.'
53
- option :keep, type: :numeric, default: 10, aliases: ['-k'], banner: '5', desc: 'How much snapshots you want to keep?'
54
- option :stop, type: :boolean, aliases: ['-s'], desc: 'Stop creating snapshots if maximum is reached.'
55
- option :mail, type: :hash, default: {}, aliases: ['-m'], banner: 'to:yourmail@example.com', desc: 'Receive mail if maximum is reached.'
56
- option :smtp, type: :hash, default: {}, aliases: ['-t'], banner: 'user_name:yourmail@example.com password:password', desc: 'SMTP options.'
57
- option :log, type: :string, aliases: ['-l'], banner: '/Users/someone/.do_snapshot/main.log', desc: 'Log file path. By default logging is disabled.'
58
- option :trace, type: :boolean, aliases: ['-d'], desc: 'Debug mode.'
59
- option :quiet, type: :boolean, aliases: ['-q'], desc: 'Quiet mode. If don\'t need any messages and log\'s'
60
- option :digital_ocean_client_id, type: :string, banner: 'YOURLONGAPICLIENTID', desc: 'DIGITAL_OCEAN_CLIENT_ID. if you can\'t use environment.'
61
- option :digital_ocean_api_key, type: :string, banner: 'YOURLONGAPIKEY', desc: 'DIGITAL_OCEAN_API_KEY. if you can\'t use environment.'
62
-
63
- def create
64
- DoSnapshot::Command.execute options, %w( log trace quiet digital_ocean_client_id digital_ocean_api_key )
69
+
70
+ method_option :only, type: :array, default: [], aliases: %w( -o ), banner: '123456 123456 123456', desc: 'Select some droplets.'
71
+ method_option :exclude, type: :array, default: [], aliases: %w( -e ), banner: '123456 123456 123456', desc: 'Except some droplets.'
72
+ method_option :keep, type: :numeric, default: 10, aliases: %w( -k ), banner: '5', desc: 'How much snapshots you want to keep?'
73
+ method_option :delay, type: :numeric, default: 10, aliases: %w( -d ), banner: '5', desc: 'Delay between snapshot operation status requests.'
74
+ method_option :mail, type: :hash, aliases: %w( -m ), banner: 'to:yourmail@example.com', desc: 'Receive mail if fail or maximum is reached.'
75
+ method_option :smtp, type: :hash, aliases: %w( -t ), banner: 'user_name:yourmail@example.com password:password', desc: 'SMTP options.'
76
+ method_option :log, type: :string, aliases: %w( -l ), banner: '/Users/someone/.do_snapshot/main.log', desc: 'Log file path. By default logging is disabled.'
77
+ method_option :clean, type: :boolean, aliases: %w( -c ), desc: 'Cleanup snapshots after create. If you have more images than you want to `keep`, older will be deleted.'
78
+ method_option :stop, type: :boolean, aliases: %w( -s), desc: 'Stop creating snapshots if maximum is reached.'
79
+ method_option :trace, type: :boolean, aliases: %w( -v ), desc: 'Verbose mode.'
80
+ method_option :quiet, type: :boolean, aliases: %w( -q ), desc: 'Quiet mode. If don\'t need any messages and in console.'
81
+
82
+ method_option :digital_ocean_client_id, type: :string, banner: 'YOURLONGAPICLIENTID', desc: 'DIGITAL_OCEAN_CLIENT_ID. if you can\'t use environment.'
83
+ method_option :digital_ocean_api_key, type: :string, banner: 'YOURLONGAPIKEY', desc: 'DIGITAL_OCEAN_API_KEY. if you can\'t use environment.'
84
+
85
+ def snap
86
+ Command.execute options, %w( log trace digital_ocean_client_id digital_ocean_api_key )
65
87
  rescue => e
88
+
89
+ Command.fail_power_on(e.id) if e && e.class == SnapshotCreateError && e.respond_to?('id')
66
90
  Log.error e.message
67
91
  backtrace(e) if options.include? 'trace'
92
+ if Log.mail
93
+ Log.mail[:subject] = 'Digital Ocean: Error.'
94
+ Log.mail[:body] = 'Please check your droplets.'
95
+ Log.notify
96
+ end
97
+ end
98
+
99
+ desc 'version, -V', 'Shows the version of the currently installed DoSnapshot gem'
100
+ def version
101
+ puts DoSnapshot::VERSION
68
102
  end
69
103
 
70
104
  protected
71
105
 
106
+ def logger
107
+ Log.logger = Logger.new(options['log'])
108
+ Log.logger.level = Log.verbose ? Logger::DEBUG : Logger::INFO
109
+ end
110
+
72
111
  def backtrace(e)
73
112
  e.backtrace.each do |t|
74
113
  Log.error t
@@ -1,7 +1,4 @@
1
1
  require 'digitalocean'
2
- require 'date'
3
- require 'pony'
4
- require 'core_ext/hash'
5
2
  require 'thread'
6
3
 
7
4
  module DoSnapshot
@@ -16,26 +13,41 @@ module DoSnapshot
16
13
  send("#{key}=", option) unless skip.include? key
17
14
  end
18
15
 
19
- self.notify = false
20
- self.threads = []
21
-
16
+ Log.info 'Start performing operations'
22
17
  work_droplets
23
- email_message if notify && mail
18
+ Log.info 'All operations has been finished.'
19
+
20
+ Log.notify if notify && !quiet
21
+ end
22
+
23
+ def fail_power_on(id)
24
+ return unless id
24
25
 
25
- Log.info 'All snapshots requested'
26
+ set_id
27
+ instance = Digitalocean::Droplet.find(id)
28
+ fail instance.message unless instance.status.include? 'OK'
29
+ if instance.droplet.status.include? 'active'
30
+ Log.info "Droplet id: #{id} failed to snapshot. But it still running."
31
+ else
32
+ Digitalocean::Droplet.power_on(id)
33
+ Log.info "Droplet id: #{id} failed to snapshot. POWER ON has been requested."
34
+ end
26
35
  end
27
36
 
28
37
  protected
29
38
 
30
- attr_accessor :droplets
31
- attr_accessor :exclude
32
- attr_accessor :only
33
- attr_accessor :keep
34
- attr_accessor :mail
35
- attr_accessor :smtp
36
- attr_accessor :stop
37
- attr_accessor :notify
38
- attr_accessor :threads
39
+ attr_accessor :droplets, :mail, :smtp, :exclude, :only
40
+ attr_accessor :delay, :keep, :quiet, :stop, :clean
41
+
42
+ attr_writer :notify, :threads
43
+
44
+ def notify
45
+ @notify ||= false
46
+ end
47
+
48
+ def threads
49
+ @threads ||= []
50
+ end
39
51
 
40
52
  # Getting droplets list from API.
41
53
  # And store into object.
@@ -44,7 +56,7 @@ module DoSnapshot
44
56
  set_id
45
57
  Log.debug 'Loading list of DigitalOcean droplets'
46
58
  droplets = Digitalocean::Droplet.all
47
- fail droplets.message unless droplets.status == 'OK'
59
+ fail droplets.message unless droplets.status.include? 'OK'
48
60
  self.droplets = droplets.droplets
49
61
  end
50
62
 
@@ -59,7 +71,7 @@ module DoSnapshot
59
71
  next if !only.empty? && !only.include?(id)
60
72
 
61
73
  instance = Digitalocean::Droplet.find(id)
62
- fail instance.message unless instance.status == 'OK'
74
+ fail instance.message unless instance.status.include? 'OK'
63
75
 
64
76
  prepare_instance instance.droplet
65
77
  end
@@ -69,7 +81,7 @@ module DoSnapshot
69
81
  # Threads review
70
82
  #
71
83
  def thread_chain
72
- threads.each {|t| t.join}
84
+ threads.each { |t| t.join }
73
85
  end
74
86
 
75
87
  # Preparing instance to take snapshot.
@@ -77,9 +89,9 @@ module DoSnapshot
77
89
  #
78
90
  def prepare_instance(instance)
79
91
  return unless instance
80
- Log.debug "Preparing droplet id: #{instance.id} name: #{instance.name} to snapshot."
92
+ Log.info "Preparing droplet id: #{instance.id} name: #{instance.name} to take snapshot."
81
93
 
82
- warning_size = "For droplet with id: #{instance.id} and name: #{instance.name} the maximum #{keep} is reached."
94
+ warning_size = "For droplet with id: #{instance.id} and name: #{instance.name} the maximum number #{keep} of snapshots is reached."
83
95
 
84
96
  if instance.snapshots.size >= keep && stop
85
97
  Log.warning warning_size
@@ -90,11 +102,15 @@ module DoSnapshot
90
102
  # Stopping instance.
91
103
  Log.debug 'Shutting down droplet.'
92
104
  threads << Thread.new do
93
- unless instance.status.include? 'off'
94
- event = Digitalocean::Droplet.power_off(instance.id)
95
- if event.status.include? 'OK'
96
- sleep 1.3 until get_event_status(event.event_id)
105
+ begin
106
+ unless instance.status.include? 'off'
107
+ event = Digitalocean::Droplet.power_off(instance.id)
108
+ if event.status.include? 'OK'
109
+ sleep delay until get_event_status(event.event_id)
110
+ end
97
111
  end
112
+ rescue => e
113
+ raise DropletShutdownError.new(instance.id), e.message, e.backtrace
98
114
  end
99
115
 
100
116
  # Create snapshot.
@@ -105,7 +121,7 @@ module DoSnapshot
105
121
  # Trying to create a snapshot.
106
122
  #
107
123
  def create_snapshot(instance, warning_size)
108
- Log.debug "Start creating snapshot for droplet id: #{instance.id} name: #{instance.name}."
124
+ Log.info "Start creating snapshot for droplet id: #{instance.id} name: #{instance.name}."
109
125
 
110
126
  today = DateTime.now
111
127
  name = "#{instance.name}_#{today.strftime('%Y_%m_%d')}"
@@ -120,7 +136,7 @@ module DoSnapshot
120
136
 
121
137
  Log.debug 'Wait until snapshot will be created.'
122
138
 
123
- sleep 10 until get_event_status(event.event_id)
139
+ sleep delay until get_event_status(event.event_id)
124
140
 
125
141
  snapshot_size += 1
126
142
 
@@ -130,9 +146,40 @@ module DoSnapshot
130
146
  if snapshot_size > keep
131
147
  Log.warning warning_size if snapshot_size > keep
132
148
  self.notify = true
149
+
150
+ # Cleanup snapshots.
151
+ cleanup_snapshots instance, (snapshot_size - keep - 1) if clean
152
+ end
153
+ rescue => e
154
+ case e.class
155
+ when SnapshotCleanupError
156
+ raise
157
+ else
158
+ raise SnapshotCreateError.new(instance.id), e.message, e.backtrace
133
159
  end
134
160
  end
135
161
 
162
+ # Cleanup our snapshots.
163
+ #
164
+ def cleanup_snapshots(instance, size)
165
+ Log.debug "Cleaning up snapshots for droplet id: #{instance.id} name: #{instance.name}."
166
+
167
+ (0..size).each do |i|
168
+ snapshot = instance.snapshots[i]
169
+ event = Digitalocean::Image.destroy(snapshot.id)
170
+
171
+ if !event
172
+ fail 'Something wrong with DigitalOcean or with your connection :)'
173
+ elsif event && !event.status.include?('OK')
174
+ fail event.message
175
+ end
176
+
177
+ Log.info "Snapshot name: #{snapshot.name} delete requested."
178
+ end
179
+ rescue => e
180
+ raise SnapshotCleanupError.new(instance.id), e.message, e.backtrace
181
+ end
182
+
136
183
  # Looking for event status.
137
184
  #
138
185
  # Before snapshot we to know that machine has powered off.
@@ -143,29 +190,6 @@ module DoSnapshot
143
190
  event.event.percentage && event.event.percentage.include?('100') ? true : false
144
191
  end
145
192
 
146
- # Sending message via Hash params.
147
- #
148
- # Options:: -m to:mail@somehost.com from:from@host.com -t address:smtp.gmail.com user_name:someuser password:somepassword
149
- #
150
- def email_message
151
- mail.symbolize_keys!
152
- smtp.symbolize_keys!
153
-
154
- mail[:subject] = 'DigitalOcean Snapshot maximum is reached.' unless mail[:subject]
155
- mail[:body] = "Please cleanup your Digital Ocean account. \nSnapshot maximum is reached." unless mail[:body]
156
- mail[:from] = 'noreply@someonelse.com' unless mail[:from]
157
- mail[:via] = :smtp unless mail[:via]
158
-
159
- smtp[:domain] = 'localhost.localdomain' unless smtp[:domain]
160
- smtp[:port] = '25' unless smtp[:port]
161
-
162
- mail[:via_options] = smtp
163
-
164
- Log.debug 'Sending e-mail notification.'
165
- # Look into your inbox :)
166
- Pony.mail(mail)
167
- end
168
-
169
193
  # Set id's of Digital Ocean API.
170
194
  #
171
195
  def set_id
@@ -1,5 +1,5 @@
1
1
  # Current version
2
2
  #
3
3
  module DoSnapshot
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.5'
5
5
  end
data/lib/do_snapshot.rb CHANGED
@@ -1,44 +1,120 @@
1
1
  require 'do_snapshot/version'
2
+ require 'thor'
2
3
  require 'logger'
4
+ require 'date'
5
+ require 'pony'
6
+ require 'core_ext/hash'
3
7
 
4
8
  # Used primary for creating snapshot's as backups for DigitalOcean
5
9
  #
6
10
  module DoSnapshot
11
+ # Set multiple Errors with `id` @param
12
+ #
13
+ class DigitalOceanError < StandardError
14
+ attr_reader :id
15
+ # @param [Object] id
16
+ def initialize(id)
17
+ @id = id
18
+ end
19
+ end
20
+ class DropletShutdownError < DigitalOceanError; end
21
+ class SnapshotCreateError < DigitalOceanError; end
22
+ class SnapshotCleanupError < DigitalOceanError; end
23
+
7
24
  # Shared logger
8
25
  #
9
26
  class Log
10
27
  class << self
11
28
  attr_accessor :logger
12
- attr_accessor :thor_log
29
+ attr_accessor :shell
30
+ attr_accessor :mail
31
+ attr_accessor :quiet
32
+ attr_accessor :verbose
33
+ attr_writer :smtp
34
+
35
+ def smtp
36
+ @smtp ||= {}
37
+ end
13
38
 
14
39
  def log(type, message)
40
+ buffer << message
15
41
  logger.send(type, message) if logger
42
+
43
+ say message, color(type) unless type == :debug && !debug?
44
+ end
45
+
46
+ def color(type)
47
+ case type
48
+ when :debug
49
+ :white
50
+ when :error
51
+ :red
52
+ when :warn
53
+ :yellow
54
+ else
55
+ :green
56
+ end
16
57
  end
17
58
 
18
59
  def info(message)
19
60
  log :info, message
20
- say message, :green
21
61
  end
22
62
 
23
63
  def warning(message)
24
64
  log :warn, message
25
- say message, :yellow
26
65
  end
27
66
 
28
67
  def error(message)
29
68
  log :error, message
30
- say message, :red
31
69
  end
32
70
 
33
71
  def debug(message)
34
72
  log :debug, message
35
- say message, :white if logger && logger.level == Logger::DEBUG
73
+ end
74
+
75
+ def say(message, color)
76
+ shell.say message, color if shell
77
+ end
78
+
79
+ def debug?
80
+ logger && logger.level == Logger::DEBUG
81
+ end
82
+
83
+ # Sending message via Hash params.
84
+ #
85
+ # Options:: --mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com user_name:someuser password:somepassword
86
+ #
87
+ def notify
88
+ return unless mail
89
+
90
+ mail.symbolize_keys!
91
+ smtp.symbolize_keys!
92
+
93
+ notify_init
94
+
95
+ Log.debug 'Sending e-mail notification.'
96
+ # Look into your inbox :)
97
+ Pony.mail(mail)
36
98
  end
37
99
 
38
100
  protected
39
101
 
40
- def say(message, color)
41
- thor_log.say message, color if thor_log
102
+ def notify_init
103
+ mail[:subject] = 'Digital Ocean: maximum snapshots is reached.' unless mail[:subject]
104
+ mail[:body] = "Please cleanup your Digital Ocean account.\nSnapshot maximum is reached." unless mail[:body]
105
+ mail[:from] = 'noreply@someonelse.com' unless mail[:from]
106
+ mail[:to] = 'to@someonelse.com' unless mail[:to]
107
+ mail[:via] = :smtp unless mail[:via]
108
+ mail[:body] = "#{mail[:body]}\n\nTrace: #{DateTime.now}\n#{buffer.join("\n")}"
109
+ smtp[:domain] = 'localhost.localdomain' unless smtp[:domain]
110
+ smtp[:port] = '25' unless smtp[:port]
111
+
112
+ mail[:via_options] = smtp
113
+ end
114
+
115
+ attr_writer :buffer
116
+ def buffer
117
+ @buffer ||= %w()
42
118
  end
43
119
  end
44
120
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: do_snapshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Merkulov
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: Snapshot creator for Digital Ocean droplets. Multi-threading inside.
84
- Use it with Cron or other tools.
84
+ Auto-cleanup feature. No matter how much droplets you have. Cron optimized.
85
85
  email:
86
86
  - sasha@merqlove.ru
87
87
  executables:
@@ -127,7 +127,7 @@ rubyforge_project:
127
127
  rubygems_version: 2.2.2
128
128
  signing_key:
129
129
  specification_version: 4
130
- summary: Snapshot creator for Digital Ocean droplets. Multi-threading inside. Use
131
- it with Cron or other tools.
130
+ summary: Snapshot creator for Digital Ocean droplets. Multi-threading. Auto-cleanup.
131
+ Cron optimized.
132
132
  test_files:
133
133
  - test/.keep