sabat-rudy 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/CHANGES.txt +188 -0
  2. data/LICENSE.txt +19 -0
  3. data/README.rdoc +118 -0
  4. data/Rakefile +165 -0
  5. data/Rudyfile +184 -0
  6. data/bin/ird +153 -0
  7. data/bin/rudy +232 -0
  8. data/bin/rudy-ec2 +241 -0
  9. data/bin/rudy-s3 +79 -0
  10. data/bin/rudy-sdb +69 -0
  11. data/examples/README.md +10 -0
  12. data/examples/debian-sinatra-passenger/commands.rb +19 -0
  13. data/examples/debian-sinatra-passenger/machines.rb +32 -0
  14. data/examples/debian-sinatra-passenger/routines.rb +30 -0
  15. data/examples/debian-sinatra-thin/commands.rb +17 -0
  16. data/examples/debian-sinatra-thin/machines.rb +35 -0
  17. data/examples/debian-sinatra-thin/routines.rb +72 -0
  18. data/lib/rudy.rb +170 -0
  19. data/lib/rudy/aws.rb +75 -0
  20. data/lib/rudy/aws/ec2.rb +59 -0
  21. data/lib/rudy/aws/ec2/address.rb +157 -0
  22. data/lib/rudy/aws/ec2/group.rb +301 -0
  23. data/lib/rudy/aws/ec2/image.rb +168 -0
  24. data/lib/rudy/aws/ec2/instance.rb +438 -0
  25. data/lib/rudy/aws/ec2/keypair.rb +104 -0
  26. data/lib/rudy/aws/ec2/snapshot.rb +109 -0
  27. data/lib/rudy/aws/ec2/volume.rb +230 -0
  28. data/lib/rudy/aws/ec2/zone.rb +77 -0
  29. data/lib/rudy/aws/s3.rb +60 -0
  30. data/lib/rudy/aws/sdb.rb +312 -0
  31. data/lib/rudy/aws/sdb/error.rb +47 -0
  32. data/lib/rudy/cli.rb +186 -0
  33. data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
  34. data/lib/rudy/cli/aws/ec2/candy.rb +191 -0
  35. data/lib/rudy/cli/aws/ec2/groups.rb +118 -0
  36. data/lib/rudy/cli/aws/ec2/images.rb +185 -0
  37. data/lib/rudy/cli/aws/ec2/instances.rb +222 -0
  38. data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
  39. data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
  40. data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
  41. data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
  42. data/lib/rudy/cli/aws/s3/buckets.rb +49 -0
  43. data/lib/rudy/cli/aws/s3/store.rb +22 -0
  44. data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
  45. data/lib/rudy/cli/candy.rb +19 -0
  46. data/lib/rudy/cli/config.rb +81 -0
  47. data/lib/rudy/cli/disks.rb +58 -0
  48. data/lib/rudy/cli/machines.rb +114 -0
  49. data/lib/rudy/cli/routines.rb +108 -0
  50. data/lib/rudy/config.rb +116 -0
  51. data/lib/rudy/config/objects.rb +148 -0
  52. data/lib/rudy/global.rb +130 -0
  53. data/lib/rudy/guidelines.rb +18 -0
  54. data/lib/rudy/huxtable.rb +373 -0
  55. data/lib/rudy/machines.rb +281 -0
  56. data/lib/rudy/metadata.rb +51 -0
  57. data/lib/rudy/metadata/backup.rb +113 -0
  58. data/lib/rudy/metadata/backups.rb +65 -0
  59. data/lib/rudy/metadata/disk.rb +177 -0
  60. data/lib/rudy/metadata/disks.rb +67 -0
  61. data/lib/rudy/metadata/objectbase.rb +104 -0
  62. data/lib/rudy/mixins.rb +2 -0
  63. data/lib/rudy/mixins/hash.rb +25 -0
  64. data/lib/rudy/routines.rb +318 -0
  65. data/lib/rudy/routines/helper.rb +55 -0
  66. data/lib/rudy/routines/helpers/dependshelper.rb +34 -0
  67. data/lib/rudy/routines/helpers/diskhelper.rb +331 -0
  68. data/lib/rudy/routines/helpers/scmhelper.rb +39 -0
  69. data/lib/rudy/routines/helpers/scripthelper.rb +198 -0
  70. data/lib/rudy/routines/helpers/userhelper.rb +37 -0
  71. data/lib/rudy/routines/passthrough.rb +38 -0
  72. data/lib/rudy/routines/reboot.rb +75 -0
  73. data/lib/rudy/routines/release.rb +50 -0
  74. data/lib/rudy/routines/shutdown.rb +33 -0
  75. data/lib/rudy/routines/startup.rb +36 -0
  76. data/lib/rudy/scm.rb +75 -0
  77. data/lib/rudy/scm/git.rb +217 -0
  78. data/lib/rudy/scm/svn.rb +110 -0
  79. data/lib/rudy/utils.rb +365 -0
  80. data/rudy.gemspec +151 -0
  81. data/support/mailtest +40 -0
  82. data/support/randomize-root-password +45 -0
  83. data/support/rudy-ec2-startup +200 -0
  84. data/support/update-ec2-ami-tools +20 -0
  85. data/test/01_mixins/10_hash_test.rb +25 -0
  86. data/test/10_config/00_setup_test.rb +20 -0
  87. data/test/10_config/30_machines_test.rb +69 -0
  88. data/test/15_scm/00_setup_test.rb +20 -0
  89. data/test/15_scm/20_git_test.rb +61 -0
  90. data/test/20_sdb/00_setup_test.rb +16 -0
  91. data/test/20_sdb/10_domains_test.rb +115 -0
  92. data/test/25_ec2/00_setup_test.rb +29 -0
  93. data/test/25_ec2/10_keypairs_test.rb +41 -0
  94. data/test/25_ec2/20_groups_test.rb +131 -0
  95. data/test/25_ec2/30_addresses_test.rb +38 -0
  96. data/test/25_ec2/40_volumes_test.rb +49 -0
  97. data/test/25_ec2/50_snapshots_test.rb +74 -0
  98. data/test/26_ec2_instances/00_setup_test.rb +28 -0
  99. data/test/26_ec2_instances/10_instances_test.rb +83 -0
  100. data/test/26_ec2_instances/50_images_test.rb +13 -0
  101. data/test/30_sdb_metadata/00_setup_test.rb +21 -0
  102. data/test/30_sdb_metadata/10_disks_test.rb +109 -0
  103. data/test/30_sdb_metadata/20_backups_test.rb +102 -0
  104. data/test/coverage.txt +51 -0
  105. data/test/helper.rb +36 -0
  106. metadata +276 -0
