solutious-rudy 0.8.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/CHANGES.txt +55 -14
  2. data/README.rdoc +26 -34
  3. data/Rudyfile +27 -32
  4. data/bin/rudy +47 -27
  5. data/bin/rudy-ec2 +2 -16
  6. data/bin/rudy-s3 +0 -10
  7. data/bin/rudy-sdb +11 -12
  8. data/lib/rudy.rb +49 -89
  9. data/lib/rudy/aws.rb +2 -43
  10. data/lib/rudy/aws/ec2.rb +57 -20
  11. data/lib/rudy/aws/ec2/address.rb +10 -11
  12. data/lib/rudy/aws/ec2/group.rb +10 -9
  13. data/lib/rudy/aws/ec2/image.rb +8 -8
  14. data/lib/rudy/aws/ec2/instance.rb +15 -16
  15. data/lib/rudy/aws/ec2/keypair.rb +14 -19
  16. data/lib/rudy/aws/ec2/snapshot.rb +16 -9
  17. data/lib/rudy/aws/ec2/volume.rb +37 -24
  18. data/lib/rudy/aws/ec2/zone.rb +5 -4
  19. data/lib/rudy/aws/s3.rb +2 -1
  20. data/lib/rudy/aws/sdb.rb +35 -86
  21. data/lib/rudy/backups.rb +24 -0
  22. data/lib/rudy/cli.rb +5 -131
  23. data/lib/rudy/cli/aws/ec2/addresses.rb +19 -27
  24. data/lib/rudy/cli/aws/ec2/candy.rb +32 -7
  25. data/lib/rudy/cli/aws/ec2/groups.rb +9 -13
  26. data/lib/rudy/cli/aws/ec2/images.rb +5 -133
  27. data/lib/rudy/cli/aws/ec2/instances.rb +25 -25
  28. data/lib/rudy/cli/aws/ec2/keypairs.rb +7 -11
  29. data/lib/rudy/cli/aws/ec2/snapshots.rb +5 -9
  30. data/lib/rudy/cli/aws/ec2/volumes.rb +22 -23
  31. data/lib/rudy/cli/aws/ec2/zones.rb +2 -3
  32. data/lib/rudy/cli/aws/sdb/domains.rb +5 -6
  33. data/lib/rudy/cli/aws/sdb/objects.rb +33 -0
  34. data/lib/rudy/cli/aws/sdb/select.rb +23 -0
  35. data/lib/rudy/cli/backups.rb +38 -0
  36. data/lib/rudy/cli/base.rb +98 -0
  37. data/lib/rudy/cli/candy.rb +1 -2
  38. data/lib/rudy/cli/config.rb +7 -4
  39. data/lib/rudy/cli/disks.rb +6 -8
  40. data/lib/rudy/cli/execbase.rb +53 -0
  41. data/lib/rudy/cli/machines.rb +14 -18
  42. data/lib/rudy/cli/metadata.rb +24 -10
  43. data/lib/rudy/cli/routines.rb +31 -5
  44. data/lib/rudy/config.rb +17 -22
  45. data/lib/rudy/config/objects.rb +44 -30
  46. data/lib/rudy/disks.rb +25 -0
  47. data/lib/rudy/exceptions.rb +95 -0
  48. data/lib/rudy/global.rb +46 -23
  49. data/lib/rudy/guidelines.rb +3 -2
  50. data/lib/rudy/huxtable.rb +66 -57
  51. data/lib/rudy/machines.rb +41 -263
  52. data/lib/rudy/metadata.rb +212 -38
  53. data/lib/rudy/metadata/backup.rb +123 -78
  54. data/lib/rudy/metadata/disk.rb +152 -170
  55. data/lib/rudy/metadata/machine.rb +179 -0
  56. data/lib/rudy/mixins.rb +2 -1
  57. data/lib/rudy/mixins/hash.rb +3 -1
  58. data/lib/rudy/mixins/symbol.rb +8 -0
  59. data/lib/rudy/routines.rb +127 -344
  60. data/lib/rudy/routines/base.rb +226 -0
  61. data/lib/rudy/routines/handlers/base.rb +48 -0
  62. data/lib/rudy/routines/handlers/depends.rb +49 -0
  63. data/lib/rudy/routines/handlers/disks.rb +239 -0
  64. data/lib/rudy/routines/handlers/group.rb +42 -0
  65. data/lib/rudy/routines/handlers/host.rb +72 -0
  66. data/lib/rudy/routines/handlers/keypair.rb +70 -0
  67. data/lib/rudy/routines/handlers/machines.rb +15 -0
  68. data/lib/rudy/routines/handlers/script.rb +85 -0
  69. data/lib/rudy/routines/handlers/user.rb +41 -0
  70. data/lib/rudy/routines/passthrough.rb +19 -23
  71. data/lib/rudy/routines/reboot.rb +82 -51
  72. data/lib/rudy/routines/shutdown.rb +61 -14
  73. data/lib/rudy/routines/startup.rb +111 -17
  74. data/lib/rudy/utils.rb +12 -59
  75. data/rudy.gemspec +85 -25
  76. data/tryouts/01_mixins/01_hash_tryouts.rb +20 -0
  77. data/tryouts/10_require_time/10_rudy_tryouts.rb +33 -0
  78. data/tryouts/10_require_time/15_global_tryouts.rb +58 -0
  79. data/tryouts/12_config/10_load_config_tryouts.rb +43 -0
  80. data/tryouts/12_config/20_defaults_tryouts.rb +16 -0
  81. data/tryouts/12_config/30_accounts_tryouts.rb +17 -0
  82. data/tryouts/12_config/40_machines_tryouts.rb +53 -0
  83. data/tryouts/12_config/50_commands_tryouts.rb +17 -0
  84. data/tryouts/12_config/60_routines_tryouts.rb +16 -0
  85. data/tryouts/15_huxtable/10_huxtable_tryouts.rb +47 -0
  86. data/tryouts/15_huxtable/20_user_tryouts.rb +47 -0
  87. data/tryouts/20_simpledb/10_domains_tryouts.rb +36 -0
  88. data/tryouts/20_simpledb/20_objects_tryouts.rb +56 -0
  89. data/tryouts/25_ec2/10_keypairs_tryouts.rb +54 -0
  90. data/tryouts/25_ec2/20_groups_tryouts.rb +56 -0
  91. data/tryouts/25_ec2/21_groups_authorize_address_tryouts.rb +53 -0
  92. data/tryouts/25_ec2/22_groups_authorize_account_tryouts.rb +54 -0
  93. data/tryouts/25_ec2/30_addresses_tryouts.rb +42 -0
  94. data/tryouts/25_ec2/40_volumes_tryouts.rb +53 -0
  95. data/tryouts/25_ec2/50_snapshots_tryouts.rb +75 -0
  96. data/tryouts/26_ec2_instances/10_instance_tryouts.rb +107 -0
  97. data/tryouts/26_ec2_instances/50_images_tryouts.rb +7 -0
  98. data/tryouts/30_metadata/10_include_tryouts.rb +45 -0
  99. data/tryouts/30_metadata/13_object_tryouts.rb +19 -0
  100. data/tryouts/30_metadata/50_disk_tryouts.rb +115 -0
  101. data/tryouts/30_metadata/51_disk_digest_tryouts.rb +24 -0
  102. data/tryouts/30_metadata/53_disk_list_tryouts.rb +35 -0
  103. data/tryouts/30_metadata/56_disk_volume_tryouts.rb +68 -0
  104. data/tryouts/30_metadata/60_backup_tryouts.rb +101 -0
  105. data/tryouts/30_metadata/63_backup_list_tryouts.rb +38 -0
  106. data/tryouts/30_metadata/64_backup_disk_tryouts.rb +65 -0
  107. data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +76 -0
  108. data/tryouts/30_metadata/70_machine_tryouts.rb +85 -0
  109. data/tryouts/30_metadata/73_machine_list_tryouts.rb +58 -0
  110. data/tryouts/30_metadata/76_machine_instance_tryouts.rb +64 -0
  111. data/tryouts/30_metadata/77_machines_tryouts.rb +45 -0
  112. data/tryouts/40_routines/10_keypair_handler_tryouts.rb +52 -0
  113. data/tryouts/40_routines/11_group_handler_tryouts.rb +36 -0
  114. data/tryouts/80_cli/10_rudyec2_tryouts.rb +8 -0
  115. data/tryouts/80_cli/60_rudy_tryouts.rb +41 -0
  116. data/tryouts/failer +6 -0
  117. data/tryouts/misc/console_tryout.rb +91 -0
  118. data/tryouts/misc/disks_tryout.rb +48 -0
  119. data/tryouts/misc/drydock_tryout.rb +48 -0
  120. data/tryouts/misc/nested_methods.rb +103 -0
  121. data/tryouts/misc/session_tryout.rb +46 -0
  122. data/tryouts/misc/tryouts.rb +33 -0
  123. data/tryouts/misc/usage_tryout.rb +23 -0
  124. metadata +119 -31
  125. data/bin/ird +0 -153
  126. data/lib/rudy/metadata/backups.rb +0 -67
  127. data/lib/rudy/metadata/debug.rb +0 -38
  128. data/lib/rudy/metadata/disks.rb +0 -67
  129. data/lib/rudy/metadata/objectbase.rb +0 -108
  130. data/lib/rudy/routines/helper.rb +0 -76
  131. data/lib/rudy/routines/helpers/dependshelper.rb +0 -34
  132. data/lib/rudy/routines/helpers/diskhelper.rb +0 -403
  133. data/lib/rudy/routines/helpers/scripthelper.rb +0 -197
  134. data/lib/rudy/routines/helpers/userhelper.rb +0 -37
  135. data/support/rudy-ec2-startup +0 -200
