solutious-rudy 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +19 -1
- data/README.rdoc +66 -35
- data/Rakefile +1 -0
- data/Rudyfile +97 -6
- data/bin/ird +7 -4
- data/bin/rudy +120 -212
- data/bin/rudy-ec2 +240 -0
- data/bin/rudy-s3 +76 -0
- data/bin/rudy-sdb +67 -0
- data/lib/annoy.rb +61 -18
- data/lib/console.rb +10 -5
- data/lib/rudy/aws/ec2/address.rb +76 -40
- data/lib/rudy/aws/ec2/group.rb +138 -78
- data/lib/rudy/aws/ec2/image.rb +134 -12
- data/lib/rudy/aws/ec2/instance.rb +116 -89
- data/lib/rudy/aws/ec2/keypair.rb +26 -14
- data/lib/rudy/aws/ec2/snapshot.rb +23 -12
- data/lib/rudy/aws/ec2/volume.rb +198 -202
- data/lib/rudy/aws/ec2/zone.rb +77 -0
- data/lib/rudy/aws/ec2.rb +56 -25
- data/lib/rudy/aws/s3.rb +54 -0
- data/lib/rudy/aws/sdb/error.rb +46 -0
- data/lib/rudy/aws/sdb.rb +298 -0
- data/lib/rudy/aws.rb +29 -57
- data/lib/rudy/{metadata/backup.rb → backup.rb} +8 -8
- data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
- data/lib/rudy/cli/aws/ec2/candy.rb +208 -0
- data/lib/rudy/cli/aws/ec2/groups.rb +121 -0
- data/lib/rudy/cli/aws/ec2/images.rb +196 -0
- data/lib/rudy/cli/aws/ec2/instances.rb +194 -0
- data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
- data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
- data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
- data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
- data/lib/rudy/cli/aws/s3/buckets.rb +50 -0
- data/lib/rudy/cli/aws/s3/store.rb +22 -0
- data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
- data/lib/rudy/cli/{deploy.rb → candy.rb} +2 -6
- data/lib/rudy/cli/config.rb +25 -20
- data/lib/rudy/cli/disks.rb +18 -108
- data/lib/rudy/cli/machines.rb +94 -0
- data/lib/rudy/cli/routines.rb +47 -70
- data/lib/rudy/cli.rb +104 -89
- data/lib/rudy/config/objects.rb +5 -43
- data/lib/rudy/config.rb +8 -24
- data/lib/rudy/disks.rb +248 -0
- data/lib/rudy/global.rb +121 -0
- data/lib/rudy/huxtable.rb +232 -147
- data/lib/rudy/machines.rb +245 -0
- data/lib/rudy/metadata.rb +136 -0
- data/lib/rudy/routines/helpers/diskhelper.rb +101 -0
- data/lib/rudy/routines/helpers/scripthelper.rb +91 -0
- data/lib/rudy/routines/release.rb +27 -8
- data/lib/rudy/routines/shutdown.rb +47 -32
- data/lib/rudy/routines/startup.rb +47 -37
- data/lib/rudy/routines.rb +30 -37
- data/lib/rudy/scm/svn.rb +1 -1
- data/lib/rudy/utils.rb +262 -4
- data/lib/rudy.rb +76 -248
- data/lib/storable.rb +19 -16
- data/lib/sysinfo.rb +1 -1
- data/rudy.gemspec +88 -68
- data/support/rudy-ec2-startup +5 -5
- data/test/05_config/00_setup_test.rb +3 -7
- data/test/20_sdb/00_setup_test.rb +2 -17
- data/test/20_sdb/10_domains_test.rb +18 -16
- data/test/25_ec2/00_setup_test.rb +5 -10
- data/test/25_ec2/10_keypairs_test.rb +13 -5
- data/test/25_ec2/20_groups_test.rb +48 -56
- data/test/25_ec2/30_addresses_test.rb +13 -10
- data/test/25_ec2/40_volumes_test.rb +11 -8
- data/test/25_ec2/50_snapshots_test.rb +17 -12
- data/test/26_ec2_instances/00_setup_test.rb +3 -8
- data/test/26_ec2_instances/10_instances_test.rb +21 -19
- data/test/30_sdb_metadata/00_setup_test.rb +2 -9
- data/test/30_sdb_metadata/10_disks_test.rb +47 -37
- data/test/30_sdb_metadata/20_backups_test.rb +9 -9
- data/test/helper.rb +5 -3
- data/vendor/highline-1.5.1/CHANGELOG +222 -0
- data/vendor/highline-1.5.1/INSTALL +35 -0
- data/vendor/highline-1.5.1/LICENSE +7 -0
- data/vendor/highline-1.5.1/README +63 -0
- data/vendor/highline-1.5.1/Rakefile +82 -0
- data/vendor/highline-1.5.1/TODO +6 -0
- data/vendor/highline-1.5.1/examples/ansi_colors.rb +38 -0
- data/vendor/highline-1.5.1/examples/asking_for_arrays.rb +18 -0
- data/vendor/highline-1.5.1/examples/basic_usage.rb +75 -0
- data/vendor/highline-1.5.1/examples/color_scheme.rb +32 -0
- data/vendor/highline-1.5.1/examples/limit.rb +12 -0
- data/vendor/highline-1.5.1/examples/menus.rb +65 -0
- data/vendor/highline-1.5.1/examples/overwrite.rb +19 -0
- data/vendor/highline-1.5.1/examples/page_and_wrap.rb +322 -0
- data/vendor/highline-1.5.1/examples/password.rb +7 -0
- data/vendor/highline-1.5.1/examples/trapping_eof.rb +22 -0
- data/vendor/highline-1.5.1/examples/using_readline.rb +17 -0
- data/vendor/highline-1.5.1/lib/highline/color_scheme.rb +120 -0
- data/vendor/highline-1.5.1/lib/highline/compatibility.rb +17 -0
- data/vendor/highline-1.5.1/lib/highline/import.rb +43 -0
- data/vendor/highline-1.5.1/lib/highline/menu.rb +395 -0
- data/vendor/highline-1.5.1/lib/highline/question.rb +463 -0
- data/vendor/highline-1.5.1/lib/highline/system_extensions.rb +193 -0
- data/vendor/highline-1.5.1/lib/highline.rb +758 -0
- data/vendor/highline-1.5.1/setup.rb +1360 -0
- data/vendor/highline-1.5.1/test/tc_color_scheme.rb +56 -0
- data/vendor/highline-1.5.1/test/tc_highline.rb +823 -0
- data/vendor/highline-1.5.1/test/tc_import.rb +54 -0
- data/vendor/highline-1.5.1/test/tc_menu.rb +429 -0
- data/vendor/highline-1.5.1/test/ts_all.rb +15 -0
- metadata +81 -69
- data/lib/aws_sdb/error.rb +0 -42
- data/lib/aws_sdb/service.rb +0 -215
- data/lib/aws_sdb.rb +0 -3
- data/lib/rudy/aws/simpledb.rb +0 -71
- data/lib/rudy/cli/addresses.rb +0 -85
- data/lib/rudy/cli/backups.rb +0 -175
- data/lib/rudy/cli/domains.rb +0 -17
- data/lib/rudy/cli/groups.rb +0 -77
- data/lib/rudy/cli/images.rb +0 -111
- data/lib/rudy/cli/instances.rb +0 -142
- data/lib/rudy/cli/keypairs.rb +0 -47
- data/lib/rudy/cli/manager.rb +0 -51
- data/lib/rudy/cli/release.rb +0 -174
- data/lib/rudy/cli/volumes.rb +0 -121
- data/lib/rudy/command/addresses.rb +0 -69
- data/lib/rudy/command/backups.rb +0 -65
- data/lib/rudy/command/disks-old.rb +0 -322
- data/lib/rudy/command/disks.rb +0 -9
- data/lib/rudy/command/domains.rb +0 -34
- data/lib/rudy/command/groups.rb +0 -118
- data/lib/rudy/command/instances.rb +0 -278
- data/lib/rudy/command/keypairs.rb +0 -149
- data/lib/rudy/command/manager.rb +0 -65
- data/lib/rudy/command/volumes.rb +0 -127
- data/lib/rudy/metadata/disk.rb +0 -149
- data/lib/rudy/metadata/machine.rb +0 -34
- data/lib/rudy/routines/disk_handler.rb +0 -190
- data/lib/rudy/routines/script_runner.rb +0 -65
- data/test/50_commands/00_setup_test.rb +0 -11
- data/test/50_commands/10_keypairs_test.rb +0 -79
- data/test/50_commands/20_groups_test.rb +0 -77
- data/test/50_commands/40_volumes_test.rb +0 -55
- data/test/50_commands/50_instances_test.rb +0 -110
- data/tryouts/console_tryout.rb +0 -91
- data/tryouts/disks.rb +0 -55
- data/tryouts/nested_methods.rb +0 -36
- data/tryouts/session_tryout.rb +0 -46
@@ -0,0 +1,245 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
module Rudy
|
5
|
+
class Machine < Storable
|
6
|
+
include Rudy::MetaData::ObjectBase
|
7
|
+
|
8
|
+
field :rtype
|
9
|
+
field :awsid
|
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
|
+
attr_reader :instance
|
25
|
+
|
26
|
+
def init
|
27
|
+
#@created =
|
28
|
+
@rtype = 'm'
|
29
|
+
@region = @@global.region
|
30
|
+
@zone = @@global.zone
|
31
|
+
@environment = @@global.environment
|
32
|
+
@role = @@global.role
|
33
|
+
@position = find_next_position || '01'
|
34
|
+
@state = 'no-instance'
|
35
|
+
end
|
36
|
+
|
37
|
+
def liner_note
|
38
|
+
update #if !dns_public? && @awsid
|
39
|
+
info = !@dns_public.nil? && !@dns_public.empty? ? @dns_public : "#{@awsid}:#{@state}"
|
40
|
+
"%s %s" % [self.name.bright, info]
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s(with_title=false)
|
44
|
+
lines = []
|
45
|
+
lines << liner_note
|
46
|
+
#if self.running?
|
47
|
+
# k, g = @keyname || 'no-keypair', self.groups.join(', ')
|
48
|
+
# lines << @@sformat % %w{zone size ami keyname groups} if with_title
|
49
|
+
# lines << @@sformat % [@zone, @size, @ami, k, g]
|
50
|
+
#end
|
51
|
+
lines.join($/)
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
update #if !dns_public? && @awsid
|
56
|
+
lines = []
|
57
|
+
lines << liner_note
|
58
|
+
field_names.each do |key|
|
59
|
+
next unless self.respond_to?(key)
|
60
|
+
val = self.send(key)
|
61
|
+
lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
|
62
|
+
end
|
63
|
+
lines.join($/)
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_next_position
|
67
|
+
list = @sdb.select(self.to_select(nil, [:position])) || []
|
68
|
+
pos = list.size + 1
|
69
|
+
pos.to_s.rjust(2, '0')
|
70
|
+
end
|
71
|
+
|
72
|
+
def name
|
73
|
+
Machine.generate_name(@zone, @environment, @role, @position)
|
74
|
+
end
|
75
|
+
|
76
|
+
def Machine.generate_name(zon, env, rol, pos)
|
77
|
+
pos = pos.to_s.rjust 2, '0'
|
78
|
+
["m", zon, env, rol, pos].join(Rudy::DELIM)
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_instance
|
82
|
+
@ec2inst.get(@awsid)
|
83
|
+
end
|
84
|
+
|
85
|
+
def update
|
86
|
+
return false unless @awsid
|
87
|
+
@instance = get_instance
|
88
|
+
if @instance.is_a?(Rudy::AWS::EC2::Instance)
|
89
|
+
@dns_public = @instance.dns_public
|
90
|
+
@dns_private = @instance.dns_private
|
91
|
+
@state = @instance.state
|
92
|
+
save
|
93
|
+
elsif @instance.nil?
|
94
|
+
@dns_public = @dns_private = nil
|
95
|
+
@state = 'unknown'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def dns_public?
|
100
|
+
!@dns_public.nil? && !@dns_public.empty?
|
101
|
+
end
|
102
|
+
def dns_private?
|
103
|
+
!@dns_private.nil? && !@dns_private.empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
def start(opts={})
|
107
|
+
raise "#{name} is already running" if running?
|
108
|
+
|
109
|
+
opts = {
|
110
|
+
:min => 1,
|
111
|
+
:size => current_machine_size,
|
112
|
+
:ami => current_machine_image,
|
113
|
+
:group => current_group_name,
|
114
|
+
:keypair => root_keypairname,
|
115
|
+
:zone => @@global.zone.to_s,
|
116
|
+
:address => current_machine_address,
|
117
|
+
:machine_data => Machine.generate_machine_data.to_yaml
|
118
|
+
}.merge(opts)
|
119
|
+
|
120
|
+
@ec2inst.create(opts) do |inst|
|
121
|
+
@awsid = inst.awsid
|
122
|
+
@created = @starts = Time.now
|
123
|
+
@state = inst.state
|
124
|
+
end
|
125
|
+
|
126
|
+
self.save
|
127
|
+
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
131
|
+
def destroy
|
132
|
+
@ec2inst.destroy(@awsid) if running?
|
133
|
+
super
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
def Machine.generate_machine_data
|
138
|
+
data = { # Give the machine an identity
|
139
|
+
:region => @@global.region.to_s,
|
140
|
+
:zone => @@global.zone.to_s,
|
141
|
+
:environment => @@global.environment.to_s,
|
142
|
+
:role => @@global.role.to_s,
|
143
|
+
:position => @@global.position.to_s,
|
144
|
+
:hosts => { # Add hosts to the /etc/hosts file
|
145
|
+
:dbmaster => "127.0.0.1",
|
146
|
+
}
|
147
|
+
}
|
148
|
+
data
|
149
|
+
end
|
150
|
+
|
151
|
+
def running?
|
152
|
+
return false if @awsid.nil? || @awsid.empty?
|
153
|
+
@ec2inst.running?(@awsid)
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
class Machines
|
161
|
+
include Rudy::MetaData
|
162
|
+
|
163
|
+
def create(&each_mach)
|
164
|
+
raise MachineGroupAlreadyRunning, current_machine_group if running?
|
165
|
+
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
166
|
+
|
167
|
+
unless (1..MAX_INSTANCES).member?(current_machine_count)
|
168
|
+
raise "Instance count must be more than 0, less than #{MAX_INSTANCES}"
|
169
|
+
end
|
170
|
+
|
171
|
+
unless @rgrp.exists?(current_group_name)
|
172
|
+
puts "Creating group: #{current_group_name}"
|
173
|
+
@rgrp.create(current_group_name)
|
174
|
+
end
|
175
|
+
|
176
|
+
unless @rkey.exists?(root_keypairname)
|
177
|
+
kp_file = File.join(Rudy::CONFIG_DIR, root_keypairname)
|
178
|
+
raise PrivateKeyFileExists, kp_file if File.exists?(kp_file)
|
179
|
+
puts "Creating keypair: #{root_keypairname}"
|
180
|
+
kp = @rkey.create(root_keypairname)
|
181
|
+
puts "Saving #{kp_file}"
|
182
|
+
Rudy::Utils.write_to_file(kp_file, kp.private_key, 'w', 0600)
|
183
|
+
else
|
184
|
+
kp_file = root_keypairpath
|
185
|
+
# This means no keypair file can be found
|
186
|
+
raise PrivateKeyNotFound, root_keypairname if kp_file.nil?
|
187
|
+
# This means we found a keypair in the config but we cannot find the private key file.
|
188
|
+
raise PrivateKeyNotFound, kp_file if !File.exists?(kp_file)
|
189
|
+
end
|
190
|
+
|
191
|
+
machines = []
|
192
|
+
current_machine_count.times do |i|
|
193
|
+
machine = Rudy::Machine.new
|
194
|
+
puts "Starting %s" % machine.name
|
195
|
+
machine.start
|
196
|
+
machines << machine
|
197
|
+
end
|
198
|
+
machines.each { |m| each_mach.call(m) } if each_mach
|
199
|
+
machines
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
def destroy(&each_mach)
|
204
|
+
raise MachineGroupNotRunning, current_machine_group unless running?
|
205
|
+
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
206
|
+
list.each { |m| each_mach.call(m); } if each_mach
|
207
|
+
list do |mach|
|
208
|
+
puts "Destroying #{mach.name}"
|
209
|
+
mach.destroy
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def list(more=[], less=[], &each_mach)
|
214
|
+
machines = list_as_hash(&each_mach)
|
215
|
+
machines &&= machines.values
|
216
|
+
machines
|
217
|
+
end
|
218
|
+
|
219
|
+
def list_as_hash(more=[], less=[], &each_mach)
|
220
|
+
query = to_select([:rtype, 'm'], less)
|
221
|
+
list = @sdb.select(query) || {}
|
222
|
+
machines = {}
|
223
|
+
list.each_pair do |n,m|
|
224
|
+
machines[n] = Rudy::Machine.from_hash(m)
|
225
|
+
end
|
226
|
+
machines.each_pair { |n,mach| each_mach.call(mach) } if each_mach
|
227
|
+
machines = nil if machines.empty?
|
228
|
+
machines
|
229
|
+
end
|
230
|
+
|
231
|
+
def get(rname=nil)
|
232
|
+
Rudy::Machine.from_hash(@sdb.get(Rudy::DOMAIN, rname)) # Returns nil if empty
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
def running?
|
237
|
+
!list.nil?
|
238
|
+
# TODO: add logic that checks whether the instances are running.
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
module MetaData
|
5
|
+
module ObjectBase
|
6
|
+
include Rudy::Huxtable
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
a, s, r = @@global.accesskey, @@global.secretkey, @@global.region
|
10
|
+
@sdb = Rudy::AWS::SDB.new(a, s, r)
|
11
|
+
@ec2inst = Rudy::AWS::EC2::Instances.new(a, s, r)
|
12
|
+
@rvol = Rudy::AWS::EC2::Volumes.new(a, s, r)
|
13
|
+
init(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def init(*args); raise "Must override init"; end
|
17
|
+
|
18
|
+
def valid?; raise "#{self.class} must override 'valid?'"; end
|
19
|
+
|
20
|
+
def to_query(more=[], less=[])
|
21
|
+
Rudy::AWS::SDB.generate_query build_criteria(more, less)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_select(more=[], less=[])
|
25
|
+
Rudy::AWS::SDB.generate_select ['*'], Rudy::DOMAIN, build_criteria(more, less)
|
26
|
+
end
|
27
|
+
|
28
|
+
def name(identifier, zon, env, rol, pos, *other)
|
29
|
+
pos = pos.to_s.rjust 2, '0'
|
30
|
+
[identifier, zon, env, rol, pos, *other].flatten.compact.join(Rudy::DELIM)
|
31
|
+
end
|
32
|
+
|
33
|
+
def save(replace=true)
|
34
|
+
replace = true if replace.nil?
|
35
|
+
@sdb ||= Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
|
36
|
+
@sdb.put(Rudy::DOMAIN, name, self.to_hash, replace) # Always returns nil
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@sdb ||= Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
|
42
|
+
@sdb.destroy(Rudy::DOMAIN, name)
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def refresh
|
47
|
+
@sdb ||= Rudy::AWS::SDB.new(@@global.accesskey, @@global.secretkey, @@global.region)
|
48
|
+
h = @sdb.get(Rudy::DOMAIN, name) || {}
|
49
|
+
from_hash(h)
|
50
|
+
end
|
51
|
+
|
52
|
+
def ==(other)
|
53
|
+
return false unless other.is_a?(self.class)
|
54
|
+
self.name == other.name
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
str = ""
|
59
|
+
field_names.each do |key|
|
60
|
+
str << sprintf(" %22s: %s#{$/}", key, self.send(key.to_sym))
|
61
|
+
end
|
62
|
+
str
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
# Builds a zipped Array from a list of criteria.
|
69
|
+
# The list of criteria is made up of metadata object attributes.
|
70
|
+
# The list is constructed by taking the adding +more+, and
|
71
|
+
# subtracting +less+ from <tt>:rtype, :region, :zone, :environment, :role, :position</tt>
|
72
|
+
#
|
73
|
+
# Returns [[:rtype, value], [:zone, value], ...]
|
74
|
+
def build_criteria(more=[], less=[])
|
75
|
+
criteria = [:rtype, :region, :zone, :environment, :role, :position, *more].compact
|
76
|
+
criteria -= [*less].flatten.uniq.compact
|
77
|
+
values = criteria.collect do |n|
|
78
|
+
self.send(n.to_sym)
|
79
|
+
end
|
80
|
+
criteria.zip(values)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
module Rudy
|
90
|
+
module MetaData
|
91
|
+
include Rudy::Huxtable
|
92
|
+
|
93
|
+
def initialize(*args)
|
94
|
+
a, s, r = @@global.accesskey, @@global.secretkey, @@global.region
|
95
|
+
@sdb = Rudy::AWS::SDB.new(a, s, r)
|
96
|
+
@rinst = Rudy::AWS::EC2::Instances.new(a, s, r)
|
97
|
+
@rgrp = Rudy::AWS::EC2::Groups.new(a, s, r)
|
98
|
+
@rkey = Rudy::AWS::EC2::KeyPairs.new(a, s, r)
|
99
|
+
init(*args)
|
100
|
+
end
|
101
|
+
|
102
|
+
def init(*args)
|
103
|
+
end
|
104
|
+
|
105
|
+
# 20090224-1813-36
|
106
|
+
def format_timestamp(dat)
|
107
|
+
mon, day, hour, min, sec = [dat.mon, dat.day, dat.hour, dat.min, dat.sec].collect { |v| v.to_s.rjust(2, "0") }
|
108
|
+
[dat.year, mon, day, Rudy::DELIM, hour, min, Rudy::DELIM, sec].join
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
# Returns a generic zipped Array of metadata
|
114
|
+
# (There is region, zone, environment, role, but no rtype)
|
115
|
+
def build_criteria(more=[], less=[])
|
116
|
+
# TODO: This build_criteria treats "more" differently than the
|
117
|
+
# ObjectBase one. Sort it out! (This way is better)
|
118
|
+
names = [:region, :zone, :environment, :role].compact
|
119
|
+
names -= [*less].flatten.uniq.compact
|
120
|
+
values = names.collect do |n|
|
121
|
+
@@global.send(n.to_sym)
|
122
|
+
end
|
123
|
+
names.zip(values) + more
|
124
|
+
end
|
125
|
+
|
126
|
+
def to_query(more=[], less=[])
|
127
|
+
Rudy::AWS::SDB.generate_query build_criteria(more, less)
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_select(more=[], less=[])
|
131
|
+
Rudy::AWS::SDB.generate_select ['*'], Rudy::DOMAIN, build_criteria(more, less)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy; module Routines;
|
4
|
+
module DiskHelper
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def execute(routine, machine, rbox)
|
8
|
+
return unless routine
|
9
|
+
raise "Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
|
10
|
+
raise "Not a Rye::Box" unless rbox.is_a?(Rye::Box)
|
11
|
+
|
12
|
+
@machine = machine
|
13
|
+
@rbox = rbox
|
14
|
+
|
15
|
+
(routine.disks || {}).each_pair do |action, disks|
|
16
|
+
unless DiskHelper.respond_to?(action)
|
17
|
+
STDERR.puts %Q(DiskHelper: unknown action "#{action}")
|
18
|
+
next
|
19
|
+
end
|
20
|
+
send(action, disks) # create, copy, destroy, ...
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def create(disks)
|
25
|
+
rdisk = Rudy::Disks.new
|
26
|
+
|
27
|
+
disks.each_pair do |path, props|
|
28
|
+
disk = Rudy::Disk.new(path, props[:size], props[:device], @machine.position)
|
29
|
+
#disk = rdisk.get(disk.name)
|
30
|
+
puts "Creating #{disk.name} "
|
31
|
+
|
32
|
+
print "Creating volume... "
|
33
|
+
disk.create
|
34
|
+
Rudy::Utils.waiter(2, 60, STDOUT, "done", nil) {
|
35
|
+
disk.available?
|
36
|
+
}
|
37
|
+
|
38
|
+
print "Attaching #{disk.awsid} to #{@machine.awsid}... "
|
39
|
+
disk.attach(@machine.awsid)
|
40
|
+
Rudy::Utils.waiter(2, 60, STDOUT, "done", nil) {
|
41
|
+
disk.attached?
|
42
|
+
}
|
43
|
+
|
44
|
+
# The device needs some time.
|
45
|
+
# Otherwise mkfs returns:
|
46
|
+
# "No such file or directory while trying to determine filesystem size"
|
47
|
+
sleep 2
|
48
|
+
|
49
|
+
print "Creating ext3 filesystem for #{disk.device}... "
|
50
|
+
@rbox.mkfs(:t, "ext3", :F, disk.device)
|
51
|
+
@rbox.mkdir(:p, disk.path)
|
52
|
+
puts "done"
|
53
|
+
|
54
|
+
print "Mounting at #{disk.path}... "
|
55
|
+
|
56
|
+
@rbox.mount(:t, 'ext3', disk.device, disk.path)
|
57
|
+
disk.mounted = true
|
58
|
+
disk.save
|
59
|
+
puts "done"
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def destroy(disks)
|
65
|
+
rdisk = Rudy::Disks.new
|
66
|
+
|
67
|
+
disks.each_pair do |path, props|
|
68
|
+
adisk = Rudy::Disk.new(path, props[:size], props[:device], @machine.position)
|
69
|
+
disk = rdisk.get(adisk.name)
|
70
|
+
if disk == nil
|
71
|
+
puts "Not found: #{adisk.name}".color(:red)
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
75
|
+
puts "Destroying #{disk.name}"
|
76
|
+
|
77
|
+
if disk.mounted?
|
78
|
+
print "Unmounting #{disk.path}... "
|
79
|
+
@rbox.umount(disk.path)
|
80
|
+
sleep 0.5
|
81
|
+
puts "done"
|
82
|
+
end
|
83
|
+
|
84
|
+
if disk.attached?
|
85
|
+
print "Detaching #{disk.awsid}... "
|
86
|
+
disk.detach
|
87
|
+
Rudy::Utils.waiter(2, 60, STDOUT, 'done', nil) {
|
88
|
+
disk.available?
|
89
|
+
}
|
90
|
+
sleep 0.5
|
91
|
+
end
|
92
|
+
|
93
|
+
print "Destroying metadata... "
|
94
|
+
disk.destroy
|
95
|
+
puts "done"
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end;end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
|
4
|
+
module Rudy; module Routines;
|
5
|
+
|
6
|
+
module ScriptHelper
|
7
|
+
extend self
|
8
|
+
|
9
|
+
@@script_types = [:after, :before, :after_local, :before_local]
|
10
|
+
@@script_config_file = "rudy-config.yml"
|
11
|
+
|
12
|
+
def before_local(routine, sconf, rbox)
|
13
|
+
execute_command(:before_local, routine, sconf, 'localhost', rbox)
|
14
|
+
end
|
15
|
+
def after_local(routine, sconf, rbox)
|
16
|
+
execute_command(:after_local, routine, sconf, 'localhost', rbox)
|
17
|
+
end
|
18
|
+
|
19
|
+
def before(routine, sconf, machine, rbox)
|
20
|
+
raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
|
21
|
+
execute_command(:before, routine, sconf, machine.name, rbox)
|
22
|
+
end
|
23
|
+
def after(routine, sconf, machine, rbox)
|
24
|
+
raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
|
25
|
+
execute_command(:after, routine, sconf, machine.name, rbox)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# * +timing+ is one of: after, before
|
32
|
+
# * +routine+ a single routine hash (startup, shutdown, etc...)
|
33
|
+
# * +sconf+ is a config hash from machines config (ignored if nil)
|
34
|
+
# * +hostname+ machine hostname that we're working on
|
35
|
+
# * +rbox+ a Rye::Box instance for the machine we're working on
|
36
|
+
def execute_command(timing, routine, sconf, hostname, rbox)
|
37
|
+
raise "ScriptHelper: Not a Rye::Box" unless rbox.is_a?(Rye::Box)
|
38
|
+
raise "ScriptHelper: #{timing}?" unless @@script_types.member?(timing)
|
39
|
+
|
40
|
+
if sconf && !sconf.empty?
|
41
|
+
tf = Tempfile.new(@@script_config_file)
|
42
|
+
Rudy::Utils.write_to_file(tf.path, sconf.to_hash.to_yaml, 'w')
|
43
|
+
end
|
44
|
+
|
45
|
+
# We need to explicitly add the rm command for rbox so we
|
46
|
+
# can delete the script config file when we're done. This
|
47
|
+
# add the method on for the instance of rbox we are using.
|
48
|
+
def rbox.rm(*args); cmd('rm', args); end
|
49
|
+
|
50
|
+
if routine.is_a?(Caesars::Hash) && routine.has_key?(timing)
|
51
|
+
puts "Connecting to #{hostname}"
|
52
|
+
rbox.connect
|
53
|
+
original_user = rbox.user
|
54
|
+
scripts = [routine[timing]].flatten
|
55
|
+
scripts.each do |script|
|
56
|
+
user, command, *args = script.to_a.flatten.compact
|
57
|
+
rbox.switch_user user # does nothing if it's the same user
|
58
|
+
puts "Creating #{@@script_config_file}"
|
59
|
+
rbox.safe = false
|
60
|
+
puts rbox.echo("'#{sconf.to_hash.to_yaml}' > #{@@script_config_file}")
|
61
|
+
rbox.safe = true
|
62
|
+
rbox.chmod(600, @@script_config_file)
|
63
|
+
puts %Q{Running (as #{user}): #{rbox.preview_command(command, args)}}
|
64
|
+
|
65
|
+
begin
|
66
|
+
ret = rbox.send(command, args)
|
67
|
+
if ret.exit_code > 0
|
68
|
+
puts " Exit code: #{ret.exit_code}".color(:red)
|
69
|
+
puts " STDERR: #{ret.stderr.join("#{$/} ")}".color(:red)
|
70
|
+
puts " STDOUT: #{ret.stdout.join("#{$/} ")}".color(:red)
|
71
|
+
else
|
72
|
+
puts ' ' << ret.stdout.join("#{$/} ")
|
73
|
+
end
|
74
|
+
rescue Rye::CommandNotFound => ex
|
75
|
+
puts " CommandNotFound: #{ex.message}".color(:red)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
rbox.rm(@@script_config_file)
|
80
|
+
end
|
81
|
+
rbox.switch_user original_user
|
82
|
+
else
|
83
|
+
#puts "Nothing to do"
|
84
|
+
end
|
85
|
+
|
86
|
+
tf.delete # delete local copy of script config
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end;end
|
@@ -1,15 +1,34 @@
|
|
1
|
-
module Rudy
|
2
|
-
module Routines
|
3
|
-
class Release < Rudy::Routines::Base
|
4
|
-
|
5
1
|
|
6
|
-
|
7
|
-
|
8
|
-
end
|
2
|
+
module Rudy; module Routines;
|
3
|
+
class Release < Rudy::Routines::Base
|
9
4
|
|
5
|
+
def execute
|
6
|
+
p find_scm(:release)
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
private
|
11
|
+
def find_scm(routine)
|
12
|
+
env, rol, att = @@global.environment, @@global.role
|
10
13
|
|
14
|
+
# Look for the source control engine, checking all known scm values.
|
15
|
+
# The available one will look like [environment][role][release][svn]
|
16
|
+
params = nil
|
17
|
+
scm_name = nil
|
18
|
+
SUPPORTED_SCM_NAMES.each do |v|
|
19
|
+
scm_name = v
|
20
|
+
params = @@config.routines.find(env, rol, routine, scm_name)
|
21
|
+
break if params
|
22
|
+
end
|
23
|
+
|
24
|
+
if params
|
25
|
+
klass = eval "Rudy::SCM::#{scm_name.to_s.upcase}"
|
26
|
+
scm = klass.new(:base => params[:base])
|
27
|
+
end
|
11
28
|
|
29
|
+
[scm, params]
|
12
30
|
|
13
31
|
end
|
32
|
+
|
14
33
|
end
|
15
|
-
end
|
34
|
+
end;end
|
@@ -1,42 +1,57 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
module Rudy
|
4
|
-
module Routines
|
5
|
-
class Shutdown < Rudy::Routines::Base
|
6
|
-
|
7
|
-
def shutdown
|
8
|
-
routine = fetch_routine(:shutdown)
|
9
|
-
rmach = Rudy::Instances.new(:config => @config, :global => @global)
|
10
|
-
rmach.destroy do
|
11
|
-
@logger.puts $/, "Running BEFORE scripts...", $/
|
12
|
-
#instances.each { |inst| @script_runner.execute(inst, :shutdown, :before) }
|
13
|
-
|
14
|
-
@logger.puts $/, "Running DISK routines...", $/
|
15
|
-
routine.disks.each_pair do |action,disks|
|
3
|
+
module Rudy; module Routines;
|
16
4
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
5
|
+
class Shutdown < Rudy::Routines::Base
|
6
|
+
|
7
|
+
def execute
|
8
|
+
raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
|
9
|
+
rmach = Rudy::Machines.new
|
10
|
+
routine = fetch_routine_config(:shutdown)
|
11
|
+
rbox_local = Rye::Box.new('localhost')
|
12
|
+
sconf = fetch_script_config
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
14
|
+
# Runs "before_local" scripts of routines config.
|
15
|
+
puts task_separator("BEFORE SCRIPTS (local)")
|
16
|
+
Rudy::Routines::ScriptHelper.before_local(routine, sconf, rbox_local)
|
17
|
+
|
18
|
+
rmach.destroy do |machine|
|
19
|
+
#rmach.list do |machine|
|
20
|
+
|
21
|
+
print "Waiting for instance..."
|
22
|
+
isup = Rudy::Utils.waiter(3, 120, STDOUT, "it's up!", 0) {
|
23
|
+
inst = machine.get_instance
|
24
|
+
inst && inst.running?
|
25
|
+
}
|
26
|
+
machine.update # Add instance info to machine and save it
|
27
|
+
print "Waiting for SSH daemon..."
|
28
|
+
isup = Rudy::Utils.waiter(2, 60, STDOUT, "it's up!", 0) {
|
29
|
+
Rudy::Utils.service_available?(machine.dns_public, 22)
|
30
|
+
}
|
31
|
+
|
32
|
+
opts = { :keys => root_keypairpath, :user => 'root', :debug => nil }
|
33
|
+
rbox = Rye::Box.new(machine.dns_public, opts)
|
35
34
|
|
35
|
+
# Runs "before" scripts of routines config.
|
36
|
+
puts task_separator("BEFORE SCRIPTS")
|
37
|
+
Rudy::Routines::ScriptHelper.before(routine, sconf, machine, rbox)
|
38
|
+
|
39
|
+
# Runs "disk" portion of routines config
|
40
|
+
puts task_separator("DISK ROUTINES")
|
41
|
+
Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
|
42
|
+
|
43
|
+
puts machine_separator(machine.liner_note)
|
36
44
|
end
|
37
45
|
|
46
|
+
|
47
|
+
# Runs "after_local" scripts
|
48
|
+
# NOTE: There "after" (remote) scripts are not run b/c the machines
|
49
|
+
# are no longer running.
|
50
|
+
puts task_separator("AFTER SCRIPTS (local)")
|
51
|
+
Rudy::Routines::ScriptHelper.after_local(routine, sconf, rbox_local)
|
52
|
+
|
38
53
|
end
|
54
|
+
|
39
55
|
end
|
40
|
-
end
|
41
56
|
|
42
|
-
|
57
|
+
end; end
|