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.
Files changed (146) hide show
  1. data/CHANGES.txt +19 -1
  2. data/README.rdoc +66 -35
  3. data/Rakefile +1 -0
  4. data/Rudyfile +97 -6
  5. data/bin/ird +7 -4
  6. data/bin/rudy +120 -212
  7. data/bin/rudy-ec2 +240 -0
  8. data/bin/rudy-s3 +76 -0
  9. data/bin/rudy-sdb +67 -0
  10. data/lib/annoy.rb +61 -18
  11. data/lib/console.rb +10 -5
  12. data/lib/rudy/aws/ec2/address.rb +76 -40
  13. data/lib/rudy/aws/ec2/group.rb +138 -78
  14. data/lib/rudy/aws/ec2/image.rb +134 -12
  15. data/lib/rudy/aws/ec2/instance.rb +116 -89
  16. data/lib/rudy/aws/ec2/keypair.rb +26 -14
  17. data/lib/rudy/aws/ec2/snapshot.rb +23 -12
  18. data/lib/rudy/aws/ec2/volume.rb +198 -202
  19. data/lib/rudy/aws/ec2/zone.rb +77 -0
  20. data/lib/rudy/aws/ec2.rb +56 -25
  21. data/lib/rudy/aws/s3.rb +54 -0
  22. data/lib/rudy/aws/sdb/error.rb +46 -0
  23. data/lib/rudy/aws/sdb.rb +298 -0
  24. data/lib/rudy/aws.rb +29 -57
  25. data/lib/rudy/{metadata/backup.rb → backup.rb} +8 -8
  26. data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
  27. data/lib/rudy/cli/aws/ec2/candy.rb +208 -0
  28. data/lib/rudy/cli/aws/ec2/groups.rb +121 -0
  29. data/lib/rudy/cli/aws/ec2/images.rb +196 -0
  30. data/lib/rudy/cli/aws/ec2/instances.rb +194 -0
  31. data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
  32. data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
  33. data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
  34. data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
  35. data/lib/rudy/cli/aws/s3/buckets.rb +50 -0
  36. data/lib/rudy/cli/aws/s3/store.rb +22 -0
  37. data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
  38. data/lib/rudy/cli/{deploy.rb → candy.rb} +2 -6
  39. data/lib/rudy/cli/config.rb +25 -20
  40. data/lib/rudy/cli/disks.rb +18 -108
  41. data/lib/rudy/cli/machines.rb +94 -0
  42. data/lib/rudy/cli/routines.rb +47 -70
  43. data/lib/rudy/cli.rb +104 -89
  44. data/lib/rudy/config/objects.rb +5 -43
  45. data/lib/rudy/config.rb +8 -24
  46. data/lib/rudy/disks.rb +248 -0
  47. data/lib/rudy/global.rb +121 -0
  48. data/lib/rudy/huxtable.rb +232 -147
  49. data/lib/rudy/machines.rb +245 -0
  50. data/lib/rudy/metadata.rb +136 -0
  51. data/lib/rudy/routines/helpers/diskhelper.rb +101 -0
  52. data/lib/rudy/routines/helpers/scripthelper.rb +91 -0
  53. data/lib/rudy/routines/release.rb +27 -8
  54. data/lib/rudy/routines/shutdown.rb +47 -32
  55. data/lib/rudy/routines/startup.rb +47 -37
  56. data/lib/rudy/routines.rb +30 -37
  57. data/lib/rudy/scm/svn.rb +1 -1
  58. data/lib/rudy/utils.rb +262 -4
  59. data/lib/rudy.rb +76 -248
  60. data/lib/storable.rb +19 -16
  61. data/lib/sysinfo.rb +1 -1
  62. data/rudy.gemspec +88 -68
  63. data/support/rudy-ec2-startup +5 -5
  64. data/test/05_config/00_setup_test.rb +3 -7
  65. data/test/20_sdb/00_setup_test.rb +2 -17
  66. data/test/20_sdb/10_domains_test.rb +18 -16
  67. data/test/25_ec2/00_setup_test.rb +5 -10
  68. data/test/25_ec2/10_keypairs_test.rb +13 -5
  69. data/test/25_ec2/20_groups_test.rb +48 -56
  70. data/test/25_ec2/30_addresses_test.rb +13 -10
  71. data/test/25_ec2/40_volumes_test.rb +11 -8
  72. data/test/25_ec2/50_snapshots_test.rb +17 -12
  73. data/test/26_ec2_instances/00_setup_test.rb +3 -8
  74. data/test/26_ec2_instances/10_instances_test.rb +21 -19
  75. data/test/30_sdb_metadata/00_setup_test.rb +2 -9
  76. data/test/30_sdb_metadata/10_disks_test.rb +47 -37
  77. data/test/30_sdb_metadata/20_backups_test.rb +9 -9
  78. data/test/helper.rb +5 -3
  79. data/vendor/highline-1.5.1/CHANGELOG +222 -0
  80. data/vendor/highline-1.5.1/INSTALL +35 -0
  81. data/vendor/highline-1.5.1/LICENSE +7 -0
  82. data/vendor/highline-1.5.1/README +63 -0
  83. data/vendor/highline-1.5.1/Rakefile +82 -0
  84. data/vendor/highline-1.5.1/TODO +6 -0
  85. data/vendor/highline-1.5.1/examples/ansi_colors.rb +38 -0
  86. data/vendor/highline-1.5.1/examples/asking_for_arrays.rb +18 -0
  87. data/vendor/highline-1.5.1/examples/basic_usage.rb +75 -0
  88. data/vendor/highline-1.5.1/examples/color_scheme.rb +32 -0
  89. data/vendor/highline-1.5.1/examples/limit.rb +12 -0
  90. data/vendor/highline-1.5.1/examples/menus.rb +65 -0
  91. data/vendor/highline-1.5.1/examples/overwrite.rb +19 -0
  92. data/vendor/highline-1.5.1/examples/page_and_wrap.rb +322 -0
  93. data/vendor/highline-1.5.1/examples/password.rb +7 -0
  94. data/vendor/highline-1.5.1/examples/trapping_eof.rb +22 -0
  95. data/vendor/highline-1.5.1/examples/using_readline.rb +17 -0
  96. data/vendor/highline-1.5.1/lib/highline/color_scheme.rb +120 -0
  97. data/vendor/highline-1.5.1/lib/highline/compatibility.rb +17 -0
  98. data/vendor/highline-1.5.1/lib/highline/import.rb +43 -0
  99. data/vendor/highline-1.5.1/lib/highline/menu.rb +395 -0
  100. data/vendor/highline-1.5.1/lib/highline/question.rb +463 -0
  101. data/vendor/highline-1.5.1/lib/highline/system_extensions.rb +193 -0
  102. data/vendor/highline-1.5.1/lib/highline.rb +758 -0
  103. data/vendor/highline-1.5.1/setup.rb +1360 -0
  104. data/vendor/highline-1.5.1/test/tc_color_scheme.rb +56 -0
  105. data/vendor/highline-1.5.1/test/tc_highline.rb +823 -0
  106. data/vendor/highline-1.5.1/test/tc_import.rb +54 -0
  107. data/vendor/highline-1.5.1/test/tc_menu.rb +429 -0
  108. data/vendor/highline-1.5.1/test/ts_all.rb +15 -0
  109. metadata +81 -69
  110. data/lib/aws_sdb/error.rb +0 -42
  111. data/lib/aws_sdb/service.rb +0 -215
  112. data/lib/aws_sdb.rb +0 -3
  113. data/lib/rudy/aws/simpledb.rb +0 -71
  114. data/lib/rudy/cli/addresses.rb +0 -85
  115. data/lib/rudy/cli/backups.rb +0 -175
  116. data/lib/rudy/cli/domains.rb +0 -17
  117. data/lib/rudy/cli/groups.rb +0 -77
  118. data/lib/rudy/cli/images.rb +0 -111
  119. data/lib/rudy/cli/instances.rb +0 -142
  120. data/lib/rudy/cli/keypairs.rb +0 -47
  121. data/lib/rudy/cli/manager.rb +0 -51
  122. data/lib/rudy/cli/release.rb +0 -174
  123. data/lib/rudy/cli/volumes.rb +0 -121
  124. data/lib/rudy/command/addresses.rb +0 -69
  125. data/lib/rudy/command/backups.rb +0 -65
  126. data/lib/rudy/command/disks-old.rb +0 -322
  127. data/lib/rudy/command/disks.rb +0 -9
  128. data/lib/rudy/command/domains.rb +0 -34
  129. data/lib/rudy/command/groups.rb +0 -118
  130. data/lib/rudy/command/instances.rb +0 -278
  131. data/lib/rudy/command/keypairs.rb +0 -149
  132. data/lib/rudy/command/manager.rb +0 -65
  133. data/lib/rudy/command/volumes.rb +0 -127
  134. data/lib/rudy/metadata/disk.rb +0 -149
  135. data/lib/rudy/metadata/machine.rb +0 -34
  136. data/lib/rudy/routines/disk_handler.rb +0 -190
  137. data/lib/rudy/routines/script_runner.rb +0 -65
  138. data/test/50_commands/00_setup_test.rb +0 -11
  139. data/test/50_commands/10_keypairs_test.rb +0 -79
  140. data/test/50_commands/20_groups_test.rb +0 -77
  141. data/test/50_commands/40_volumes_test.rb +0 -55
  142. data/test/50_commands/50_instances_test.rb +0 -110
  143. data/tryouts/console_tryout.rb +0 -91
  144. data/tryouts/disks.rb +0 -55
  145. data/tryouts/nested_methods.rb +0 -36
  146. 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
- def execute()
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
- unless @rdisks.respond_to?(action)
18
- @logger.puts("Skipping unknown action: #{action}").color(:blue)
19
- next
20
- end
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
- disks.each_pair do |path,props|
23
- props[:path] = path
24
- begin
25
- @rdisks.send(action, instance, props)
26
- rescue => ex
27
- @logger.puts ex.message
28
- @logger.puts "Continuing..."
29
- @logger.puts ex.backtrace if debug?
30
- end
31
- end
32
-
33
- end
34
- end
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