@@ -0,0 +1,226 @@
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
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
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 (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
+ else
208
+ exit 12
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ def print_exception(user, host, cmd, nickname, ex)
215
+ prefix = @@global.parallel ? "#{nickname}: #{cmd}: " : ""
216
+ if ex.is_a?(Rye::CommandError)
217
+ le prefix << ex.message.color(:red)
218
+ else
219
+ le prefix << "#{ex.class}: #{ex.message}".color(:red)
220
+ end
221
+ le *ex.backtrace
222
+ end
223
+
224
+ end
225
+
226
+ 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,239 @@
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 disks?(routine)
17
+ (routine.kind_of?(Hash) && routine.disks &&
18
+ routine.disks.kind_of?(Hash) && !routine.disks.empty?) ? true : false
19
+ end
20
+
21
+ def paths(routine)
22
+ return nil unless disks?(routine)
23
+ routine.disks.values.collect { |d| d.keys }.flatten
24
+ end
25
+
26
+
27
+ def execute(type, routine, rset, lbox, argv=nil)
28
+ original_user = rset.user
29
+ rset.add_key user_keypairpath('root')
30
+ rset.switch_user 'root'
31
+
32
+ # We need to add mkfs since it's not enabled by default.
33
+ # We prepend the command with rudy_ so we can delete it.
34
+ Rye::Cmd.add_command(:rudy_mkfs, 'mkfs')
35
+
36
+ routine.each_pair do |action, disks|
37
+ unless respond_to?(action.to_sym)
38
+ Rudy::Huxtable.le %Q(DiskHelper: unknown action "#{action}")
39
+ next
40
+ end
41
+ # A quick hack to take advantage of the threading in Rye::Set.
42
+ # The action method does not run in the context of a Rye::Box
43
+ # object so we need to send rset as an argument.
44
+ rset.batch do
45
+ disks.each_pair do |path, props|
46
+ # self contains the current instance of Rye::Box.
47
+ disk = Rudy::Disk.new(self.stash.position, path, props)
48
+ Rudy::Routines::Handlers::Disks.send(action, self, disk)
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ Rye::Cmd.remove_command(:rudy_mkfs)
55
+
56
+ rset.switch_user original_user
57
+ end
58
+
59
+
60
+ def create(rbox, disk)
61
+ if disk.exists?
62
+ puts "Disk found: #{disk.name}"
63
+ disk.refresh!
64
+ end
65
+
66
+ unless @@global.force
67
+ raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
68
+ end
69
+
70
+ unless disk.volume_exists?
71
+ msg = "Creating volume... "
72
+ disk.create
73
+ Rudy::Utils.waiter(2, 60, STDOUT, msg) {
74
+ disk.volume_available?
75
+ }
76
+ end
77
+
78
+ attach rbox, disk unless disk.volume_attached?
79
+ format rbox, disk if disk.raw?
80
+ mount rbox, disk unless disk.mounted?
81
+
82
+ disk.save :replace
83
+ end
84
+
85
+
86
+
87
+ def detach(rbox, disk)
88
+
89
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
90
+ disk.refresh!
91
+
92
+ raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
93
+
94
+ umount rbox, disk if disk.mounted?
95
+ raise Rudy::Disks::InUse, disk.name if disk.mounted?
96
+
97
+ msg = "Detaching #{disk.volid}..."
98
+ disk.volume_detach
99
+ Rudy::Utils.waiter(2, 60, STDOUT, msg) {
100
+ disk.volume_available?
101
+ }
102
+
103
+ end
104
+
105
+ def attach(rbox, disk)
106
+
107
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
108
+ disk.refresh!
109
+
110
+ raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
111
+
112
+ msg = "Attaching #{disk.volid} to #{rbox.stash.instid}... "
113
+ disk.volume_attach(rbox.stash.instid)
114
+ Rudy::Utils.waiter(2, 10, STDOUT, msg) {
115
+ disk.volume_attached?
116
+ }
117
+
118
+ end
119
+
120
+ def mount(rbox, disk)
121
+
122
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
123
+ disk.refresh!
124
+ attach rbox, disk unless disk.volume_attached?
125
+
126
+ unless @@global.force
127
+ raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
128
+ raise Rudy::Disks::NotFormatted, disk.name if disk.raw?
129
+ raise Rudy::Disks::AlreadyMounted, disk.name if disk.mounted?
130
+ end
131
+
132
+ rbox.mkdir(:p, disk.path)
133
+
134
+ puts "Mounting at #{disk.path}... "
135
+
136
+ rbox.mount(:t, disk.fstype, disk.device, disk.path)
137
+ disk.mounted = true
138
+ disk.save :replace
139
+ sleep 1
140
+ end
141
+
142
+
143
+ def umount(rbox, disk)
144
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
145
+ disk.refresh!
146
+
147
+ raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
148
+ raise Rudy::Disks::NotMounted, disk.name if !disk.mounted?
149
+
150
+ puts "Unmounting #{disk.path}... "
151
+ rbox.umount(disk.path)
152
+ disk.mounted = false
153
+ disk.save :replace
154
+ sleep 2
155
+ end
156
+ alias_method :unmount, :umount
157
+
158
+ def format(rbox, disk)
159
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
160
+ disk.refresh!
161
+
162
+ attach rbox, disk unless disk.volume_attached?
163
+
164
+ raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
165
+
166
+ unless @@global.force
167
+ raise Rudy::Disks::AlreadyFormatted, disk.name if !disk.raw?
168
+ end
169
+
170
+ disk.fstype = 'ext3' if disk.fstype.nil? || disk.fstype.empty?
171
+
172
+ puts "Creating #{disk.fstype} filesystem for #{disk.device}... "
173
+ rbox.rudy_mkfs(:t, disk.fstype, :F, disk.device)
174
+ disk.raw = false
175
+ disk.save :replace
176
+ end
177
+
178
+ def destroy(rbox, disk)
179
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
180
+ disk.refresh!
181
+
182
+ umount rbox, disk if disk.mounted?
183
+ detach rbox, disk if disk.volume_attached?
184
+
185
+ unless @@global.force
186
+ raise Rudy::Disks::InUse, disk.name if disk.volume_attached?
187
+ end
188
+
189
+ puts "Destroying #{disk.name}"
190
+ disk.destroy
191
+ end
192
+
193
+ def archive(rbox, disk)
194
+ raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
195
+ disk.refresh!
196
+
197
+ raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
198
+
199
+ back = disk.archive
200
+ puts "Created backup: #{back.name}"
201
+ end
202
+
203
+ def restore(rbox, disk)
204
+
205
+ if disk.exists?
206
+ puts "Disk found: #{disk.name}"
207
+ disk.refresh!
208
+ end
209
+
210
+ unless @@global.force
211
+ raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
212
+ end
213
+
214
+ latest_backup = disk.backups.last
215
+ disk.size, disk.fstype = latest_backup.size, latest_backup.fstype
216
+
217
+ puts "Backup found: #{latest_backup.name}"
218
+
219
+ unless disk.volume_exists?
220
+ msg = "Creating volume... "
221
+ disk.create latest_backup.size, latest_backup.zone, latest_backup.snapid
222
+ Rudy::Utils.waiter(2, 60, STDOUT, msg) {
223
+ disk.volume_available?
224
+ }
225
+
226
+ end
227
+ disk.raw = false
228
+
229
+ attach rbox, disk unless disk.volume_attached?
230
+ #format rbox, disk if disk.raw?
231
+ mount rbox, disk unless disk.mounted?
232
+
233
+ disk.save :replace
234
+
235
+ end
236
+
237
+
238
+ end
239
+ end