@@ -0,0 +1,198 @@
1
+ require 'tempfile'
2
+
3
+ module Rudy; module Routines;
4
+ #--
5
+ # TODO: Rename to ShellHelper
6
+ #++
7
+ module ScriptHelper
8
+ include Rudy::Routines::HelperBase # TODO: use execute_rbox_command
9
+ extend self
10
+
11
+ @@script_types = [:after, :before, :after_local, :before_local, :script, :script_local]
12
+ @@script_config_file = "rudy-config.yml"
13
+
14
+ # TODO: refactor using this_method
15
+
16
+ def before_local(routine, sconf, rbox)
17
+ execute_command(:before_local, routine, sconf, 'localhost', rbox)
18
+ end
19
+ def before_local?(routine)
20
+ # before_local generally doesn't take a user name like the remote
21
+ # before block so we add it here (unless the user did specify it)
22
+ routine[:before_local] = {
23
+ Rudy.sysinfo.user.to_sym => routine.delete(:before_local)
24
+ } if routine[:before_local].is_a?(Proc)
25
+ execute_command?(:before_local, routine)
26
+ end
27
+ def script_local(routine, sconf, rbox)
28
+ execute_command(:script_local, routine, sconf, 'localhost', rbox)
29
+ end
30
+ def script_local?(routine)
31
+ # before_local generally doesn't take a user name like the remote
32
+ # before block so we add it here (unless the user did specify it)
33
+ routine[:script_local] = {
34
+ Rudy.sysinfo.user.to_sym => routine.delete(:script_local)
35
+ } if routine[:script_local].is_a?(Proc)
36
+ execute_command?(:script_local, routine)
37
+ end
38
+
39
+ def after_local(routine, sconf, rbox)
40
+ execute_command(:after_local, routine, sconf, 'localhost', rbox)
41
+ end
42
+ def after_local?(routine)
43
+ routine[:after_local] = { # See before_local note
44
+ Rudy.sysinfo.user.to_sym => routine.delete(:after_local)
45
+ } if routine[:after_local].is_a?(Proc)
46
+ execute_command?(:after_local, routine)
47
+ end
48
+
49
+ def before(routine, sconf, machine, rbox)
50
+ raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
51
+ execute_command(:before, routine, sconf, machine.name, rbox)
52
+ end
53
+ def before?(routine); execute_command?(:before, routine); end
54
+
55
+ def after(routine, sconf, machine, rbox)
56
+ raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
57
+ execute_command(:after, routine, sconf, machine.name, rbox)
58
+ end
59
+ def after?(routine); execute_command?(:after, routine); end
60
+
61
+ def script(routine, sconf, machine, rbox)
62
+ raise "ScriptHelper: Not a Rudy::Machine" unless machine.is_a?(Rudy::Machine)
63
+ execute_command(:script, routine, sconf, machine.name, rbox)
64
+ end
65
+ def script?(routine); execute_command?(:script, routine); end
66
+
67
+
68
+ private
69
+
70
+ # Does the routine have the requested script type?
71
+ # * +timing+ is one of: after, before, after_local, before_local
72
+ # * +routine+ a single routine hash (startup, shutdown, etc...)
73
+ # Prints notice to STDERR if there's an empty conf hash
74
+ def execute_command?(timing, routine)
75
+ hasconf = (routine.is_a?(Caesars::Hash) && routine.has_key?(timing))
76
+ return false unless hasconf
77
+ unless routine[timing].kind_of?(Hash)
78
+ STDERR.puts "No user supplied for #{timing} block".color(:red)
79
+ exit 12 unless keep_going?
80
+ return false
81
+ end
82
+ routine[timing].each_pair do |user,proc|
83
+ #p [timing, user, proc].join(', ')
84
+ if proc.nil? || !proc.is_a?(Proc)
85
+ STDERR.puts "Empty #{timing} config for #{user}"
86
+ else
87
+ return true
88
+ end
89
+ end
90
+ false
91
+ end
92
+
93
+ # * +timing+ is one of: after, before, after_local, before_local
94
+ # * +routine+ a single routine hash (startup, shutdown, etc...)
95
+ # * +sconf+ is a config hash from machines config (ignored if nil)
96
+ # * +hostname+ machine hostname that we're working on
97
+ # * +rbox+ a Rye::Box instance for the machine we're working on
98
+ def execute_command(timing, routine, sconf, hostname, rbox)
99
+ raise "ScriptHelper: Not a Rye::Box" unless rbox.is_a?(Rye::Box)
100
+ raise "ScriptHelper: #{timing}?" unless @@script_types.member?(timing)
101
+
102
+ if sconf && !sconf.empty?
103
+ tf = Tempfile.new(@@script_config_file)
104
+ Rudy::Utils.write_to_file(tf.path, sconf.to_hash.to_yaml, 'w')
105
+ end
106
+
107
+ # Do we need to run this again? It's called in generic_routine_runner
108
+ ##if execute_command?(timing, routine) # i.e. before_local?
109
+
110
+ # We need to explicitly add the rm command for rbox so we
111
+ # can delete the script config file when we're done. This
112
+ # adds the method to this instance of rbox only.
113
+ # We give it a funny so we can delete it knowing we're not
114
+ # deleting a method added somewhere else.
115
+ def rbox.rudy_tmp_rm(*args); cmd('rm', args); end
116
+
117
+ original_user = rbox.user
118
+ user_blocks = routine[timing] || {}
119
+ users = user_blocks.keys
120
+ # Root stuff is always run first.
121
+ users.unshift(users.delete(:root)) if users.member?(:root)
122
+ users.each do |user|
123
+ proc = user_blocks[user]
124
+
125
+ begin
126
+ rbox.switch_user user # does nothing if it's the same user
127
+ rbox.connect(false) # does nothing if already connected
128
+ rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch => ex
129
+ STDERR.puts "Error connecting: #{ex.message}".color(:red)
130
+ STDERR.puts "Skipping user #{user}".color(:red)
131
+ next
132
+ end
133
+
134
+ execute_rbox_command {
135
+ # We need to create the config file for every script,
136
+ # b/c the user may change and it would not be accessible.
137
+ # We turn off safe mode so we can write the config file via SSH.
138
+ # This will need to use SCP eventually; it is unsafe and error prone.
139
+ # TODO: Replace with rbox.upload. Make it safe again!
140
+ conf_str = StringIO.new
141
+ conf_str.puts sconf.to_hash.to_yaml
142
+ rbox.upload(conf_str, @@script_config_file)
143
+ rbox.chmod(600, @@script_config_file)
144
+ }
145
+
146
+ begin
147
+ # We define hooks so we can call the script block as a batch.
148
+ # We intentionally set and unset the hooks so the other commands
149
+ # (config file copy) don't get printed.
150
+ #
151
+ # This block gets called for every command method call.
152
+ rbox.pre_command_hook do |cmd, args, user|
153
+ puts command_separator(rbox.preview_command(cmd, args), user)
154
+ end
155
+ # And this one gets called after each command method call.
156
+ rbox.post_command_hook do |ret|
157
+ puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
158
+ print_response(ret)
159
+ end
160
+
161
+ ### EXECUTE THE COMMANDS BLOCK
162
+ rbox.batch(&proc)
163
+
164
+ rbox.pre_command_hook = nil
165
+ rbox.post_command_hook = nil
166
+ rescue Rye::CommandError => ex
167
+ print_response(ex)
168
+ exit 12 unless keep_going?
169
+ rescue Rye::CommandNotFound => ex
170
+ STDERR.puts " CommandNotFound: #{ex.message}".color(:red)
171
+ STDERR.puts ex.backtrace if Rudy.debug?
172
+ exit 12 unless keep_going?
173
+ end
174
+
175
+ # I was gettings errors about script_config_file not existing. There
176
+ # might be a race condition when the rm command is called too quickly.
177
+ # It's also quite possible I'm off my rocker!
178
+ ## NOTE: I believe this was an issue with Rye. I fixed it when I was
179
+ ## noticing the same error in another place. It hasn't repeated.
180
+ ## sleep 0.1
181
+
182
+ rbox.cd # reset to home dir
183
+ rbox.rudy_tmp_rm(@@script_config_file)
184
+ end
185
+
186
+ # Return the borrowed rbox instance to the user it was provided with
187
+ rbox.switch_user original_user
188
+
189
+ ##else
190
+ ## puts "Nothing to do"
191
+ ##end
192
+
193
+ tf.delete # delete local copy of script config
194
+
195
+ end
196
+ end
197
+
198
+ end;end
@@ -0,0 +1,37 @@
1
+
2
+ module Rudy; module Routines;
3
+ module UserHelper
4
+ include Rudy::Routines::HelperBase # TODO: use execute_rbox_command
5
+ extend self
6
+
7
+ def adduser?(routine)
8
+ (!routine.adduser.nil? && !routine.adduser.to_s.empty?)
9
+ end
10
+ def adduser(routine, machine, rbox)
11
+
12
+ # On Solaris, the user's home directory needs to be specified
13
+ # explicitly so we do it for linux too for fun.
14
+ homedir = rbox.guess_user_home(routine.adduser.to_s)
15
+ args = [:m, :d, homedir, :s, '/bin/bash', routine.adduser.to_s]
16
+ puts command_separator(rbox.preview_command(:useradd, args), rbox.user)
17
+
18
+ # NOTE: We'll may to use platform specific code here.
19
+ # Linux has adduser and useradd commands:
20
+ # adduser can prompt for info which we don't want.
21
+ # useradd does not prompt (on Debian/Ubuntu at least).
22
+ # We need to specify bash b/c the default is /bin/sh
23
+ execute_rbox_command { rbox.useradd(args) }
24
+ end
25
+
26
+ def authorize?(routine)
27
+ (!routine.authorize.nil? && !routine.authorize.to_s.empty?)
28
+ end
29
+ def authorize(routine, machine, rbox)
30
+ puts command_separator(:authorize_keys_remote, rbox.user)
31
+ execute_rbox_command { rbox.authorize_keys_remote(routine.authorize) }
32
+ end
33
+
34
+
35
+ end
36
+
37
+ end; end
@@ -0,0 +1,38 @@
1
+
2
+
3
+ module Rudy; module Routines;
4
+ class Passthrough < Rudy::Routines::Base
5
+
6
+ def init(*args)
7
+ @routine_name = args.first
8
+ @routine = fetch_routine_config(@routine_name)
9
+ end
10
+
11
+ # * +each_mach+ is an optional block which is executed between
12
+ # disk creation and the after scripts. The will receives two
13
+ # arguments: instances of Rudy::Machine and Rye::Box.
14
+ def execute(&each_mach)
15
+ routine_separator(@routine_name)
16
+ machines = []
17
+ generic_machine_runner(:list) do |machine,rbox|
18
+ puts $/ #, "[routine: #{@routine_name}]"
19
+ machines << machine
20
+ end
21
+ machines
22
+ end
23
+
24
+ # Called by generic_machine_runner
25
+ def raise_early_exceptions
26
+ raise Rudy::Error, "No routine name" unless @routine_name
27
+ raise NoRoutine, @routine_name unless @routine
28
+ rmach = Rudy::Machines.new
29
+ raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
30
+ raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
31
+ if !@@global.offline && !rmach.running?
32
+ raise MachineGroupNotRunning, current_machine_group
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end; end
@@ -0,0 +1,75 @@
1
+
2
+
3
+ module Rudy; module Routines;
4
+ class Reboot < Rudy::Routines::Base
5
+
6
+ def init(*args)
7
+ @routine = fetch_routine_config(:reboot)
8
+ end
9
+
10
+ # * +each_mach+ is an optional block which is executed between
11
+ # disk creation and the after scripts. The will receives two
12
+ # arguments: instances of Rudy::Machine and Rye::Box.
13
+ def execute(&each_mach)
14
+ routine_separator(:reboot)
15
+ unless @routine
16
+ STDERR.puts "[this is a generic reboot routine]"
17
+ @routine = {}
18
+ end
19
+ machines = []
20
+ generic_machine_runner(:list) do |machine,rbox|
21
+ puts $/, "Rebooting...", $/
22
+ rbox.disconnect
23
+ machine.restart
24
+ sleep 4
25
+ msg = preliminary_separator("Checking if instance is running...")
26
+ Rudy::Utils.waiter(3, 120, STDOUT, msg, 0) {
27
+ machine.running?
28
+ }
29
+
30
+ # Add instance info to machine and save it. This is really important
31
+ # for the initial startup so the metadata is updated right away. But
32
+ # it's also important to call here because if a routine was executed
33
+ # and an unexpected exception occurs before this update is executed
34
+ # the machine metadata won't contain the DNS information. Calling it
35
+ # here ensure that the metadata is always up-to-date.
36
+ machine.update
37
+
38
+ sleep 4
39
+
40
+ msg = preliminary_separator("Waiting for SSH daemon...")
41
+ Rudy::Utils.waiter(3, 120, STDOUT, msg, 0) {
42
+ Rudy::Utils.service_available?(machine.dns_public, 22)
43
+ }
44
+
45
+ # NOTE: THIS IS INCOMPLETE
46
+
47
+ sleep 1 # Avoid IOError: closed stream on SSH
48
+
49
+
50
+ if Rudy::Routines::DiskHelper.disks?(@routine) # disk
51
+ puts task_separator("DISKS")
52
+ if rbox.ostype == "sunos"
53
+ puts "Sorry, Solaris is not supported yet!"
54
+ else
55
+ Rudy::Routines::DiskHelper.execute(@routine, machine, rbox)
56
+ end
57
+ end
58
+
59
+ machines << machine
60
+ end
61
+ machines
62
+ end
63
+
64
+ # Called by generic_machine_runner
65
+ def raise_early_exceptions
66
+ rmach = Rudy::Machines.new
67
+ # There's no keypair check here because Rudy::Machines will attempt
68
+ # to create one.
69
+ raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
70
+ raise MachineGroupNotRunning, current_machine_group unless rmach.running?
71
+ end
72
+
73
+ end
74
+
75
+ end; end
@@ -0,0 +1,50 @@
1
+
2
+
3
+ module Rudy; module Routines;
4
+ class Release < Rudy::Routines::Base
5
+
6
+ def init(*args)
7
+ @routine_name = args.first || :release # :release or :rerelease
8
+ @routine = fetch_routine_config(@routine_name)
9
+ end
10
+
11
+ def execute()
12
+ routine_separator(@routine_name)
13
+
14
+ vlist = []
15
+
16
+ # Some early version control system failing
17
+ if Rudy::Routines::SCMHelper.scm?(@routine)
18
+ vlist = Rudy::Routines::SCMHelper.create_scm_objects(@routine)
19
+ puts task_separator("CREATING RELEASE TAG#{'S' if vlist.size > 1}")
20
+ vlist.each do |scm|
21
+ scm.create_release(Rudy.sysinfo.user)
22
+ puts scm.liner_note
23
+ end
24
+ end
25
+
26
+ machines = []
27
+ generic_machine_runner(:list) do |machine,rbox|
28
+ vlist.each do |scm|
29
+ puts task_separator("CREATING REMOTE #{scm.engine.to_s.upcase} CHECKOUT")
30
+ scm.create_remote_checkout(rbox)
31
+ end
32
+ machines << machine
33
+ end
34
+
35
+ machines
36
+ end
37
+
38
+ # Called by generic_machine_runner
39
+ def raise_early_exceptions
40
+ raise NoRoutine, :release unless @routine
41
+ rmach = Rudy::Machines.new
42
+ raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
43
+ raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
44
+ raise MachineGroupNotRunning, current_machine_group unless rmach.running?
45
+ end
46
+
47
+
48
+
49
+ end
50
+ end;end
@@ -0,0 +1,33 @@
1
+
2
+
3
+ module Rudy; module Routines;
4
+ class Shutdown < Rudy::Routines::Base
5
+
6
+ def init(*args)
7
+ @routine = fetch_routine_config(:shutdown)
8
+ end
9
+
10
+ def execute
11
+ routine_separator(:shutdown)
12
+ unless @routine
13
+ STDERR.puts "[this is a generic shutdown routine]"
14
+ @routine = {}
15
+ end
16
+ machines = []
17
+ generic_machine_runner(:destroy) do |machine,rbox|
18
+ puts $/, "Shutting down...", $/
19
+ machines << machine
20
+ end
21
+ machines
22
+ end
23
+
24
+ # Called by generic_machine_runner
25
+ def raise_early_exceptions
26
+ rmach = Rudy::Machines.new
27
+ raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
28
+ raise MachineGroupNotRunning, current_machine_group unless rmach.running?
29
+ end
30
+
31
+ end
32
+
33
+ end; end
@@ -0,0 +1,36 @@
1
+
2
+
3
+ module Rudy; module Routines;
4
+ class Startup < Rudy::Routines::Base
5
+
6
+ def init(*args)
7
+ @routine = fetch_routine_config(:startup)
8
+ end
9
+
10
+ # * +each_mach+ is an optional block which is executed between
11
+ # disk creation and the after scripts. The will receives two
12
+ # arguments: instances of Rudy::Machine and Rye::Box.
13
+ # Returns an Array of Rudy::Machine objects
14
+ def execute(&each_mach)
15
+ routine_separator(:startup)
16
+ unless @routine
17
+ STDERR.puts "[this is a generic startup routine]"
18
+ @routine = {}
19
+ end
20
+ machines = generic_machine_runner(:create)
21
+ machines
22
+ end
23
+
24
+ # Called by generic_machine_runner
25
+ def raise_early_exceptions
26
+ rmach = Rudy::Machines.new
27
+ # There's no keypair check here because Rudy::Machines will create one
28
+ raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
29
+ # We don't check @@global.offline b/c we can't create EC2 instances
30
+ # without an internet connection. Use passthrough for routine tests.
31
+ raise MachineGroupAlreadyRunning, current_machine_group if rmach.running?
32
+ end
33
+
34
+ end
35
+
36
+ end; end