aebus 0.0.1
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.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/README +32 -0
- data/Rakefile +1 -0
- data/aebus.gemspec +28 -0
- data/bin/aebus +57 -0
- data/lib/aebus.rb +208 -0
- data/lib/aebus/version.rb +3 -0
- data/lib/aebus_zones.rb +11 -0
- data/lib/config/config.rb +60 -0
- data/lib/config/volume.rb +116 -0
- data/lib/ec2/snapshot.rb +69 -0
- metadata +91 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Aebus - Automatic EC2 BackUp Software
|
2
|
+
|
3
|
+
A small gem that allows you to easily automate EC2 backups, included purging of old backups and checking the backup status
|
4
|
+
|
5
|
+
|
6
|
+
==Sample
|
7
|
+
|
8
|
+
default:
|
9
|
+
access_key_id: <your_access_key_id>
|
10
|
+
secret_access_key: <your_secret_access_key>
|
11
|
+
zone: eu-west1
|
12
|
+
backups:
|
13
|
+
daily:
|
14
|
+
enabled: true
|
15
|
+
keep: 7
|
16
|
+
when: 0 3 * * *
|
17
|
+
weekly:
|
18
|
+
enabled: true
|
19
|
+
keep: 5
|
20
|
+
when: 0 3 * * 1
|
21
|
+
monthly:
|
22
|
+
enabled: true
|
23
|
+
keep: all
|
24
|
+
when: 0 3 1 * *
|
25
|
+
|
26
|
+
|
27
|
+
vol-1234567:
|
28
|
+
|
29
|
+
vol-7654321:
|
30
|
+
backups:
|
31
|
+
daily:
|
32
|
+
enabled: false
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/aebus.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "aebus/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "aebus"
|
7
|
+
s.version = Aebus::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Marco Sandrini"]
|
10
|
+
s.email = ["nessche@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/nessche/Aebus"
|
12
|
+
s.summary = "Automated EC2 BackUp Software"
|
13
|
+
s.description = "A tool to automate snapshot management in EC2"
|
14
|
+
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency("commander", "~> 4.0.6")
|
22
|
+
s.add_dependency("parse-cron", ">= 0.1.1")
|
23
|
+
s.add_dependency("amazon-ec2", "~> 0.9.17")
|
24
|
+
|
25
|
+
# specify any dependencies here; for example:
|
26
|
+
# s.add_development_dependency "rspec"
|
27
|
+
# s.add_runtime_dependency "rest-client"
|
28
|
+
end
|
data/bin/aebus
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'commander/import'
|
5
|
+
require 'pathname'
|
6
|
+
require_relative '../lib/aebus'
|
7
|
+
|
8
|
+
DEFAULT_CONFIG_NAME = "./aebus.yaml"
|
9
|
+
|
10
|
+
program :version, Aebus::VERSION
|
11
|
+
program :description, 'Automatic EC2 BackUp Software'
|
12
|
+
|
13
|
+
global_option('-c','--config FILE', 'The YAML file containing the backup configuration')
|
14
|
+
|
15
|
+
default_command :help
|
16
|
+
|
17
|
+
command :status do |c|
|
18
|
+
c.syntax = 'aebus status [options]'
|
19
|
+
c.summary = 'Checks for backup status'
|
20
|
+
c.description = <<-eos
|
21
|
+
Checks for the backup status of a given set of EC2 Volumes.
|
22
|
+
If no volume is specified in the command line, all volumes defined in the config files are checked
|
23
|
+
eos
|
24
|
+
c.example 'Checks the status of all volumes defined in the config file', 'aebus status'
|
25
|
+
c.example 'Checks the status of vol1 and vol2', 'aebus status vol1 vol2'
|
26
|
+
|
27
|
+
c.when_called do |args, options|
|
28
|
+
options.default \
|
29
|
+
:config => DEFAULT_CONFIG_NAME
|
30
|
+
raise ("Config file does not exist") unless FileTest.exist?(Pathname.new(options.config).realpath)
|
31
|
+
aebus = Aebus::Aebus.new
|
32
|
+
aebus.status(args,options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
command :backup do |c|
|
37
|
+
c.syntax = 'aebus backup [options]'
|
38
|
+
c.summary = 'Backs up a set of EC2 Volumes'
|
39
|
+
c.description = <<-eos
|
40
|
+
Backs up a set of EC2 Volumes, according to the configuration file. If no volume is specified in the
|
41
|
+
command line, all volumes defined in the config file are backed up
|
42
|
+
eos
|
43
|
+
c.example 'Manually creates backup of vol1 and vol2', 'aebus backup --manual vol1 vol2'
|
44
|
+
c.example 'Create, if needed, backups for all volumes', 'aebus backup'
|
45
|
+
c.option '--manual', 'Starts a manual backup (always creates a snapshot for each volume)'
|
46
|
+
c.option '--[no-]purge', 'Do not purge expired backups, defaults to --purge'
|
47
|
+
c.when_called do |args, options|
|
48
|
+
options.default \
|
49
|
+
:config => DEFAULT_CONFIG_NAME,
|
50
|
+
:manual => false,
|
51
|
+
:purge => true
|
52
|
+
raise ("Config file does not exist") unless FileTest.exist?(Pathname.new(options.config).realpath)
|
53
|
+
aebus = Aebus::Aebus.new
|
54
|
+
aebus.backup(args,options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
data/lib/aebus.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'AWS'
|
5
|
+
require_relative 'config/config'
|
6
|
+
require_relative 'aebus_zones'
|
7
|
+
require_relative 'ec2/snapshot'
|
8
|
+
|
9
|
+
module Aebus
|
10
|
+
|
11
|
+
VERSION = '0.0.1'
|
12
|
+
|
13
|
+
class Aebus
|
14
|
+
|
15
|
+
AWS_NAME_TAG = "Name"
|
16
|
+
AEBUS_TAG = "Aebus"
|
17
|
+
|
18
|
+
def status(args, options)
|
19
|
+
current_time_utc = Time.now.utc
|
20
|
+
config = Config::Config.new(File.join(File.dirname("."), options.config), current_time_utc)
|
21
|
+
@ec2 = AWS::EC2::Base.new(:access_key_id => config.defaults["access_key_id"],
|
22
|
+
:secret_access_key => config.defaults["secret_access_key"],
|
23
|
+
:server => zone_to_url(config.defaults["zone"]))
|
24
|
+
|
25
|
+
target_volumes = calculate_target_volumes(config, args)
|
26
|
+
snap_map = get_snapshots_map
|
27
|
+
|
28
|
+
target_volumes.each do |target|
|
29
|
+
volume = config.volumes[target]
|
30
|
+
tags = volume.backups_to_be_run(snap_map[target])
|
31
|
+
if (tags.count > 0) then
|
32
|
+
puts ("[INFO] Volume #{target} needs to be backed up. Tags: #{tags.join(',')}")
|
33
|
+
else
|
34
|
+
puts ("[INFO] Volume #{target} does not need to be backed up")
|
35
|
+
end
|
36
|
+
|
37
|
+
purgeable_snapshots =volume.purgeable_snapshots(snap_map[target])
|
38
|
+
puts ("[INFO] Volume #{target} has #{purgeable_snapshots.count} purgeable snapshot(s): #{purgeable_snapshots.inject([]){|x, snap| x << snap.id}.join(',')}")
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def backup(args, options)
|
46
|
+
|
47
|
+
current_time_utc = Time.now.utc
|
48
|
+
config = Config::Config.new(File.join(File.dirname("."), options.config), current_time_utc)
|
49
|
+
@ec2 = AWS::EC2::Base.new(:access_key_id => config.defaults["access_key_id"],
|
50
|
+
:secret_access_key => config.defaults["secret_access_key"],
|
51
|
+
:server => zone_to_url(config.defaults["zone"]))
|
52
|
+
|
53
|
+
target_volumes = calculate_target_volumes(config, args)
|
54
|
+
if (options.manual) then
|
55
|
+
|
56
|
+
target_volumes.each do |volume|
|
57
|
+
|
58
|
+
backup_volume(volume, current_time_utc, [EC2::AEBUS_MANUAL_TAG])
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
else
|
63
|
+
|
64
|
+
snap_map = get_snapshots_map
|
65
|
+
target_volumes.each do |target|
|
66
|
+
|
67
|
+
volume = config.volumes[target]
|
68
|
+
tags = volume.backups_to_be_run(snap_map[target])
|
69
|
+
if (tags.count > 0) then
|
70
|
+
tags << EC2::AEBUS_AUTO_TAG
|
71
|
+
puts("[INFO] Creating backup for volume #{target} with tags #{tags.join(',')}")
|
72
|
+
backup_volume(target, current_time_utc, tags)
|
73
|
+
else
|
74
|
+
puts ("[INFO] Volume #{target} does not need to be backed up")
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
snap_map = get_snapshots_map # we reload the map since we may have created more snapshots
|
80
|
+
if (options.purge) then
|
81
|
+
target_volumes.each do |target|
|
82
|
+
volume = config.volumes[target]
|
83
|
+
purgeable_snapshots = volume.purgeable_snapshots(snap_map[target])
|
84
|
+
purgeable_snapshots.each {|snapshot| purge_snapshot(snapshot.id)}
|
85
|
+
end
|
86
|
+
else
|
87
|
+
puts("[INFO] Skipping purging phase")
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
def calculate_target_volumes(config, args)
|
95
|
+
|
96
|
+
result = config.volume_ids
|
97
|
+
if (args && (args.count > 0)) then
|
98
|
+
result &= args
|
99
|
+
end
|
100
|
+
|
101
|
+
result
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
def list_volumes
|
106
|
+
response = @ec2.describe_volumes
|
107
|
+
puts(response)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
def zone_to_url(zone)
|
112
|
+
ZONES[zone]
|
113
|
+
end
|
114
|
+
|
115
|
+
def backup_volume(volume_id, current_time_utc, tags)
|
116
|
+
begin
|
117
|
+
volume_info = @ec2.describe_volumes(:volume_id => volume_id)
|
118
|
+
|
119
|
+
rescue AWS::Error => e
|
120
|
+
puts("[WARNING] Volume Id #{volume_id} not found")
|
121
|
+
return false
|
122
|
+
end
|
123
|
+
|
124
|
+
begin
|
125
|
+
puts(volume_info)
|
126
|
+
volume_tags = volume_info.volumeSet.item[0].tagSet.item
|
127
|
+
puts(volume_tags)
|
128
|
+
|
129
|
+
name_and_desc = Aebus.calculate_name_and_desc(volume_id, volume_tags, current_time_utc)
|
130
|
+
puts(name_and_desc)
|
131
|
+
create_response = @ec2.create_snapshot(:volume_id => volume_id, :description => name_and_desc[1])
|
132
|
+
puts(create_response)
|
133
|
+
|
134
|
+
rescue AWS::Error => e
|
135
|
+
puts("[ERROR] Volume Id #{volume_id} could not be backed up")
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
|
139
|
+
begin
|
140
|
+
|
141
|
+
@ec2.create_tags(:resource_id => create_response.snapshotId,
|
142
|
+
:tag => [{AWS_NAME_TAG => name_and_desc[0]}, {AEBUS_TAG => tags.join(',')}])
|
143
|
+
rescue AWS::Error => e
|
144
|
+
puts("[WARNING] Could not set tags to snapshot #{create_response.snapshotId}")
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
|
148
|
+
puts("[INFO] Created snapshot #{create_response.snapshotId} for volume #{volume_id}");
|
149
|
+
|
150
|
+
return true
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def self.calculate_name_and_desc(volume_id, tags, utc_time)
|
156
|
+
|
157
|
+
name = "backup_#{utc_time.strftime("%Y%m%d")}_#{volume_id}"
|
158
|
+
volume_name = volume_id
|
159
|
+
tags.each do |tag|
|
160
|
+
if tag["key"].eql?(AWS_NAME_TAG) then
|
161
|
+
volume_name = tag["value"]
|
162
|
+
break
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
description = "Backup for volume #{volume_name} taken at #{utc_time.strftime("%Y-%m-%d %H:%M:%S")}"
|
167
|
+
|
168
|
+
return [name, description]
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
def get_snapshots_map
|
173
|
+
|
174
|
+
response = @ec2.describe_snapshots(:owner => 'self')
|
175
|
+
snap_array = response.snapshotSet.item
|
176
|
+
result = Hash.new
|
177
|
+
snap_array.each do |snap|
|
178
|
+
snapshot = EC2::Snapshot.new(snap)
|
179
|
+
if (result.include?(snapshot.volume_id)) then
|
180
|
+
vol_array = result[snapshot.volume_id]
|
181
|
+
index = vol_array.index{ |s| snapshot.start_time > s.start_time}
|
182
|
+
index ||= vol_array.count
|
183
|
+
vol_array.insert(index, snapshot)
|
184
|
+
else
|
185
|
+
vol_array = Array.new
|
186
|
+
vol_array << snapshot
|
187
|
+
result.store(snapshot.volume_id, vol_array)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
result
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
def purge_snapshot(snapshot_id)
|
195
|
+
begin
|
196
|
+
response = @ec2.delete_snapshot(:snapshot_id => snapshot_id)
|
197
|
+
if (response[return]) then
|
198
|
+
puts("[INFO] Purged snapshot #{snapshot_id}")
|
199
|
+
end
|
200
|
+
rescue AWS::Error => e
|
201
|
+
puts("[WARNING] Could not purge snapshot #{snapshot_id}")
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
data/lib/aebus_zones.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'cron_parser'
|
3
|
+
require_relative 'volume'
|
4
|
+
|
5
|
+
module Aebus
|
6
|
+
|
7
|
+
module Config
|
8
|
+
|
9
|
+
class Config
|
10
|
+
|
11
|
+
DEFAULT_STRING = 'default'
|
12
|
+
|
13
|
+
attr_reader :defaults, :volumes
|
14
|
+
|
15
|
+
def initialize(filename, current_time_utc)
|
16
|
+
|
17
|
+
yaml_root = YAML::load(File.open(filename))
|
18
|
+
raise "Cannot find configuration file" unless yaml_root
|
19
|
+
|
20
|
+
@defaults = yaml_root.delete(DEFAULT_STRING)
|
21
|
+
default_backups = BackupSchedule.parse_backups_config(current_time_utc, @defaults["backups"])
|
22
|
+
|
23
|
+
@volumes = Hash.new
|
24
|
+
yaml_root.each_pair do |k, v|
|
25
|
+
@volumes[k] = Volume.new(current_time_utc, k, v, default_backups)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def volume_ids
|
31
|
+
|
32
|
+
result = Array.new
|
33
|
+
@volumes.each_key do |k|
|
34
|
+
result << k
|
35
|
+
end
|
36
|
+
|
37
|
+
result
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_value_for_volume(volume_id, key)
|
42
|
+
result = nil
|
43
|
+
if (@volumes.include? volume_id) then
|
44
|
+
if (@volumes[volume_id].config.include? key) then
|
45
|
+
result = @volumes[volume_id].config[key]
|
46
|
+
else
|
47
|
+
result = @defaults[key]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'cron_parser'
|
2
|
+
|
3
|
+
module Aebus
|
4
|
+
|
5
|
+
module Config
|
6
|
+
|
7
|
+
KEEP_ALL = "all"
|
8
|
+
|
9
|
+
class BackupSchedule
|
10
|
+
|
11
|
+
attr_reader :label, :last_deadline, :next_deadline, :keep
|
12
|
+
|
13
|
+
def initialize (current_time_utc, label, backup_config)
|
14
|
+
@label = label
|
15
|
+
if (backup_config["enabled"]) then
|
16
|
+
calculate_deadlines(current_time_utc, backup_config["when"])
|
17
|
+
end
|
18
|
+
@keep = backup_config["keep"]
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def calculate_deadlines(current_time_utc, when_string)
|
23
|
+
raise(ArgumentError, "when field cannot be empty if the backup is enabled") unless when_string
|
24
|
+
|
25
|
+
parser = CronParser.new (when_string)
|
26
|
+
@last_deadline = parser.last(current_time_utc)
|
27
|
+
@next_deadline = parser.next(current_time_utc)
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"Backup Schedule: label => #{@label} last_deadline => #{@last_deadline} next_deadline => #{@next_deadline} keep => #{@keep}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.parse_backups_config(current_time_utc, backups_config)
|
36
|
+
|
37
|
+
return nil unless backups_config
|
38
|
+
|
39
|
+
result = Hash.new
|
40
|
+
|
41
|
+
backups_config.each_pair do |key,value|
|
42
|
+
result.store(key, BackupSchedule.new(current_time_utc, key, value))
|
43
|
+
end
|
44
|
+
|
45
|
+
result
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class Volume
|
52
|
+
|
53
|
+
attr_reader :id, :config
|
54
|
+
|
55
|
+
def initialize(current_time_utc, volume_id, config, default_backups)
|
56
|
+
|
57
|
+
@config = config
|
58
|
+
@id = volume_id
|
59
|
+
@backups = default_backups ? default_backups.dup : Hash.new
|
60
|
+
if (config && config["backups"]) then
|
61
|
+
@backups.merge(BackupSchedule.parse_backups_config(current_time_utc,config["backups"]))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def backups_to_be_run(snapshots)
|
66
|
+
|
67
|
+
result = Array.new
|
68
|
+
|
69
|
+
@backups.each_pair do |k,v|
|
70
|
+
|
71
|
+
result << k unless recent_backup?(k, snapshots, v.last_deadline)
|
72
|
+
|
73
|
+
end
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
def recent_backup?(label, snapshots, last_deadline)
|
78
|
+
|
79
|
+
snapshots.each do |snapshot|
|
80
|
+
|
81
|
+
if (snapshot.aebus_tags_include?(label) && (snapshot.start_time > last_deadline))
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
false
|
87
|
+
end
|
88
|
+
|
89
|
+
def purgeable_snapshots(snapshots)
|
90
|
+
puts(snapshots.count)
|
91
|
+
removables = snapshots.select{|snapshot| snapshot.aebus_removable_snapshot?}
|
92
|
+
puts(removables.count)
|
93
|
+
available_backups = @backups.each_with_object({}) { | (k, v) , h | h[k] = v.keep}
|
94
|
+
removables.each do |snapshot|
|
95
|
+
snapshot.aebus_tags.each do |tag|
|
96
|
+
if (available_backups.include? tag) then
|
97
|
+
if (KEEP_ALL.eql?(available_backups[tag])) then
|
98
|
+
puts("Keeping snapshot #{snapshot.id} because of all on #{tag}")
|
99
|
+
snapshot.keep = true
|
100
|
+
elsif (available_backups[tag] > 0) then
|
101
|
+
snapshot.keep = true
|
102
|
+
available_backups[tag] -= 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
removables.select{|snapshot| !snapshot.keep? }
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
data/lib/ec2/snapshot.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Aebus
|
2
|
+
|
3
|
+
module EC2
|
4
|
+
|
5
|
+
AEBUS_TAG = "Aebus"
|
6
|
+
AEBUS_MANUAL_TAG = "manual"
|
7
|
+
AEBUS_KEEP_TAG = "keep"
|
8
|
+
AEBUS_AUTO_TAG = "auto"
|
9
|
+
|
10
|
+
class Snapshot
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
attr_reader :start_time, :volume_id, :id, :tags
|
15
|
+
|
16
|
+
def initialize(hash)
|
17
|
+
|
18
|
+
raise(ArgumentError,"hash cannot be nil") unless hash
|
19
|
+
@keep
|
20
|
+
@id = hash.snapshotId
|
21
|
+
@start_time = Time.parse(hash.startTime)
|
22
|
+
@volume_id = hash.volumeId
|
23
|
+
@tags = Hash.new
|
24
|
+
if (hash.tagSet) then
|
25
|
+
tag_array = hash.tagSet.item
|
26
|
+
tag_array.each do |tag|
|
27
|
+
@tags.store(tag["key"],tag["value"])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
"{snapshot_id => #{@id}, volume_id => #{@volume_id}, start_time => #{@start_time}, tags => #{@tags} "
|
34
|
+
end
|
35
|
+
|
36
|
+
def aebus_tags_include?(label)
|
37
|
+
if aebus_snapshot? then
|
38
|
+
aebus_tags = @tags[AEBUS_TAG].split(',')
|
39
|
+
return aebus_tags.include? label
|
40
|
+
end
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def aebus_snapshot?
|
45
|
+
@tags.include?(AEBUS_TAG)
|
46
|
+
end
|
47
|
+
|
48
|
+
def aebus_removable_snapshot?
|
49
|
+
(aebus_tags & [AEBUS_MANUAL_TAG, AEBUS_KEEP_TAG]).count == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def aebus_tags
|
53
|
+
return nil unless aebus_snapshot?
|
54
|
+
@tags[AEBUS_TAG].split(',')
|
55
|
+
end
|
56
|
+
|
57
|
+
def keep= value
|
58
|
+
@keep = value
|
59
|
+
end
|
60
|
+
|
61
|
+
def keep?
|
62
|
+
@keep
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aebus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marco Sandrini
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-05 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: commander
|
16
|
+
requirement: &70097059520900 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 4.0.6
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70097059520900
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: parse-cron
|
27
|
+
requirement: &70097059520400 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.1
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70097059520400
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: amazon-ec2
|
38
|
+
requirement: &70097059519940 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.9.17
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70097059519940
|
47
|
+
description: A tool to automate snapshot management in EC2
|
48
|
+
email:
|
49
|
+
- nessche@gmail.com
|
50
|
+
executables:
|
51
|
+
- aebus
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- README
|
58
|
+
- Rakefile
|
59
|
+
- aebus.gemspec
|
60
|
+
- bin/aebus
|
61
|
+
- lib/aebus.rb
|
62
|
+
- lib/aebus/version.rb
|
63
|
+
- lib/aebus_zones.rb
|
64
|
+
- lib/config/config.rb
|
65
|
+
- lib/config/volume.rb
|
66
|
+
- lib/ec2/snapshot.rb
|
67
|
+
homepage: https://github.com/nessche/Aebus
|
68
|
+
licenses: []
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.8.10
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Automated EC2 BackUp Software
|
91
|
+
test_files: []
|