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 (132) hide show
  1. data/CHANGES.txt +110 -18
  2. data/README.rdoc +40 -44
  3. data/Rudyfile +35 -50
  4. data/bin/rudy +88 -57
  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 +59 -91
  9. data/lib/rudy/aws.rb +4 -45
  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 +18 -19
  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 +39 -26
  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 +45 -20
  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 +104 -0
  37. data/lib/rudy/cli/candy.rb +1 -2
  38. data/lib/rudy/cli/config.rb +20 -7
  39. data/lib/rudy/cli/disks.rb +7 -9
  40. data/lib/rudy/cli/execbase.rb +56 -0
  41. data/lib/rudy/cli/machines.rb +242 -45
  42. data/lib/rudy/cli/metadata.rb +24 -10
  43. data/lib/rudy/cli/networks.rb +34 -0
  44. data/lib/rudy/cli/routines.rb +32 -6
  45. data/lib/rudy/cli/status.rb +60 -0
  46. data/lib/rudy/config.rb +55 -32
  47. data/lib/rudy/config/objects.rb +44 -30
  48. data/lib/rudy/disks.rb +25 -0
  49. data/lib/rudy/exceptions.rb +99 -0
  50. data/lib/rudy/global.rb +67 -28
  51. data/lib/rudy/guidelines.rb +3 -2
  52. data/lib/rudy/huxtable.rb +67 -58
  53. data/lib/rudy/machines.rb +41 -263
  54. data/lib/rudy/metadata.rb +212 -38
  55. data/lib/rudy/metadata/backup.rb +123 -78
  56. data/lib/rudy/metadata/disk.rb +153 -170
  57. data/lib/rudy/metadata/machine.rb +179 -0
  58. data/lib/rudy/mixins.rb +2 -1
  59. data/lib/rudy/mixins/hash.rb +3 -1
  60. data/lib/rudy/mixins/symbol.rb +8 -0
  61. data/lib/rudy/routines.rb +127 -344
  62. data/lib/rudy/routines/base.rb +229 -0
  63. data/lib/rudy/routines/handlers/base.rb +48 -0
  64. data/lib/rudy/routines/handlers/depends.rb +49 -0
  65. data/lib/rudy/routines/handlers/disks.rb +249 -0
  66. data/lib/rudy/routines/handlers/group.rb +44 -0
  67. data/lib/rudy/routines/handlers/host.rb +70 -0
  68. data/lib/rudy/routines/handlers/keypair.rb +70 -0
  69. data/lib/rudy/routines/handlers/machines.rb +15 -0
  70. data/lib/rudy/routines/handlers/script.rb +85 -0
  71. data/lib/rudy/routines/handlers/user.rb +45 -0
  72. data/lib/rudy/routines/passthrough.rb +19 -23
  73. data/lib/rudy/routines/reboot.rb +98 -50
  74. data/lib/rudy/routines/shutdown.rb +65 -14
  75. data/lib/rudy/routines/startup.rb +112 -17
  76. data/lib/rudy/utils.rb +35 -68
  77. data/rudy.gemspec +82 -25
  78. data/tryouts/01_mixins/01_hash_tryouts.rb +20 -0
  79. data/tryouts/10_require_time/10_rudy_tryouts.rb +33 -0
  80. data/tryouts/10_require_time/15_global_tryouts.rb +58 -0
  81. data/tryouts/12_config/10_load_config_tryouts.rb +43 -0
  82. data/tryouts/12_config/20_defaults_tryouts.rb +16 -0
  83. data/tryouts/12_config/30_accounts_tryouts.rb +17 -0
  84. data/tryouts/12_config/40_machines_tryouts.rb +53 -0
  85. data/tryouts/12_config/50_commands_tryouts.rb +17 -0
  86. data/tryouts/12_config/60_routines_tryouts.rb +16 -0
  87. data/tryouts/15_huxtable/10_huxtable_tryouts.rb +47 -0
  88. data/tryouts/15_huxtable/20_user_tryouts.rb +47 -0
  89. data/tryouts/20_simpledb/10_domains_tryouts.rb +36 -0
  90. data/tryouts/20_simpledb/20_objects_tryouts.rb +56 -0
  91. data/tryouts/25_ec2/10_keypairs_tryouts.rb +54 -0
  92. data/tryouts/25_ec2/20_groups_tryouts.rb +56 -0
  93. data/tryouts/25_ec2/21_groups_authorize_address_tryouts.rb +53 -0
  94. data/tryouts/25_ec2/22_groups_authorize_account_tryouts.rb +54 -0
  95. data/tryouts/25_ec2/30_addresses_tryouts.rb +42 -0
  96. data/tryouts/25_ec2/40_volumes_tryouts.rb +53 -0
  97. data/tryouts/25_ec2/50_snapshots_tryouts.rb +75 -0
  98. data/tryouts/26_ec2_instances/10_instance_tryouts.rb +107 -0
  99. data/tryouts/26_ec2_instances/50_images_tryouts.rb +7 -0
  100. data/tryouts/30_metadata/10_include_tryouts.rb +45 -0
  101. data/tryouts/30_metadata/13_object_tryouts.rb +19 -0
  102. data/tryouts/30_metadata/50_disk_tryouts.rb +115 -0
  103. data/tryouts/30_metadata/51_disk_digest_tryouts.rb +24 -0
  104. data/tryouts/30_metadata/53_disk_list_tryouts.rb +35 -0
  105. data/tryouts/30_metadata/56_disk_volume_tryouts.rb +68 -0
  106. data/tryouts/30_metadata/60_backup_tryouts.rb +101 -0
  107. data/tryouts/30_metadata/63_backup_list_tryouts.rb +38 -0
  108. data/tryouts/30_metadata/64_backup_disk_tryouts.rb +65 -0
  109. data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +76 -0
  110. data/tryouts/30_metadata/70_machine_tryouts.rb +85 -0
  111. data/tryouts/30_metadata/73_machine_list_tryouts.rb +58 -0
  112. data/tryouts/30_metadata/76_machine_instance_tryouts.rb +64 -0
  113. data/tryouts/30_metadata/77_machines_tryouts.rb +45 -0
  114. data/tryouts/40_routines/10_keypair_handler_tryouts.rb +52 -0
  115. data/tryouts/40_routines/11_group_handler_tryouts.rb +36 -0
  116. data/tryouts/80_cli/10_rudyec2_tryouts.rb +8 -0
  117. data/tryouts/80_cli/60_rudy_tryouts.rb +41 -0
  118. data/tryouts/exploration/console.rb +91 -0
  119. data/tryouts/exploration/machine.rb +23 -0
  120. data/tryouts/failer +6 -0
  121. metadata +116 -32
  122. data/bin/ird +0 -153
  123. data/lib/rudy/metadata/backups.rb +0 -67
  124. data/lib/rudy/metadata/debug.rb +0 -38
  125. data/lib/rudy/metadata/disks.rb +0 -67
  126. data/lib/rudy/metadata/objectbase.rb +0 -108
  127. data/lib/rudy/routines/helper.rb +0 -76
  128. data/lib/rudy/routines/helpers/dependshelper.rb +0 -34
  129. data/lib/rudy/routines/helpers/diskhelper.rb +0 -403
  130. data/lib/rudy/routines/helpers/scripthelper.rb +0 -197
  131. data/lib/rudy/routines/helpers/userhelper.rb +0 -37
  132. 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