rudy 0.8.5 → 0.9.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 +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
|
+
|