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
@@ -0,0 +1,229 @@
|
|
1
|
+
|
2
|
+
module Rudy; module Routines;
|
3
|
+
class Base
|
4
|
+
include Rudy::Huxtable
|
5
|
+
|
6
|
+
@@run = true
|
7
|
+
|
8
|
+
def self.run?; @@run; end
|
9
|
+
def self.disable_run; @@run = false; end
|
10
|
+
def self.enable_run; @@run = true; end
|
11
|
+
|
12
|
+
def run?; @@run; end
|
13
|
+
def disable_run; @@run = false; end
|
14
|
+
def enable_run; @@run = true; end
|
15
|
+
|
16
|
+
# An Array Rudy::Machines objects that will be processed
|
17
|
+
attr_reader :machines
|
18
|
+
|
19
|
+
# * +name+ The name of the command specified on the command line
|
20
|
+
# * +option+ A Hash or OpenStruct of named command line options.
|
21
|
+
# If it's a Hash it will be converted to an OpenStruct.
|
22
|
+
# * +argv+ An Array of arguments
|
23
|
+
#
|
24
|
+
# +option+ and +argv+ are made available to the routine block.
|
25
|
+
#
|
26
|
+
# routines do
|
27
|
+
# magic do |options,argv|
|
28
|
+
# ...
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
def initialize(name=nil, option={}, argv=[], *args)
|
33
|
+
name ||= (self.class.to_s.split(/::/)).last.downcase
|
34
|
+
option = OpenStruct.new(option) if option.is_a? Hash
|
35
|
+
@name, @option, @argv = name.to_sym, option, argv
|
36
|
+
a, s, r = @@global.accesskey, @@global.secretkey, @@global.region
|
37
|
+
@@sdb ||= Rudy::AWS::SDB.new(a, s, r)
|
38
|
+
|
39
|
+
# Grab the routines configuration for this routine name
|
40
|
+
# e.g. startup, sysupdate, installdeps
|
41
|
+
@routine = fetch_routine_config @name rescue {}
|
42
|
+
|
43
|
+
ld "Routine: #{@routine.inspect}"
|
44
|
+
|
45
|
+
if @routine
|
46
|
+
# Removes the dependencies from the routines hash.
|
47
|
+
# We run these separately from the other actions.
|
48
|
+
@before, @after = @routine.delete(:before), @routine.delete(:after)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Share one Rye::Box instance for localhost across all routines
|
52
|
+
@@lbox = create_rye_box @@global.localhost unless defined?(@@lbox)
|
53
|
+
|
54
|
+
disable_run if @@global.testrun
|
55
|
+
|
56
|
+
# We create these frozen globals for the benefit of
|
57
|
+
# the local and remote routine blocks.
|
58
|
+
$global = @@global.dup.freeze unless $global
|
59
|
+
$option = option.dup.freeze unless $option
|
60
|
+
|
61
|
+
## TODO: get the machine config for just the current machine group. This
|
62
|
+
## probably requires Caesars to be aware of which nodes are structural.
|
63
|
+
##$config = fetch_machine_config unless $config
|
64
|
+
|
65
|
+
init(*args) if respond_to? :init
|
66
|
+
end
|
67
|
+
|
68
|
+
def raise_early_exceptions; raise "Please override"; end
|
69
|
+
def execute; raise "Please override"; end
|
70
|
+
|
71
|
+
# Create an instance of Rye::Box for +hostname+. +opts+ is
|
72
|
+
# an optional Hash of options. See Rye::Box.initialize
|
73
|
+
#
|
74
|
+
# This method should be used throughout the Rudy::Routines
|
75
|
+
# namespace rather than creating instances manually b/c it
|
76
|
+
# applies some fancy pants defaults like command hooks.
|
77
|
+
def create_rye_box(hostname, opts={})
|
78
|
+
ld [:hostname, hostname, opts, caller[0]]
|
79
|
+
opts = {
|
80
|
+
:info => (@@global.verbose >= 3), # rudy -vvv
|
81
|
+
:debug => false,
|
82
|
+
:user => Rudy.sysinfo.user
|
83
|
+
}.merge opts
|
84
|
+
|
85
|
+
box = Rye::Box.new hostname, opts
|
86
|
+
|
87
|
+
|
88
|
+
# We define hooks so we can still print each command and its output
|
89
|
+
# when running the command blocks. NOTE: We only print this in
|
90
|
+
# verbosity mode.
|
91
|
+
if @@global.verbose > 0 && !@@global.parallel
|
92
|
+
# This block gets called for every command method call.
|
93
|
+
box.pre_command_hook do |cmd, user, host, nickname|
|
94
|
+
print_command user, nickname, cmd
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
if @@global.verbose > 1
|
99
|
+
# And this one gets called after each command method call.
|
100
|
+
box.post_command_hook do |ret|
|
101
|
+
print_response ret
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
box.exception_hook(Rye::CommandError, &rbox_exception_handler)
|
106
|
+
box.exception_hook(Exception, &rbox_exception_handler)
|
107
|
+
|
108
|
+
## It'd better for unknown commands to be handled elsewhere
|
109
|
+
## because it doesn't make sense to retry a method that doesn't exist
|
110
|
+
##box.exception_hook(Rye::CommandNotFound, &rbox_exception_handler)
|
111
|
+
|
112
|
+
box
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
# Create an instance of Rye::Set from a list of +hostnames+.
|
118
|
+
# +hostnames+ can contain hostnames or Rudy::Machine objects.
|
119
|
+
# +opts+ is an optional Hash of options. See Rye::Box.initialize
|
120
|
+
#
|
121
|
+
# NOTE: Windows machines are skipped and not added to the set.
|
122
|
+
def create_rye_set(hostnames, opts={})
|
123
|
+
hostnames ||= []
|
124
|
+
|
125
|
+
opts = {
|
126
|
+
:user => (current_machine_user).to_s,
|
127
|
+
:parallel => @@global.parallel
|
128
|
+
}.merge(opts)
|
129
|
+
set = Rye::Set.new current_machine_group, opts
|
130
|
+
|
131
|
+
opts.delete(:parallel) # Not used by Rye::Box.new
|
132
|
+
|
133
|
+
hostnames.each do |m|
|
134
|
+
# This is a short-circuit for Windows instances. We don't support
|
135
|
+
# disks for windows yet and there's no SSH so routines are out of
|
136
|
+
# the picture too.
|
137
|
+
next if (m.os || '').to_s == 'win32'
|
138
|
+
|
139
|
+
if m.is_a?(Rudy::Machine)
|
140
|
+
m.refresh! if m.dns_public.nil? || m.dns_public.empty?
|
141
|
+
if m.dns_public.nil? || m.dns_public.empty?
|
142
|
+
ld "Cannot find public DNS for #{m.name} (continuing...)"
|
143
|
+
##next
|
144
|
+
end
|
145
|
+
ld [:dns_public, m.dns_public, m.instid]
|
146
|
+
rbox = create_rye_box(m.dns_public, opts)
|
147
|
+
rbox.stash = m # Store the machine instance in the stash
|
148
|
+
rbox.nickname = m.name
|
149
|
+
else
|
150
|
+
# Otherwise we assume it's a hostname
|
151
|
+
rbox = create_rye_box(m)
|
152
|
+
end
|
153
|
+
rbox.add_key user_keypairpath(opts[:user])
|
154
|
+
set.add_box rbox
|
155
|
+
end
|
156
|
+
|
157
|
+
ld "Machines Set: %s" % [set.empty? ? '[empty]' : set.inspect]
|
158
|
+
|
159
|
+
set
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
# Returns a formatted string for printing command info
|
166
|
+
def print_command(user, host, cmd)
|
167
|
+
#return if @@global.parallel
|
168
|
+
cmd ||= ""
|
169
|
+
cmd, user = cmd.to_s, user.to_s
|
170
|
+
prompt = user == "root" ? "#" : "$"
|
171
|
+
li ("%s@%s%s %s" % [user, host, prompt, cmd.bright])
|
172
|
+
end
|
173
|
+
|
174
|
+
def print_response(rap)
|
175
|
+
# Non zero exit codes raise exceptions so
|
176
|
+
# the erorrs have already been handled.
|
177
|
+
return if rap.exit_code != 0
|
178
|
+
|
179
|
+
if @@global.parallel
|
180
|
+
cmd, user = cmd.to_s, user.to_s
|
181
|
+
prompt = user == "root" ? "#" : "$"
|
182
|
+
li "%s@%s%s %s%s%s" % [rap.box.user, rap.box.nickname, prompt, rap.cmd.bright, $/, rap.stdout.inspect]
|
183
|
+
unless rap.stderr.empty?
|
184
|
+
le "#{rap.box.nickname}: " << rap.stderr.join("#{rap.box.nickname}: ")
|
185
|
+
end
|
186
|
+
else
|
187
|
+
li ' ' << rap.stdout.join("#{$/} ") if !rap.stdout.empty?
|
188
|
+
colour = rap.exit_code != 0 ? :red : :normal
|
189
|
+
unless rap.stderr.empty?
|
190
|
+
le (" STDERR " << '-'*38).color(colour).bright
|
191
|
+
le " " << rap.stderr.join("#{$/} ").color(colour)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def rbox_exception_handler
|
199
|
+
Proc.new do |ex, cmd, user, host, nickname|
|
200
|
+
print_exception(user, host, cmd, nickname, ex)
|
201
|
+
unless @@global.parallel
|
202
|
+
choice = Annoy.get_user_input('(S)kip (R)etry (F)orce (A)bort: ', nil, 3600) || ''
|
203
|
+
if choice.match(/\AS/i)
|
204
|
+
:skip
|
205
|
+
elsif choice.match(/\AR/i)
|
206
|
+
:retry # Tells Rye::Box#run_command to retry
|
207
|
+
elsif choice.match(/\AF/i)
|
208
|
+
@@global.force = true
|
209
|
+
:retry
|
210
|
+
else
|
211
|
+
exit 12
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def print_exception(user, host, cmd, nickname, ex)
|
218
|
+
prefix = @@global.parallel ? "#{nickname}: #{cmd}: " : ""
|
219
|
+
if ex.is_a?(Rye::CommandError)
|
220
|
+
le prefix << ex.message.color(:red)
|
221
|
+
else
|
222
|
+
le prefix << "#{ex.class}: #{ex.message}".color(:red)
|
223
|
+
end
|
224
|
+
le *ex.backtrace if @@global.verbose > 2
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
end; end;
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy; module Routines; module Handlers;
|
4
|
+
module Base
|
5
|
+
include Rudy::Huxtable
|
6
|
+
|
7
|
+
def trap_rbox_errors(ret=nil, &command)
|
8
|
+
begin
|
9
|
+
ret = command.call if command
|
10
|
+
return unless ret.is_a?(Rye::Rap)
|
11
|
+
puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
|
12
|
+
print_response(ret)
|
13
|
+
rescue IOError => ex
|
14
|
+
STDERR.puts " Connection Error (#{ex.message})".color(:red)
|
15
|
+
choice = Annoy.get_user_input('(S)kip (A)bort: ', nil, 3600) || ''
|
16
|
+
if choice.match(/\AS/i)
|
17
|
+
return
|
18
|
+
#elsif choice.match(/\AR/i)
|
19
|
+
# retry
|
20
|
+
else
|
21
|
+
exit 12
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
ret
|
26
|
+
end
|
27
|
+
|
28
|
+
def keep_going?
|
29
|
+
Annoy.pose_question(" Keep going?\a ", /yes|y|ya|sure|you bet!/i, STDERR)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
def print_response(rap)
|
35
|
+
colour = rap.exit_code != 0 ? :red : :normal
|
36
|
+
[:stderr].each do |sumpin|
|
37
|
+
next if rap.send(sumpin).empty?
|
38
|
+
STDERR.puts
|
39
|
+
STDERR.puts((" #{sumpin.to_s.upcase} " << '-'*38).color(colour).bright)
|
40
|
+
STDERR.puts " " << rap.send(sumpin).join("#{$/} ").color(colour)
|
41
|
+
end
|
42
|
+
STDERR.puts " Exit code: #{rap.exit_code}".color(colour) if rap.exit_code != 0
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end; end; end
|
48
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Rudy; module Routines; module Handlers;
|
3
|
+
module Depends
|
4
|
+
include Rudy::Routines::Handlers::Base
|
5
|
+
extend self
|
6
|
+
|
7
|
+
## NOTE: Dependencies don't use Rudy::Routines.add_handler but we
|
8
|
+
## define them ehere anyway so raise_early_exceptions passes.
|
9
|
+
Rudy::Routines.add_handler :before, self
|
10
|
+
Rudy::Routines.add_handler :after, self
|
11
|
+
|
12
|
+
def raise_early_exceptions(type, depends, rset, lbox, argv=nil)
|
13
|
+
unless depends.kind_of? Array
|
14
|
+
raise Rudy::Error, "#{type} must be a kind of Array (#{depends.class})"
|
15
|
+
end
|
16
|
+
raise Rudy::Routines::EmptyDepends, type if depends.nil? || depends.empty?
|
17
|
+
depends.flatten.compact.each do |name|
|
18
|
+
raise Rudy::Routines::NoRoutine, name unless valid_routine?(name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# A simple wrapper for executing a routine.
|
23
|
+
#
|
24
|
+
# * +routine_name+ should be a Symbol representing a routine
|
25
|
+
# available to the current machine group.
|
26
|
+
#
|
27
|
+
# This method finds the handler for the given routine,
|
28
|
+
# creates an instance, calls raise_early_exceptions,
|
29
|
+
# and finally executes the routine.
|
30
|
+
def execute(routine_name)
|
31
|
+
routine_obj = Rudy::Routines.get_routine routine_name
|
32
|
+
ld "Executing dependency: #{routine_name} (#{routine_obj})"
|
33
|
+
routine = routine_obj.new routine_name
|
34
|
+
routine.raise_early_exceptions
|
35
|
+
routine.execute
|
36
|
+
end
|
37
|
+
|
38
|
+
# Calls execute for each routine name in +depends+ (an Array).
|
39
|
+
# Does nothing if given an empty Array or nil.
|
40
|
+
def execute_all(depends)
|
41
|
+
return if depends.nil? || depends.empty?
|
42
|
+
depends = depends.flatten.compact
|
43
|
+
ld "Found depenencies: #{depends.join(', ')}"
|
44
|
+
depends.each { |routine| execute(routine) }
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end; end; end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
|
2
|
+
module Rudy::Routines::Handlers;
|
3
|
+
module Disks
|
4
|
+
include Rudy::Routines::Handlers::Base
|
5
|
+
extend self
|
6
|
+
|
7
|
+
ACTIONS = [:create, :destroy, :archive, :mount, :restore,
|
8
|
+
:attach, :detach, :mount, :umount].freeze
|
9
|
+
|
10
|
+
Rudy::Routines.add_handler :disks, self
|
11
|
+
|
12
|
+
def raise_early_exceptions(type, batch, rset, lbox, argv=nil)
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def any?(routine)
|
17
|
+
(routine.kind_of?(Hash) && routine.disks &&
|
18
|
+
routine.disks.kind_of?(Hash) && !routine.disks.empty?) ? true : false
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create mount?, create?, umount? etc... methods
|
22
|
+
ACTIONS.each do |action|
|
23
|
+
define_method "#{action}?" do |routine|
|
24
|
+
return false unless any? routine
|
25
|
+
routine.disks.member? action
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def paths(routine)
|
30
|
+
return nil unless disks?(routine)
|
31
|
+
routine.disks.values.collect { |d| d.keys }.flatten
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def execute(type, routine, rset, lbox, argv=nil)
|
36
|
+
original_user = rset.user
|
37
|
+
rset.add_key user_keypairpath('root')
|
38
|
+
rset.switch_user 'root'
|
39
|
+
|
40
|
+
# We need to add mkfs since it's not enabled by default.
|
41
|
+
# We prepend the command with rudy_ so we can delete it.
|
42
|
+
Rye::Cmd.add_command(:rudy_mkfs, 'mkfs')
|
43
|
+
|
44
|
+
routine.each_pair do |action, disks|
|
45
|
+
unless respond_to?(action.to_sym)
|
46
|
+
Rudy::Huxtable.le %Q(DiskHelper: unknown action "#{action}")
|
47
|
+
next
|
48
|
+
end
|
49
|
+
# A quick hack to take advantage of the threading in Rye::Set.
|
50
|
+
# The action method does not run in the context of a Rye::Box
|
51
|
+
# object so we need to send rset as an argument.
|
52
|
+
rset.batch do
|
53
|
+
disks.each_pair do |path, props|
|
54
|
+
# self contains the current instance of Rye::Box.
|
55
|
+
disk = Rudy::Disk.new(self.stash.position, path, props)
|
56
|
+
Rudy::Routines::Handlers::Disks.send(action, self, disk)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
Rye::Cmd.remove_command(:rudy_mkfs)
|
63
|
+
|
64
|
+
rset.switch_user original_user
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def create(rbox, disk)
|
69
|
+
if disk.exists?
|
70
|
+
puts "Disk found: #{disk.name}"
|
71
|
+
disk.refresh!
|
72
|
+
end
|
73
|
+
|
74
|
+
unless @@global.force
|
75
|
+
raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
|
76
|
+
end
|
77
|
+
|
78
|
+
unless disk.volume_exists?
|
79
|
+
msg = "Creating volume... "
|
80
|
+
disk.create
|
81
|
+
Rudy::Utils.waiter(2, 60, STDOUT, msg) {
|
82
|
+
disk.volume_available?
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
attach rbox, disk unless disk.volume_attached?
|
87
|
+
format rbox, disk if disk.raw?
|
88
|
+
mount rbox, disk unless disk.mounted?
|
89
|
+
|
90
|
+
disk.save :replace
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
def detach(rbox, disk)
|
96
|
+
|
97
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
98
|
+
disk.refresh!
|
99
|
+
|
100
|
+
raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
|
101
|
+
|
102
|
+
umount rbox, disk if disk.mounted?
|
103
|
+
raise Rudy::Disks::InUse, disk.name if disk.mounted?
|
104
|
+
|
105
|
+
msg = "Detaching #{disk.volid}..."
|
106
|
+
disk.volume_detach
|
107
|
+
Rudy::Utils.waiter(2, 60, STDOUT, msg) {
|
108
|
+
disk.volume_available?
|
109
|
+
}
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
def attach(rbox, disk)
|
114
|
+
|
115
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
116
|
+
disk.refresh!
|
117
|
+
|
118
|
+
raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
|
119
|
+
|
120
|
+
msg = "Attaching #{disk.volid} to #{rbox.stash.instid}... "
|
121
|
+
disk.volume_attach(rbox.stash.instid)
|
122
|
+
Rudy::Utils.waiter(2, 10, STDOUT, msg) {
|
123
|
+
disk.volume_attached?
|
124
|
+
}
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def mount(rbox, disk)
|
129
|
+
|
130
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
131
|
+
disk.refresh!
|
132
|
+
attach rbox, disk unless disk.volume_attached?
|
133
|
+
|
134
|
+
unless @@global.force
|
135
|
+
raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
|
136
|
+
raise Rudy::Disks::NotFormatted, disk.name if disk.raw?
|
137
|
+
raise Rudy::Disks::AlreadyMounted, disk.name if disk.mounted?
|
138
|
+
end
|
139
|
+
|
140
|
+
rbox.mkdir(:p, disk.path)
|
141
|
+
|
142
|
+
puts "Mounting at #{disk.path}... "
|
143
|
+
|
144
|
+
rbox.mount(:t, disk.fstype, disk.device, disk.path)
|
145
|
+
disk.mounted = true
|
146
|
+
disk.save :replace
|
147
|
+
sleep 1
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
def umount(rbox, disk)
|
152
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
153
|
+
disk.refresh!
|
154
|
+
|
155
|
+
raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
|
156
|
+
if @@global.force
|
157
|
+
raise Rudy::Disks::NotMounted, disk.name if !disk.mounted?
|
158
|
+
end
|
159
|
+
|
160
|
+
puts "Unmounting #{disk.path}... "
|
161
|
+
rbox.umount(disk.path)
|
162
|
+
disk.mounted = false
|
163
|
+
disk.save :replace
|
164
|
+
sleep 2
|
165
|
+
end
|
166
|
+
alias_method :unmount, :umount
|
167
|
+
|
168
|
+
def format(rbox, disk)
|
169
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
170
|
+
disk.refresh!
|
171
|
+
|
172
|
+
attach rbox, disk unless disk.volume_attached?
|
173
|
+
|
174
|
+
raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
|
175
|
+
|
176
|
+
unless @@global.force
|
177
|
+
raise Rudy::Disks::AlreadyFormatted, disk.name if !disk.raw?
|
178
|
+
end
|
179
|
+
|
180
|
+
disk.fstype = 'ext3' if disk.fstype.nil? || disk.fstype.empty?
|
181
|
+
|
182
|
+
puts "Creating #{disk.fstype} filesystem for #{disk.device}... "
|
183
|
+
rbox.rudy_mkfs(:t, disk.fstype, :F, disk.device)
|
184
|
+
disk.raw = false
|
185
|
+
disk.save :replace
|
186
|
+
end
|
187
|
+
|
188
|
+
def destroy(rbox, disk)
|
189
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
190
|
+
disk.refresh!
|
191
|
+
|
192
|
+
umount rbox, disk if disk.mounted?
|
193
|
+
detach rbox, disk if disk.volume_attached?
|
194
|
+
|
195
|
+
unless @@global.force
|
196
|
+
raise Rudy::Disks::InUse, disk.name if disk.volume_attached?
|
197
|
+
end
|
198
|
+
|
199
|
+
puts "Destroying #{disk.name}"
|
200
|
+
disk.destroy
|
201
|
+
end
|
202
|
+
|
203
|
+
def archive(rbox, disk)
|
204
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
205
|
+
disk.refresh!
|
206
|
+
|
207
|
+
raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
|
208
|
+
|
209
|
+
back = disk.archive
|
210
|
+
puts "Created backup: #{back.name}"
|
211
|
+
end
|
212
|
+
|
213
|
+
def restore(rbox, disk)
|
214
|
+
|
215
|
+
if disk.exists?
|
216
|
+
puts "Disk found: #{disk.name}"
|
217
|
+
disk.refresh!
|
218
|
+
end
|
219
|
+
|
220
|
+
unless @@global.force
|
221
|
+
raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
|
222
|
+
end
|
223
|
+
|
224
|
+
latest_backup = disk.backups.last
|
225
|
+
latest_backup.fstype = 'ext3' if latest_backup.fstype.nil? || latest_backup.fstype.empty?
|
226
|
+
disk.size, disk.fstype = latest_backup.size, latest_backup.fstype
|
227
|
+
|
228
|
+
puts "Backup found: #{latest_backup.name}"
|
229
|
+
|
230
|
+
unless disk.volume_exists?
|
231
|
+
msg = "Creating volume... "
|
232
|
+
disk.create latest_backup.size, latest_backup.zone, latest_backup.snapid
|
233
|
+
Rudy::Utils.waiter(2, 60, STDOUT, msg) {
|
234
|
+
disk.volume_available?
|
235
|
+
}
|
236
|
+
disk.raw = false
|
237
|
+
disk.save :replace
|
238
|
+
end
|
239
|
+
|
240
|
+
attach rbox, disk unless disk.volume_attached?
|
241
|
+
mount rbox, disk unless disk.mounted?
|
242
|
+
|
243
|
+
disk.save :replace
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
end
|
249
|
+
end
|