rudy 0.3.2 → 0.4.0
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/CHANGES.txt +53 -3
- data/README.rdoc +9 -5
- data/bin/rudy +115 -292
- data/bin/rudy-ec2 +107 -0
- data/lib/console.rb +322 -278
- data/lib/rudy.rb +78 -55
- data/lib/rudy/aws/ec2.rb +63 -5
- data/lib/rudy/command/addresses.rb +18 -13
- data/lib/rudy/command/backups.rb +175 -0
- data/lib/rudy/command/base.rb +664 -146
- data/lib/rudy/command/config.rb +77 -0
- data/lib/rudy/command/deploy.rb +12 -0
- data/lib/rudy/command/disks.rb +165 -195
- data/lib/rudy/command/environment.rb +42 -64
- data/lib/rudy/command/groups.rb +21 -19
- data/lib/rudy/command/images.rb +34 -19
- data/lib/rudy/command/instances.rb +46 -92
- data/lib/rudy/command/machines.rb +161 -0
- data/lib/rudy/command/metadata.rb +14 -30
- data/lib/rudy/command/release.rb +174 -0
- data/lib/rudy/command/volumes.rb +26 -10
- data/lib/rudy/config.rb +93 -0
- data/lib/rudy/metadata/backup.rb +1 -1
- data/lib/rudy/metadata/disk.rb +15 -50
- data/lib/rudy/scm/svn.rb +32 -21
- data/lib/rudy/utils.rb +2 -3
- data/lib/storable.rb +4 -0
- data/lib/tryouts.rb +40 -0
- data/rudy.gemspec +25 -9
- data/support/mailtest +40 -0
- data/support/rudy-ec2-startup +41 -15
- data/tryouts/console_tryout.rb +91 -0
- metadata +86 -11
- data/lib/drydock.rb +0 -524
- data/lib/rudy/command/stage.rb +0 -45
- data/lib/rudy/metadata/config.rb +0 -8
- data/lib/rudy/metadata/environment.rb +0 -0
data/lib/rudy.rb
CHANGED
@@ -1,29 +1,57 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
#
|
3
|
+
# No Ruby 1.9.1 support. Only 1.8.x for now :[
|
4
|
+
unless RUBY_VERSION < "1.9"
|
5
|
+
puts "Sorry! We're using the right_aws gem and it doesn't support Ruby 1.9 (md5 error)."
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'digest/md5'
|
12
|
+
require 'right_aws'
|
13
|
+
require 'stringio'
|
14
|
+
require 'ostruct'
|
15
|
+
require 'yaml'
|
16
|
+
require 'socket'
|
17
|
+
require 'tempfile'
|
18
|
+
|
19
|
+
require 'console'
|
20
|
+
require 'storable'
|
21
|
+
|
22
|
+
require 'net/ssh'
|
23
|
+
require 'net/ssh/gateway'
|
24
|
+
require 'net/ssh/multi'
|
25
|
+
require 'net/scp'
|
26
|
+
|
27
|
+
rescue LoadError => ex
|
28
|
+
puts "Problem requiring: #{ex.message}"
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
|
6
32
|
|
7
|
-
require 'console'
|
8
|
-
require 'storable'
|
9
33
|
|
10
34
|
module Rudy #:nodoc:
|
11
|
-
RUDY_DOMAIN =
|
12
|
-
RUDY_DELIM =
|
13
|
-
|
35
|
+
RUDY_DOMAIN = "rudy_state"
|
36
|
+
RUDY_DELIM = '-'
|
37
|
+
|
38
|
+
RUDY_CONFIG_DIR = File.join(ENV['HOME'] || ENV['USERPROFILE'], '.rudy')
|
39
|
+
RUDY_CONFIG_FILE = File.join(RUDY_CONFIG_DIR, 'config')
|
14
40
|
|
15
|
-
DEFAULT_REGION =
|
16
|
-
DEFAULT_ZONE =
|
17
|
-
DEFAULT_ENVIRONMENT =
|
18
|
-
DEFAULT_ROLE =
|
19
|
-
DEFAULT_POSITION =
|
41
|
+
DEFAULT_REGION = 'us-east-1'
|
42
|
+
DEFAULT_ZONE = 'us-east-1b'
|
43
|
+
DEFAULT_ENVIRONMENT = 'stage'
|
44
|
+
DEFAULT_ROLE = 'app'
|
45
|
+
DEFAULT_POSITION = '01'
|
20
46
|
|
21
|
-
DEFAULT_USER =
|
47
|
+
DEFAULT_USER = 'rudy'
|
48
|
+
|
49
|
+
SUPPORTED_SCM_NAMES = [:svn, :git]
|
22
50
|
|
23
51
|
module VERSION #:nodoc:
|
24
52
|
MAJOR = 0.freeze unless defined? MAJOR
|
25
|
-
MINOR =
|
26
|
-
TINY =
|
53
|
+
MINOR = 4.freeze unless defined? MINOR
|
54
|
+
TINY = 0.freeze unless defined? TINY
|
27
55
|
def self.to_s
|
28
56
|
[MAJOR, MINOR, TINY].join('.')
|
29
57
|
end
|
@@ -41,43 +69,18 @@ module Rudy #:nodoc:
|
|
41
69
|
def self.in_situ?
|
42
70
|
File.exists?('/etc/ec2/instance-id')
|
43
71
|
end
|
44
|
-
|
45
|
-
class Config < Storable
|
46
|
-
|
47
|
-
attr_accessor :path
|
48
|
-
|
49
|
-
field :userdata => Hash
|
50
|
-
|
51
|
-
def initialize(args={:path => nil})
|
52
|
-
@path = args[:path] || RUDY_CONFIG
|
53
|
-
@userdata = {
|
54
|
-
'default' => {
|
55
|
-
}
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
def get(name)
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
def exists?
|
64
|
-
File.exists?(@path)
|
65
|
-
end
|
66
|
-
end
|
67
72
|
end
|
68
73
|
|
69
74
|
require 'rudy/aws'
|
75
|
+
require 'rudy/config'
|
70
76
|
require 'rudy/metadata'
|
71
|
-
require 'rudy/scm/svn'
|
72
77
|
require 'rudy/utils'
|
73
78
|
require 'rudy/command/base'
|
74
79
|
|
75
|
-
#
|
80
|
+
# Require Command, MetaData, and SCM classes
|
76
81
|
begin
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
Dir.glob(File.join(RUDY_LIB, 'rudy', 'metadata', "*.rb")).each do |path|
|
82
|
+
# TODO: Use autoload
|
83
|
+
Dir.glob(File.join(RUDY_LIB, 'rudy', '{command,metadata,scm}', "*.rb")).each do |path|
|
81
84
|
require path
|
82
85
|
end
|
83
86
|
rescue LoadError => ex
|
@@ -93,7 +96,7 @@ end
|
|
93
96
|
# end
|
94
97
|
#
|
95
98
|
def capture(stream)
|
96
|
-
raise "We can only capture STDOUT or STDERR" unless stream == :stdout || stream == :stderr
|
99
|
+
#raise "We can only capture STDOUT or STDERR" unless stream == :stdout || stream == :stderr
|
97
100
|
|
98
101
|
# I'm using this to trap the annoying right_aws "peer certificate" warning.
|
99
102
|
# TODO: discover source of annoying right_aws warning and give it a hiding.
|
@@ -110,7 +113,19 @@ def capture(stream)
|
|
110
113
|
end
|
111
114
|
|
112
115
|
|
116
|
+
def write_to_file(filename, content, type)
|
117
|
+
type = (type == :append) ? 'a' : 'w'
|
118
|
+
f = File.open(filename,type)
|
119
|
+
f.puts content
|
120
|
+
f.close
|
121
|
+
end
|
122
|
+
|
113
123
|
def are_you_sure?(len=3)
|
124
|
+
if Drydock.debug?
|
125
|
+
puts 'DEBUG: skipping "are you sure" check'
|
126
|
+
return true
|
127
|
+
end
|
128
|
+
|
114
129
|
if STDIN.tty? # Only ask a question if there's a human
|
115
130
|
challenge = strand len
|
116
131
|
STDOUT.print "Are you sure? To continue type \"#{challenge}\": "
|
@@ -137,26 +152,27 @@ def strand( len=8, safe=true )
|
|
137
152
|
newpass
|
138
153
|
end
|
139
154
|
|
140
|
-
def sh(command, chdir=false)
|
155
|
+
def sh(command, chdir=false, verbose=false)
|
141
156
|
prevdir = Dir.pwd
|
142
157
|
Dir.chdir chdir if chdir
|
143
|
-
puts command if
|
158
|
+
puts command if verbose
|
144
159
|
system(command)
|
145
160
|
Dir.chdir prevdir if chdir
|
146
161
|
end
|
147
162
|
|
148
|
-
|
149
|
-
|
150
|
-
puts "CONNECTING TO #{host}..."
|
163
|
+
def ssh_command(host, keypair, user, command=false, printonly=false, verbose=false)
|
164
|
+
#puts "CONNECTING TO #{host}..."
|
151
165
|
cmd = "ssh -q -i #{keypair} #{user}@#{host} "
|
152
|
-
command = "cd #{chdir} && #{command}" if chdir
|
153
166
|
cmd += " '#{command}'" if command
|
154
167
|
puts cmd if verbose
|
155
|
-
|
168
|
+
return cmd if printonly
|
169
|
+
# backticks returns STDOUT
|
170
|
+
# exec replaces current process (it's just like running ssh)
|
171
|
+
(command) ? `#{cmd}` : Kernel.exec(cmd)
|
156
172
|
end
|
157
173
|
|
158
174
|
|
159
|
-
def
|
175
|
+
def scp_command(host, keypair, user, paths, to_path, to_local=false, verbose=false, printonly=false)
|
160
176
|
|
161
177
|
paths = [paths] unless paths.is_a?(Array)
|
162
178
|
from_paths = ""
|
@@ -181,6 +197,13 @@ def scp(host, keypair, user, paths, to_path, to_local=false, verbose=false, prin
|
|
181
197
|
end
|
182
198
|
|
183
199
|
|
200
|
+
# Returns +str+ with the average leading indentation removed.
|
201
|
+
# Useful for keeping inline codeblocks spaced with code.
|
202
|
+
def without_indent(str)
|
203
|
+
lines = str.split($/)
|
204
|
+
lspaces = (lines.inject(0) {|total,line| total += (line.scan(/^\s+/).first || '').size } / lines.size) + 1
|
205
|
+
lines.collect { |line| line.gsub(/^\s{#{lspaces}}/, '') }.join($/)
|
206
|
+
end
|
184
207
|
|
185
208
|
|
186
209
|
|
data/lib/rudy/aws/ec2.rb
CHANGED
@@ -57,7 +57,16 @@ module Rudy::AWS
|
|
57
57
|
class Volumes
|
58
58
|
include Rudy::AWS::ObjectBase
|
59
59
|
|
60
|
-
|
60
|
+
# [{:aws_device=>"/dev/sdr",
|
61
|
+
# :aws_attachment_status=>"attached",
|
62
|
+
# :snapshot_id=>nil,
|
63
|
+
# :aws_id=>"vol-6811f601",
|
64
|
+
# :aws_attached_at=>Wed Mar 11 07:06:44 UTC 2009,
|
65
|
+
# :aws_status=>"in-use",
|
66
|
+
# :aws_instance_id=>"i-0b2ab662",
|
67
|
+
# :aws_created_at=>Tue Mar 10 18:55:18 UTC 2009,
|
68
|
+
# :zone=>"us-east-1b",
|
69
|
+
# :aws_size=>10}]
|
61
70
|
def list
|
62
71
|
list = @aws.describe_volumes() || []
|
63
72
|
list.select { |v| v[:aws_status] != "deleting" }
|
@@ -86,7 +95,29 @@ module Rudy::AWS
|
|
86
95
|
false
|
87
96
|
end
|
88
97
|
|
98
|
+
def get(vol_id)
|
99
|
+
list = @aws.describe_volumes(vol_id) || []
|
100
|
+
list.first
|
101
|
+
end
|
102
|
+
|
103
|
+
def deleting?(vol_id)
|
104
|
+
return false unless vol_id
|
105
|
+
vol = get(vol_id)
|
106
|
+
(vol && vol[:aws_status] == "deleting")
|
107
|
+
end
|
89
108
|
|
109
|
+
def available?(vol_id)
|
110
|
+
return false unless vol_id
|
111
|
+
vol = get(vol_id)
|
112
|
+
(vol && vol[:aws_status] == "available")
|
113
|
+
end
|
114
|
+
|
115
|
+
def attached?(vol_id)
|
116
|
+
return false unless vol_id
|
117
|
+
vol = get(vol_id)
|
118
|
+
(vol && vol[:aws_status] == "in-use")
|
119
|
+
end
|
120
|
+
|
90
121
|
end
|
91
122
|
|
92
123
|
class Instances
|
@@ -95,11 +126,15 @@ module Rudy::AWS
|
|
95
126
|
def destroy(*list)
|
96
127
|
begin
|
97
128
|
@aws.terminate_instances(list.flatten)
|
98
|
-
rescue RightAws::AwsError => ex
|
99
|
-
|
129
|
+
#rescue RightAws::AwsError => ex
|
130
|
+
# raise UnknownInstance.new
|
100
131
|
end
|
101
132
|
end
|
102
133
|
|
134
|
+
def restart(*list)
|
135
|
+
@aws.reboot_instances(list.flatten)
|
136
|
+
end
|
137
|
+
|
103
138
|
def attached_volume?(id, device)
|
104
139
|
list = volumes(id)
|
105
140
|
list.each do |v|
|
@@ -113,6 +148,10 @@ module Rudy::AWS
|
|
113
148
|
list.select { |v| v[:aws_status] != "deleting" && v[:aws_instance_id] === id }
|
114
149
|
end
|
115
150
|
|
151
|
+
def device_volume(id, device)
|
152
|
+
volumes.select { |v| v[:aws_device] === device }
|
153
|
+
end
|
154
|
+
|
116
155
|
def create(ami, group, keypair_name, user_data, zone)
|
117
156
|
@aws.run_instances(ami, 1, 1, [group], keypair_name, user_data, 'public', nil, nil, nil, zone)
|
118
157
|
end
|
@@ -121,6 +160,24 @@ module Rudy::AWS
|
|
121
160
|
# that matches +filter+.
|
122
161
|
# Returns a hash. The keys are instance IDs and the values are a hash
|
123
162
|
# of attributes associated to that instance.
|
163
|
+
# {:aws_state_code=>"16",
|
164
|
+
# :private_dns_name=>"domU-12-31-38-00-51-F1.compute-1.internal",
|
165
|
+
# :aws_instance_type=>"m1.small",
|
166
|
+
# :aws_reason=>"",
|
167
|
+
# :ami_launch_index=>"0",
|
168
|
+
# :aws_owner=>"207436219441",
|
169
|
+
# :aws_launch_time=>"2009-03-11T06:55:00.000Z",
|
170
|
+
# :aws_kernel_id=>"aki-a71cf9ce",
|
171
|
+
# :ssh_key_name=>"rilli-sexytime",
|
172
|
+
# :aws_reservation_id=>"r-66f5710f",
|
173
|
+
# :aws_state=>"running",
|
174
|
+
# :aws_ramdisk_id=>"ari-a51cf9cc",
|
175
|
+
# :aws_instance_id=>"i-0b2ab662",
|
176
|
+
# :aws_groups=>["rudydev-app"],
|
177
|
+
# :aws_availability_zone=>"us-east-1b",
|
178
|
+
# :aws_image_id=>"ami-daca2db3",
|
179
|
+
# :aws_product_codes=>[],
|
180
|
+
# :dns_name=>"ec2-67-202-9-30.compute-1.amazonaws.com"}
|
124
181
|
def list(filter='.')
|
125
182
|
filter = filter.to_s.downcase.tr('_|-', '.') # treat dashes, underscores as one
|
126
183
|
# Returns an array of hashes with the following keys:
|
@@ -138,6 +195,7 @@ module Rudy::AWS
|
|
138
195
|
end
|
139
196
|
|
140
197
|
def get(inst_id)
|
198
|
+
# This is ridiculous. Send inst_id to describe volumes
|
141
199
|
instance = {}
|
142
200
|
list.each_pair do |id, hash|
|
143
201
|
next unless inst_id == id
|
@@ -178,8 +236,8 @@ module Rudy::AWS
|
|
178
236
|
|
179
237
|
# Create a new EC2 security group
|
180
238
|
# Returns true/false whether successful
|
181
|
-
def create(name, desc=
|
182
|
-
@aws.create_security_group(name, desc)
|
239
|
+
def create(name, desc=nil)
|
240
|
+
@aws.create_security_group(name, desc || "Group #{name}")
|
183
241
|
end
|
184
242
|
|
185
243
|
# Delete an EC2 security group
|
@@ -4,25 +4,31 @@
|
|
4
4
|
module Rudy
|
5
5
|
module Command
|
6
6
|
class Addresses < Rudy::Command::Base
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
raise "
|
7
|
+
|
8
|
+
|
9
|
+
def associate_addresses_valid?
|
10
|
+
raise "You have not supplied an IP addresses" unless @argv.address
|
11
|
+
raise "You did not supply an instance ID" unless @argv.instanceid
|
12
|
+
|
13
|
+
@inst = @ec2.instances.get(@argv.instanceid)
|
14
|
+
raise "Instance #{@inst[:aws_instance_id]} does not exist!" unless @inst
|
12
15
|
|
13
|
-
raise "
|
14
|
-
raise "
|
15
|
-
raise "#{address} is already associated!" if @ec2.addresses.associated?(address)
|
16
|
+
raise "That's not an elastic IP you own!" unless @ec2.addresses.valid?(@argv.address)
|
17
|
+
raise "#{@argv.address} is already associated!" if @ec2.addresses.associated?(@argv.address)
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def associate_addresses
|
23
|
+
puts "Associating #{@argv.address} to #{@inst[:aws_groups]}: #{@inst[:dns_name]}"
|
24
|
+
@ec2.addresses.associate(@inst[:aws_instance_id], @argv.address)
|
19
25
|
puts "Done!"
|
20
26
|
puts
|
21
27
|
|
22
|
-
|
28
|
+
addresses
|
23
29
|
end
|
24
30
|
|
25
|
-
def
|
31
|
+
def addresses
|
26
32
|
puts "Elastic IP mappings:"
|
27
33
|
@ec2.addresses.list.each do |address|
|
28
34
|
print "IP: #{address[:public_ip]} "
|
@@ -34,7 +40,6 @@ module Rudy
|
|
34
40
|
puts
|
35
41
|
end
|
36
42
|
|
37
|
-
|
38
43
|
end
|
39
44
|
end
|
40
45
|
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
module Rudy
|
6
|
+
module Command
|
7
|
+
class Backups < Rudy::Command::Base
|
8
|
+
|
9
|
+
|
10
|
+
def backup
|
11
|
+
criteria = [@global.zone]
|
12
|
+
criteria += [@global.environment, @global.role] unless @option.all
|
13
|
+
|
14
|
+
Rudy::MetaData::Backup.list(@sdb, *criteria).each do |backup|
|
15
|
+
puts "%s (%s)" % [backup.name, backup.awsid]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Check for backups pointing to snapshots that don't exist.
|
20
|
+
def sync_backup
|
21
|
+
unless argv.empty?
|
22
|
+
puts "The disk you specified will be ignored."
|
23
|
+
argv.clear
|
24
|
+
end
|
25
|
+
|
26
|
+
criteria = [@global.zone]
|
27
|
+
criteria += [@global.environment, @global.role] unless @option.all
|
28
|
+
|
29
|
+
puts "Looking for backup metadata with delinquent snapshots..."
|
30
|
+
to_be_deleted = {} # snap-id => backup
|
31
|
+
Rudy::MetaData::Backup.list(@sdb, *criteria).each do |backup|
|
32
|
+
to_be_deleted[backup.awsid] = backup unless @ec2.snapshots.exists?(backup.awsid)
|
33
|
+
end
|
34
|
+
|
35
|
+
if to_be_deleted.empty?
|
36
|
+
puts "All backups are in-sync with snapshots. Nothing to do."
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
puts
|
41
|
+
puts "These backup metadata will be deleted:"
|
42
|
+
to_be_deleted.each do |snap_id, backup|
|
43
|
+
puts "%s: %s" % [snap_id, backup.name]
|
44
|
+
end
|
45
|
+
|
46
|
+
puts
|
47
|
+
are_you_sure?
|
48
|
+
|
49
|
+
puts
|
50
|
+
puts "Deleting..."
|
51
|
+
to_be_deleted.each do |snap_id, backup|
|
52
|
+
print " -> #{backup.name}... "
|
53
|
+
@sdb.destroy(RUDY_DOMAIN, backup.name)
|
54
|
+
puts "done"
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "Done!"
|
58
|
+
end
|
59
|
+
|
60
|
+
def destroy_backup_valid?
|
61
|
+
raise "No backup specified" if argv.empty?
|
62
|
+
exit unless are_you_sure?(5)
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def destroy_backup
|
67
|
+
name = @argv.first
|
68
|
+
puts "Destroying #{name}"
|
69
|
+
begin
|
70
|
+
backup = Rudy::MetaData::Backup.get(@sdb, name)
|
71
|
+
rescue => ex
|
72
|
+
puts "Error deleteing backup: #{ex.message}"
|
73
|
+
end
|
74
|
+
|
75
|
+
return unless backup
|
76
|
+
|
77
|
+
begin
|
78
|
+
puts " -> deleting snapshot..."
|
79
|
+
@ec2.snapshots.destroy(backup.awsid)
|
80
|
+
rescue => ex
|
81
|
+
puts "Error deleting snapshot: #{ex.message}."
|
82
|
+
puts "Continuing..."
|
83
|
+
ensure
|
84
|
+
puts " -> deleting metadata..."
|
85
|
+
@sdb.destroy(RUDY_DOMAIN, name)
|
86
|
+
end
|
87
|
+
puts "Done."
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_backup
|
91
|
+
diskname = @argv.first
|
92
|
+
|
93
|
+
machine = find_current_machine
|
94
|
+
|
95
|
+
disks = Rudy::MetaData::Disk.list(@sdb, machine[:aws_availability_zone], @global.environment, @global.role, @global.position)
|
96
|
+
raise "The machine #{machine_name} does not have any disk metadata" if disks.empty?
|
97
|
+
|
98
|
+
puts "Machine: #{machine_name}"
|
99
|
+
|
100
|
+
if @option.snapshot
|
101
|
+
raise "You must supply a diskname when using an existing snapshot" unless diskname
|
102
|
+
raise "The snapshot #{@option.snapshot} does not exist" unless @ec2.snapshots.exists?(@option.snapshot)
|
103
|
+
disk = Rudy::MetaData::Disk.get(@sdb, diskname)
|
104
|
+
|
105
|
+
raise "The disk #{diskname} does not exist" unless disk
|
106
|
+
backup = Rudy::MetaData::Backup.new
|
107
|
+
backup.awsid = @option.snapshot
|
108
|
+
backup.time_stamp
|
109
|
+
|
110
|
+
# Populate machine infos
|
111
|
+
[:zone, :environment, :role, :position].each do |n|
|
112
|
+
backup.send("#{n}=", @global.send(n)) if @global.send(n)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Populate disk infos
|
116
|
+
[:path, :size].each do |n|
|
117
|
+
backup.send("#{n}=", disk.send(n)) if disk.send(n)
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
Rudy::MetaData::Backup.save(@sdb, backup)
|
122
|
+
|
123
|
+
puts backup.name
|
124
|
+
|
125
|
+
else
|
126
|
+
volumes = @ec2.instances.volumes(machine[:aws_instance_id])
|
127
|
+
raise "The machine #{machine_name} does not have any volumes attached." if volumes.empty?
|
128
|
+
|
129
|
+
puts "#{disks.size} Disk(s) defined with #{volumes.size} Volume(s) running"
|
130
|
+
|
131
|
+
volumes.each do |volume|
|
132
|
+
print "Volume #{volume[:aws_id]}... "
|
133
|
+
disk = Rudy::MetaData::Disk.find_from_volume(@sdb, volume[:aws_id])
|
134
|
+
backup = Rudy::MetaData::Backup.new
|
135
|
+
|
136
|
+
# TODO: Look for the disk based on the machine
|
137
|
+
raise "No disk associated to volume #{volume[:aws_id]}" unless disk
|
138
|
+
|
139
|
+
backup.volume = volume[:aws_id]
|
140
|
+
|
141
|
+
# Populate machine infos
|
142
|
+
[:zone, :environment, :role, :position].each do |n|
|
143
|
+
backup.send("#{n}=", @global.send(n)) if @global.send(n)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Populate disk infos
|
147
|
+
[:path, :size].each do |n|
|
148
|
+
backup.send("#{n}=", disk.send(n)) if disk.send(n)
|
149
|
+
end
|
150
|
+
|
151
|
+
backup.time_stamp
|
152
|
+
|
153
|
+
raise "There was a problem creating the backup metadata" unless backup.valid?
|
154
|
+
|
155
|
+
snap = @ec2.snapshots.create(volume[:aws_id])
|
156
|
+
|
157
|
+
if !snap || !snap.is_a?(Hash)
|
158
|
+
puts "There was an unknown problem creating #{backup.name}. Continuing with the next volume..."
|
159
|
+
next
|
160
|
+
end
|
161
|
+
|
162
|
+
backup.awsid = snap[:aws_id]
|
163
|
+
|
164
|
+
Rudy::MetaData::Backup.save(@sdb, backup)
|
165
|
+
|
166
|
+
puts backup.name
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|