rudy 0.8.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +110 -18
- data/README.rdoc +40 -44
- data/Rudyfile +35 -50
- data/bin/rudy +88 -57
- data/bin/rudy-ec2 +2 -16
- data/bin/rudy-s3 +0 -10
- data/bin/rudy-sdb +11 -12
- data/lib/rudy.rb +59 -91
- data/lib/rudy/aws.rb +4 -45
- data/lib/rudy/aws/ec2.rb +57 -20
- data/lib/rudy/aws/ec2/address.rb +10 -11
- data/lib/rudy/aws/ec2/group.rb +10 -9
- data/lib/rudy/aws/ec2/image.rb +8 -8
- data/lib/rudy/aws/ec2/instance.rb +18 -19
- data/lib/rudy/aws/ec2/keypair.rb +14 -19
- data/lib/rudy/aws/ec2/snapshot.rb +16 -9
- data/lib/rudy/aws/ec2/volume.rb +39 -26
- data/lib/rudy/aws/ec2/zone.rb +5 -4
- data/lib/rudy/aws/s3.rb +2 -1
- data/lib/rudy/aws/sdb.rb +35 -86
- data/lib/rudy/backups.rb +24 -0
- data/lib/rudy/cli.rb +5 -131
- data/lib/rudy/cli/aws/ec2/addresses.rb +19 -27
- data/lib/rudy/cli/aws/ec2/candy.rb +45 -20
- data/lib/rudy/cli/aws/ec2/groups.rb +9 -13
- data/lib/rudy/cli/aws/ec2/images.rb +5 -133
- data/lib/rudy/cli/aws/ec2/instances.rb +25 -25
- data/lib/rudy/cli/aws/ec2/keypairs.rb +7 -11
- data/lib/rudy/cli/aws/ec2/snapshots.rb +5 -9
- data/lib/rudy/cli/aws/ec2/volumes.rb +22 -23
- data/lib/rudy/cli/aws/ec2/zones.rb +2 -3
- data/lib/rudy/cli/aws/sdb/domains.rb +5 -6
- data/lib/rudy/cli/aws/sdb/objects.rb +33 -0
- data/lib/rudy/cli/aws/sdb/select.rb +23 -0
- data/lib/rudy/cli/backups.rb +38 -0
- data/lib/rudy/cli/base.rb +104 -0
- data/lib/rudy/cli/candy.rb +1 -2
- data/lib/rudy/cli/config.rb +20 -7
- data/lib/rudy/cli/disks.rb +7 -9
- data/lib/rudy/cli/execbase.rb +56 -0
- data/lib/rudy/cli/machines.rb +242 -45
- data/lib/rudy/cli/metadata.rb +24 -10
- data/lib/rudy/cli/networks.rb +34 -0
- data/lib/rudy/cli/routines.rb +32 -6
- data/lib/rudy/cli/status.rb +60 -0
- data/lib/rudy/config.rb +55 -32
- data/lib/rudy/config/objects.rb +44 -30
- data/lib/rudy/disks.rb +25 -0
- data/lib/rudy/exceptions.rb +99 -0
- data/lib/rudy/global.rb +67 -28
- data/lib/rudy/guidelines.rb +3 -2
- data/lib/rudy/huxtable.rb +67 -58
- data/lib/rudy/machines.rb +41 -263
- data/lib/rudy/metadata.rb +212 -38
- data/lib/rudy/metadata/backup.rb +123 -78
- data/lib/rudy/metadata/disk.rb +153 -170
- data/lib/rudy/metadata/machine.rb +179 -0
- data/lib/rudy/mixins.rb +2 -1
- data/lib/rudy/mixins/hash.rb +3 -1
- data/lib/rudy/mixins/symbol.rb +8 -0
- data/lib/rudy/routines.rb +127 -344
- data/lib/rudy/routines/base.rb +229 -0
- data/lib/rudy/routines/handlers/base.rb +48 -0
- data/lib/rudy/routines/handlers/depends.rb +49 -0
- data/lib/rudy/routines/handlers/disks.rb +249 -0
- data/lib/rudy/routines/handlers/group.rb +44 -0
- data/lib/rudy/routines/handlers/host.rb +70 -0
- data/lib/rudy/routines/handlers/keypair.rb +70 -0
- data/lib/rudy/routines/handlers/machines.rb +15 -0
- data/lib/rudy/routines/handlers/script.rb +85 -0
- data/lib/rudy/routines/handlers/user.rb +45 -0
- data/lib/rudy/routines/passthrough.rb +19 -23
- data/lib/rudy/routines/reboot.rb +98 -50
- data/lib/rudy/routines/shutdown.rb +65 -14
- data/lib/rudy/routines/startup.rb +112 -17
- data/lib/rudy/utils.rb +35 -68
- data/rudy.gemspec +82 -25
- data/tryouts/01_mixins/01_hash_tryouts.rb +20 -0
- data/tryouts/10_require_time/10_rudy_tryouts.rb +33 -0
- data/tryouts/10_require_time/15_global_tryouts.rb +58 -0
- data/tryouts/12_config/10_load_config_tryouts.rb +43 -0
- data/tryouts/12_config/20_defaults_tryouts.rb +16 -0
- data/tryouts/12_config/30_accounts_tryouts.rb +17 -0
- data/tryouts/12_config/40_machines_tryouts.rb +53 -0
- data/tryouts/12_config/50_commands_tryouts.rb +17 -0
- data/tryouts/12_config/60_routines_tryouts.rb +16 -0
- data/tryouts/15_huxtable/10_huxtable_tryouts.rb +47 -0
- data/tryouts/15_huxtable/20_user_tryouts.rb +47 -0
- data/tryouts/20_simpledb/10_domains_tryouts.rb +36 -0
- data/tryouts/20_simpledb/20_objects_tryouts.rb +56 -0
- data/tryouts/25_ec2/10_keypairs_tryouts.rb +54 -0
- data/tryouts/25_ec2/20_groups_tryouts.rb +56 -0
- data/tryouts/25_ec2/21_groups_authorize_address_tryouts.rb +53 -0
- data/tryouts/25_ec2/22_groups_authorize_account_tryouts.rb +54 -0
- data/tryouts/25_ec2/30_addresses_tryouts.rb +42 -0
- data/tryouts/25_ec2/40_volumes_tryouts.rb +53 -0
- data/tryouts/25_ec2/50_snapshots_tryouts.rb +75 -0
- data/tryouts/26_ec2_instances/10_instance_tryouts.rb +107 -0
- data/tryouts/26_ec2_instances/50_images_tryouts.rb +7 -0
- data/tryouts/30_metadata/10_include_tryouts.rb +45 -0
- data/tryouts/30_metadata/13_object_tryouts.rb +19 -0
- data/tryouts/30_metadata/50_disk_tryouts.rb +115 -0
- data/tryouts/30_metadata/51_disk_digest_tryouts.rb +24 -0
- data/tryouts/30_metadata/53_disk_list_tryouts.rb +35 -0
- data/tryouts/30_metadata/56_disk_volume_tryouts.rb +68 -0
- data/tryouts/30_metadata/60_backup_tryouts.rb +101 -0
- data/tryouts/30_metadata/63_backup_list_tryouts.rb +38 -0
- data/tryouts/30_metadata/64_backup_disk_tryouts.rb +65 -0
- data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +76 -0
- data/tryouts/30_metadata/70_machine_tryouts.rb +85 -0
- data/tryouts/30_metadata/73_machine_list_tryouts.rb +58 -0
- data/tryouts/30_metadata/76_machine_instance_tryouts.rb +64 -0
- data/tryouts/30_metadata/77_machines_tryouts.rb +45 -0
- data/tryouts/40_routines/10_keypair_handler_tryouts.rb +52 -0
- data/tryouts/40_routines/11_group_handler_tryouts.rb +36 -0
- data/tryouts/80_cli/10_rudyec2_tryouts.rb +8 -0
- data/tryouts/80_cli/60_rudy_tryouts.rb +41 -0
- data/tryouts/exploration/console.rb +91 -0
- data/tryouts/exploration/machine.rb +23 -0
- data/tryouts/failer +6 -0
- metadata +116 -32
- data/bin/ird +0 -153
- data/lib/rudy/metadata/backups.rb +0 -67
- data/lib/rudy/metadata/debug.rb +0 -38
- data/lib/rudy/metadata/disks.rb +0 -67
- data/lib/rudy/metadata/objectbase.rb +0 -108
- data/lib/rudy/routines/helper.rb +0 -76
- data/lib/rudy/routines/helpers/dependshelper.rb +0 -34
- data/lib/rudy/routines/helpers/diskhelper.rb +0 -403
- data/lib/rudy/routines/helpers/scripthelper.rb +0 -197
- data/lib/rudy/routines/helpers/userhelper.rb +0 -37
- data/support/rudy-ec2-startup +0 -200
data/lib/rudy/machines.rb
CHANGED
@@ -1,293 +1,71 @@
|
|
1
|
-
|
2
1
|
|
3
2
|
|
4
3
|
module Rudy
|
5
|
-
class Machine < Storable
|
6
|
-
include Rudy::MetaData::ObjectBase
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
field :region
|
12
|
-
field :zone
|
13
|
-
field :environment
|
14
|
-
field :role
|
15
|
-
field :position
|
16
|
-
|
17
|
-
field :created => Time
|
18
|
-
field :started => Time
|
19
|
-
|
20
|
-
field :dns_public
|
21
|
-
field :dns_private
|
22
|
-
field :state
|
23
|
-
|
24
|
-
field :os
|
25
|
-
|
26
|
-
attr_reader :instance
|
27
|
-
|
28
|
-
def init
|
29
|
-
#@created =
|
30
|
-
@rtype = 'm'
|
31
|
-
@region = @@global.region
|
32
|
-
@zone = @@global.zone
|
33
|
-
@environment = @@global.environment
|
34
|
-
@role = @@global.role
|
35
|
-
@position = find_next_position || '01'
|
36
|
-
@state = 'no-instance'
|
37
|
-
@os = 'unknown'
|
38
|
-
end
|
5
|
+
module Machines
|
6
|
+
RTYPE = 'm'.freeze
|
39
7
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
"%s %s" % [self.name.bright, info]
|
44
|
-
end
|
8
|
+
extend self
|
9
|
+
extend Rudy::Metadata::ClassMethods
|
10
|
+
extend Rudy::Huxtable
|
45
11
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# lines << @@sformat % %w{zone size ami keyname groups} if with_title
|
52
|
-
# lines << @@sformat % [@zone, @size, @ami, k, g]
|
53
|
-
#end
|
54
|
-
lines.join($/)
|
12
|
+
def get(position)
|
13
|
+
tmp = Rudy::Machine.new position
|
14
|
+
record = Rudy::Metadata.get tmp.name
|
15
|
+
return nil unless record.is_a?(Hash)
|
16
|
+
tmp.from_hash record
|
55
17
|
end
|
56
18
|
|
57
|
-
def inspect
|
58
|
-
update #if !dns_public? && @awsid
|
59
|
-
lines = []
|
60
|
-
lines << liner_note
|
61
|
-
field_names.each do |key|
|
62
|
-
next unless self.respond_to?(key)
|
63
|
-
val = self.send(key)
|
64
|
-
lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
|
65
|
-
end
|
66
|
-
lines.join($/)
|
67
|
-
end
|
68
|
-
|
69
19
|
def find_next_position
|
70
|
-
|
20
|
+
raise "reimplement by looking at position values"
|
21
|
+
list = Rudy::Machines.list({}, [:position]) || []
|
71
22
|
pos = list.size + 1
|
72
23
|
pos.to_s.rjust(2, '0')
|
73
24
|
end
|
74
25
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
def Machine.generate_name(zon, env, rol, pos)
|
80
|
-
pos = pos.to_s.rjust 2, '0'
|
81
|
-
["m", zon, env, rol, pos].join(Rudy::DELIM)
|
26
|
+
# Returns true if any machine metadata exists for this group
|
27
|
+
def exists?(pos=nil)
|
28
|
+
machines = pos.nil? ? list : get(pos)
|
29
|
+
!machines.nil?
|
82
30
|
end
|
83
31
|
|
84
|
-
|
85
|
-
|
32
|
+
# Returns true if all machines in the group are running instances
|
33
|
+
def running?(pos=nil)
|
34
|
+
group = pos.nil? ? list : [get(pos)].compact
|
35
|
+
return false if group.nil? || group.empty?
|
36
|
+
group.collect! { |m| m.instance_running? }
|
37
|
+
!group.member?(false)
|
86
38
|
end
|
87
39
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
elsif @instance.nil?
|
97
|
-
@awsid = @dns_public = @dns_private = nil
|
98
|
-
@state = 'rogue'
|
99
|
-
# Don't save it b/c it's possible the EC2 server is just down.
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def dns_public?
|
104
|
-
!@dns_public.nil? && !@dns_public.empty?
|
105
|
-
end
|
106
|
-
def dns_private?
|
107
|
-
!@dns_private.nil? && !@dns_private.empty?
|
108
|
-
end
|
109
|
-
|
110
|
-
def start(opts={})
|
111
|
-
raise "#{name} is already running" if running?
|
112
|
-
|
113
|
-
opts = {
|
114
|
-
:min => 1,
|
115
|
-
:size => current_machine_size,
|
116
|
-
:ami => current_machine_image,
|
117
|
-
:group => current_group_name,
|
118
|
-
:keypair => root_keypairname,
|
119
|
-
:zone => @@global.zone.to_s,
|
120
|
-
:machine_data => Machine.generate_machine_data.to_yaml
|
121
|
-
}.merge(opts)
|
122
|
-
|
123
|
-
@os = current_machine_os
|
124
|
-
|
125
|
-
@ec2inst.create(opts) do |inst|
|
126
|
-
@awsid = inst.awsid
|
127
|
-
@created = @starts = Time.now
|
128
|
-
@state = inst.state
|
129
|
-
# We need to be safe when creating machines because if an exception is
|
130
|
-
# raised, instances will have been creating but the calling class won't know.
|
131
|
-
begin
|
132
|
-
address = current_machine_address(@position)
|
133
|
-
# Assign IP address only if we have one for that position
|
134
|
-
if address
|
135
|
-
# Make sure the address is associated to the current account
|
136
|
-
if @radd.exists?(address)
|
137
|
-
puts "Associating #{address} to #{inst.awsid}"
|
138
|
-
@radd.associate(address, inst.awsid)
|
139
|
-
else
|
140
|
-
STDERR.puts "Unknown address: #{address}"
|
141
|
-
end
|
142
|
-
end
|
143
|
-
rescue => ex
|
144
|
-
STDERR.puts "Error: #{ex.message}"
|
145
|
-
STDERR.puts ex.backtrace if Rudy.debug?
|
40
|
+
# Returns an Array of newly created Rudy::Machine objects
|
41
|
+
def create(size=nil)
|
42
|
+
if Rudy::Huxtable.global.position.nil?
|
43
|
+
size ||= current_machine_count.to_i || 1
|
44
|
+
group = Array.new(size) do |i|
|
45
|
+
m = Rudy::Machine.new(i + 1)
|
46
|
+
m.create
|
47
|
+
m
|
146
48
|
end
|
147
|
-
end
|
148
|
-
|
149
|
-
self.save
|
150
|
-
|
151
|
-
self
|
152
|
-
end
|
153
|
-
|
154
|
-
def destroy
|
155
|
-
@ec2inst.destroy(@awsid) if running?
|
156
|
-
super
|
157
|
-
end
|
158
|
-
|
159
|
-
def restart
|
160
|
-
@ec2inst.restart(@awsid) if running?
|
161
|
-
end
|
162
|
-
|
163
|
-
def Machine.generate_machine_data
|
164
|
-
data = { # Give the machine an identity
|
165
|
-
:region => @@global.region.to_s,
|
166
|
-
:zone => @@global.zone.to_s,
|
167
|
-
:environment => @@global.environment.to_s,
|
168
|
-
:role => @@global.role.to_s,
|
169
|
-
:position => @@global.position.to_s,
|
170
|
-
:hosts => { # Add hosts to the /etc/hosts file
|
171
|
-
:dbmaster => "127.0.0.1",
|
172
|
-
}
|
173
|
-
}
|
174
|
-
data
|
175
|
-
end
|
176
|
-
|
177
|
-
def running?
|
178
|
-
return false if @awsid.nil? || @awsid.empty?
|
179
|
-
@ec2inst.running?(@awsid) rescue nil
|
180
|
-
end
|
181
|
-
|
182
|
-
end
|
183
|
-
|
184
|
-
|
185
|
-
class Machines
|
186
|
-
include Rudy::MetaData
|
187
|
-
|
188
|
-
def create(&each_mach)
|
189
|
-
raise MachineGroupAlreadyRunning, current_machine_group if running?
|
190
|
-
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
191
|
-
|
192
|
-
unless (1..MAX_INSTANCES).member?(current_machine_count)
|
193
|
-
raise "Instance count must be more than 0, less than #{MAX_INSTANCES}"
|
194
|
-
end
|
195
|
-
|
196
|
-
unless @rgrp.exists?(current_group_name)
|
197
|
-
puts "Creating group: #{current_group_name}"
|
198
|
-
@rgrp.create(current_group_name)
|
199
|
-
end
|
200
|
-
|
201
|
-
unless @rkey.exists?(root_keypairname)
|
202
|
-
kp_file = File.join(Rudy::CONFIG_DIR, root_keypairname)
|
203
|
-
raise PrivateKeyFileExists, kp_file if File.exists?(kp_file)
|
204
|
-
puts "Creating keypair: #{root_keypairname}"
|
205
|
-
kp = @rkey.create(root_keypairname)
|
206
|
-
puts "Saving #{kp_file}"
|
207
|
-
Rudy::Utils.write_to_file(kp_file, kp.private_key, 'w', 0600)
|
208
49
|
else
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
# This means we found a keypair in the config but we cannot find the private key file.
|
213
|
-
raise PrivateKeyNotFound, kp_file if !File.exists?(kp_file)
|
214
|
-
end
|
215
|
-
|
216
|
-
machines = []
|
217
|
-
current_machine_count.times do |i|
|
218
|
-
machine = Rudy::Machine.new
|
219
|
-
|
220
|
-
#puts "Starting %s" % machine.name
|
221
|
-
|
222
|
-
machine.start
|
223
|
-
machines << machine
|
50
|
+
m = Rudy::Machine.new(Rudy::Huxtable.global.position)
|
51
|
+
m.create
|
52
|
+
[m]
|
224
53
|
end
|
225
|
-
machines.each { |m| each_mach.call(m) } if each_mach
|
226
|
-
machines
|
227
54
|
end
|
228
55
|
|
229
|
-
|
230
|
-
|
231
|
-
raise
|
232
|
-
|
233
|
-
|
234
|
-
list do |mach|
|
235
|
-
#puts "Destroying #{mach.name}"
|
236
|
-
mach.destroy
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
|
241
|
-
def restart(&each_mach)
|
242
|
-
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
243
|
-
raise MachineGroupNotRunning, current_machine_group unless running?
|
244
|
-
machines = list
|
245
|
-
machines.each do |mach|
|
246
|
-
each_mach.call(mach) if each_mach
|
247
|
-
puts "Restarting #{mach.name}"
|
248
|
-
mach.restart
|
249
|
-
end
|
250
|
-
machines
|
251
|
-
end
|
252
|
-
|
253
|
-
def list(more=[], less=[], &each_mach)
|
254
|
-
machines = list_as_hash(more, less, &each_mach)
|
255
|
-
machines &&= machines.values
|
256
|
-
machines
|
257
|
-
end
|
258
|
-
|
259
|
-
def list_as_hash(more=[], less=[], &each_mach)
|
260
|
-
query = to_select([:rtype, 'm'], less)
|
261
|
-
list = @sdb.select(query) || {}
|
262
|
-
machines = {}
|
263
|
-
list.each_pair do |n,m|
|
264
|
-
machines[n] = Rudy::Machine.from_hash(m)
|
56
|
+
def restart
|
57
|
+
group = list
|
58
|
+
raise MachineGroupNotRunning, current_group_name if group.nil?
|
59
|
+
group.each do |inst|
|
60
|
+
inst.restart
|
265
61
|
end
|
266
|
-
|
267
|
-
machines = nil if machines.empty?
|
268
|
-
machines
|
62
|
+
group
|
269
63
|
end
|
270
64
|
|
271
|
-
def
|
272
|
-
Rudy::Machine.from_hash
|
65
|
+
def from_hash(h)
|
66
|
+
Rudy::Machine.from_hash h
|
273
67
|
end
|
274
68
|
|
275
|
-
|
276
|
-
def running?
|
277
|
-
!list.nil?
|
278
|
-
# TODO: add logic that checks whether the instances are running.
|
279
|
-
end
|
280
|
-
|
281
|
-
end
|
282
|
-
|
283
|
-
|
284
|
-
class Machines::Offline
|
285
|
-
def list(more=[], less=[], &each_mach)
|
286
|
-
m = Rudy::Machine.new
|
287
|
-
m.dns_public = 'localhost'
|
288
|
-
each_mach.call(m) if each_mach
|
289
|
-
[m]
|
290
|
-
end
|
291
69
|
end
|
292
70
|
|
293
71
|
end
|
data/lib/rudy/metadata.rb
CHANGED
@@ -1,62 +1,236 @@
|
|
1
1
|
|
2
|
+
|
2
3
|
module Rudy
|
3
|
-
module
|
4
|
+
module Metadata
|
4
5
|
include Rudy::Huxtable
|
5
6
|
|
6
|
-
|
7
|
+
COMMON_FIELDS = [:region, :zone, :environment, :role].freeze
|
8
|
+
|
9
|
+
@@rsdb = nil
|
10
|
+
@@domain = Rudy::DOMAIN
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
#
|
13
|
+
def self.get_rclass(rtype)
|
14
|
+
case rtype
|
15
|
+
when Rudy::Machines::RTYPE
|
16
|
+
Rudy::Machines
|
17
|
+
when Rudy::Disks::RTYPE
|
18
|
+
Rudy::Disks
|
19
|
+
when Rudy::Backups::RTYPE
|
20
|
+
Rudy::Backups
|
21
|
+
else
|
22
|
+
raise UnknownRecordType, rtype
|
23
|
+
end
|
17
24
|
end
|
18
25
|
|
19
|
-
|
26
|
+
# Creates instances of the following and stores to class variables:
|
27
|
+
# * Rudy::AWS::SDB
|
28
|
+
# * Rudy::AWS::EC2::Volumes
|
29
|
+
def self.connect(accesskey, secretkey, region, reconnect=false)
|
30
|
+
return @@rsdb unless reconnect || @@rsdb.nil?
|
31
|
+
@@rsdb = Rudy::AWS::SDB.new accesskey, secretkey, region
|
32
|
+
true
|
33
|
+
end
|
34
|
+
def self.domain(name=nil)
|
35
|
+
return @@domain if name.nil?
|
36
|
+
@@domain = name
|
37
|
+
end
|
38
|
+
# An alias for Rudy::Metadata.domain
|
39
|
+
def self.domain=(*args)
|
40
|
+
domain *args
|
20
41
|
end
|
21
42
|
|
22
|
-
#
|
23
|
-
def
|
24
|
-
|
25
|
-
[dat.year, mon, day, Rudy::DELIM, hour, min, Rudy::DELIM, sec].join
|
43
|
+
# Creates a SimpleDB domain named +n+ and updates +@@domain+ if successful
|
44
|
+
def self.create_domain(n)
|
45
|
+
@@domain = n if @@rsdb.create_domain n
|
26
46
|
end
|
27
47
|
|
28
|
-
|
29
|
-
|
48
|
+
# Destroys a SimpleDB domain named +n+ and sets +@@domain+ to Rudy::DOMAIN
|
49
|
+
def self.destroy_domain(n)
|
50
|
+
Rudy::Huxtable.ld "DESTROY: #{n}" if Rudy.debug?
|
51
|
+
@@rsdb.destroy_domain n
|
52
|
+
@@domain = Rudy::DOMAIN
|
30
53
|
true
|
31
54
|
end
|
32
55
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
56
|
+
# Get a record from SimpleDB with the key +n+
|
57
|
+
def self.get(n)
|
58
|
+
Rudy::Huxtable.ld "GET: #{n}" if Rudy.debug?
|
59
|
+
@@rsdb.get @@domain, n
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.exists?(n)
|
63
|
+
!get(n).nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.put(n, o, replace=false)
|
67
|
+
Rudy::Huxtable.ld "PUT: #{n}" if Rudy.debug?
|
68
|
+
@@rsdb.put @@domain, n, o, replace
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.destroy(n)
|
72
|
+
Rudy::Huxtable.ld "DESTROY: #{n}" if Rudy.debug?
|
73
|
+
@@rsdb.destroy @@domain, n
|
74
|
+
end
|
75
|
+
|
76
|
+
# Generates and executes a SimpleDB select query based on
|
77
|
+
# the specified +fields+ Hash. See self.build_criteria.
|
78
|
+
#
|
79
|
+
# Returns a Hash. keys are SimpleDB object IDs and values
|
80
|
+
# are the object attributes.
|
81
|
+
def self.select(fields={})
|
82
|
+
squery = Rudy::AWS::SDB.generate_select @@domain, fields
|
83
|
+
Rudy::Huxtable.ld "SELECT: #{squery}" if Rudy.debug?
|
84
|
+
@@rsdb.select squery
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
# Generates a default criteria for all metadata based on
|
89
|
+
# region, zone, environment, and role. If a position has
|
90
|
+
# been specified in the globals it will also be included.
|
91
|
+
# * +rtype+ is the record type. One of: m, disk, or back.
|
92
|
+
# * +fields+ replaces and adds values to this criteria
|
93
|
+
# * +less+ removes keys from the default criteria.
|
94
|
+
#
|
95
|
+
# Returns a Hash.
|
96
|
+
def self.build_criteria(rtype, fields={}, less=[])
|
97
|
+
fields ||= {}
|
98
|
+
fields[:rtype] = rtype
|
99
|
+
fields[:position] = @@global.position unless @@global.position.nil?
|
100
|
+
names = Rudy::Metadata::COMMON_FIELDS
|
101
|
+
values = names.collect { |n| @@global.send(n.to_sym) }
|
102
|
+
mixer = names.zip(values).flatten
|
103
|
+
criteria = Hash[*mixer].merge(fields)
|
104
|
+
criteria.reject! { |n,v| less.member?(n) }
|
105
|
+
Rudy::Huxtable.ld "CRITERIA: #{criteria.inspect}"
|
106
|
+
criteria
|
107
|
+
end
|
108
|
+
|
109
|
+
module ClassMethods
|
110
|
+
extend self
|
111
|
+
extend Rudy::Huxtable
|
112
|
+
|
113
|
+
# TODO: MOVE TO Rudy:Disks etc...
|
114
|
+
def list(fields={}, less=[], &block)
|
115
|
+
fields = Rudy::Metadata.build_criteria self::RTYPE, fields, less
|
116
|
+
records_raw, records = Rudy::Metadata.select(fields), []
|
117
|
+
return nil if records_raw.nil? || records_raw.empty?
|
118
|
+
records_raw.each_pair do |p, r|
|
119
|
+
obj = self.from_hash r
|
120
|
+
records << obj
|
121
|
+
end
|
122
|
+
records.sort { |a,b| a.name <=> b.name }
|
123
|
+
end
|
124
|
+
|
125
|
+
def list_as_hash(fields={}, less=[], &block)
|
126
|
+
fields = Rudy::Metadata.build_criteria self::RTYPE, fields, less
|
127
|
+
records_raw, records = Rudy::Metadata.select(fields), {}
|
128
|
+
return nil if records_raw.nil? || records_raw.empty?
|
129
|
+
records_raw.each_pair do |p, r|
|
130
|
+
obj = self.from_hash r
|
131
|
+
records[p] = obj
|
132
|
+
end
|
133
|
+
records
|
46
134
|
end
|
47
|
-
|
135
|
+
|
136
|
+
def any?(fields={}, less=[])
|
137
|
+
!list(fields, less).nil?
|
138
|
+
end
|
139
|
+
|
48
140
|
end
|
49
141
|
|
50
|
-
|
51
|
-
|
142
|
+
# All classes which include Rudy::Metadata must reimplement
|
143
|
+
# the method stubs in this module. These methods only raise
|
144
|
+
# exceptions.
|
145
|
+
module InstanceMethods
|
146
|
+
class << self
|
147
|
+
def valid?; raise "implement valid?"; end
|
148
|
+
def name; raise "implement name"; end
|
149
|
+
def postprocess; raise "implement postprocess"; end
|
150
|
+
end
|
52
151
|
end
|
53
|
-
|
54
|
-
def
|
55
|
-
|
152
|
+
|
153
|
+
def self.included(obj)
|
154
|
+
obj.send :include, Rudy::Metadata::InstanceMethods
|
155
|
+
|
156
|
+
# Add common storable fields.
|
157
|
+
[COMMON_FIELDS, :position].flatten.each do |n|
|
158
|
+
obj.field n
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
def initialize(rtype, opts={})
|
164
|
+
@rtype = rtype
|
165
|
+
@position = position || @@global.position || '01'
|
166
|
+
|
167
|
+
COMMON_FIELDS.each { |n|
|
168
|
+
ld "SETTING: #{n}: #{@@global.send(n)}" if @@global.verbose > 3
|
169
|
+
instance_variable_set("@#{n}", @@global.send(n))
|
170
|
+
}
|
171
|
+
|
172
|
+
opts.each_pair do |n,v|
|
173
|
+
raise "Unknown attribute for #{self.class}: #{n}" if !self.has_field? n
|
174
|
+
next if v.nil?
|
175
|
+
ld "RESETTING: #{n}: #{v}" if @@global.verbose > 3
|
176
|
+
self.send("#{n}=", v)
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
def name(*other)
|
182
|
+
parts = [@rtype, @zone, @environment, @role, @position, *other].flatten
|
183
|
+
parts.join Rudy::DELIM
|
184
|
+
end
|
185
|
+
|
186
|
+
def save(replace=false)
|
187
|
+
raise DuplicateRecord, self.name unless replace || !self.exists?
|
188
|
+
Rudy::Metadata.put self.name, self.to_hash, replace
|
189
|
+
true
|
190
|
+
end
|
191
|
+
|
192
|
+
def destroy(force=false)
|
193
|
+
raise UnknownObject, self.name unless self.exists?
|
194
|
+
Rudy::Metadata.destroy self.name
|
195
|
+
true
|
196
|
+
end
|
197
|
+
|
198
|
+
def descriptors(*additional)
|
199
|
+
criteria = {
|
200
|
+
:region => @region, :zone => @zone,
|
201
|
+
:environment => @environment, :role => @role
|
202
|
+
}
|
203
|
+
additional.each do |att|
|
204
|
+
criteria[att] = self.send(att)
|
205
|
+
end
|
206
|
+
ld "DESCRIPTORS: #{criteria.inspect} (#{additional})"
|
207
|
+
criteria
|
208
|
+
end
|
209
|
+
|
210
|
+
# Refresh the metadata object from SimpleDB. If the record doesn't
|
211
|
+
# exist it will raise an UnknownObject error
|
212
|
+
def refresh!
|
213
|
+
raise UnknownObject, self.name unless self.exists?
|
214
|
+
h = Rudy::Metadata.get self.name
|
215
|
+
return false if h.nil? || h.empty?
|
216
|
+
obj = self.from_hash(h)
|
217
|
+
obj.postprocess
|
218
|
+
obj
|
219
|
+
end
|
220
|
+
|
221
|
+
# Compares the names between two Rudy::Metadata objects.
|
222
|
+
def ==(other)
|
223
|
+
return false unless other === self.class
|
224
|
+
self.name == other.name
|
225
|
+
end
|
226
|
+
|
227
|
+
# Is there an object in SimpleDB where the key == self.name
|
228
|
+
def exists?
|
229
|
+
!Rudy::Metadata.get(self.name).nil?
|
56
230
|
end
|
57
231
|
|
58
232
|
end
|
59
233
|
end
|
60
234
|
|
61
|
-
Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'metadata', 'objectbase.rb')
|
62
235
|
Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'metadata', '*.rb')
|
236
|
+
|