solutious-rudy 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +40 -16
- data/README.rdoc +6 -6
- data/bin/rudy +66 -10
- data/bin/rudy-ec2 +3 -1
- data/examples/authorize.rb +15 -0
- data/examples/gem-test.rb +11 -5
- data/examples/solaris.rb +35 -0
- data/examples/windows.rb +101 -0
- data/lib/rudy.rb +7 -1
- data/lib/rudy/aws.rb +2 -2
- data/lib/rudy/aws/ec2.rb +29 -22
- data/lib/rudy/aws/ec2/group.rb +1 -1
- data/lib/rudy/aws/ec2/image.rb +1 -29
- data/lib/rudy/aws/ec2/instance.rb +4 -32
- data/lib/rudy/aws/ec2/keypair.rb +1 -6
- data/lib/rudy/aws/ec2/snapshot.rb +2 -20
- data/lib/rudy/aws/ec2/volume.rb +11 -19
- data/lib/rudy/aws/ec2/zone.rb +1 -6
- data/lib/rudy/aws/sdb.rb +1 -1
- data/lib/rudy/cli/aws/ec2/addresses.rb +4 -10
- data/lib/rudy/cli/aws/ec2/groups.rb +0 -1
- data/lib/rudy/cli/aws/ec2/images.rb +1 -4
- data/lib/rudy/cli/aws/ec2/info.rb +63 -0
- data/lib/rudy/cli/aws/ec2/instances.rb +3 -5
- data/lib/rudy/cli/aws/ec2/keypairs.rb +3 -5
- data/lib/rudy/cli/aws/ec2/snapshots.rb +2 -6
- data/lib/rudy/cli/aws/ec2/zones.rb +2 -4
- data/lib/rudy/cli/backups.rb +20 -9
- data/lib/rudy/cli/base.rb +60 -3
- data/lib/rudy/cli/candy.rb +1 -1
- data/lib/rudy/cli/disks.rb +65 -7
- data/lib/rudy/cli/execbase.rb +0 -2
- data/lib/rudy/cli/images.rb +97 -0
- data/lib/rudy/cli/info.rb +48 -0
- data/lib/rudy/cli/keypairs.rb +43 -0
- data/lib/rudy/cli/machines.rb +48 -38
- data/lib/rudy/cli/networks.rb +68 -0
- data/lib/rudy/cli/routines.rb +3 -10
- data/lib/rudy/config/objects.rb +0 -1
- data/lib/rudy/disks.rb +4 -0
- data/lib/rudy/global.rb +1 -1
- data/lib/rudy/huxtable.rb +9 -3
- data/lib/rudy/machines.rb +1 -1
- data/lib/rudy/metadata.rb +4 -1
- data/lib/rudy/metadata/backup.rb +2 -2
- data/lib/rudy/metadata/disk.rb +7 -4
- data/lib/rudy/metadata/machine.rb +66 -2
- data/lib/rudy/routines.rb +2 -1
- data/lib/rudy/routines/base.rb +4 -157
- data/lib/rudy/routines/handlers/base.rb +6 -3
- data/lib/rudy/routines/handlers/disks.rb +127 -42
- data/lib/rudy/routines/handlers/group.rb +45 -10
- data/lib/rudy/routines/handlers/host.rb +16 -10
- data/lib/rudy/routines/handlers/keypair.rb +26 -10
- data/lib/rudy/routines/handlers/rye.rb +173 -0
- data/lib/rudy/routines/handlers/script.rb +2 -1
- data/lib/rudy/routines/passthrough.rb +2 -2
- data/lib/rudy/routines/reboot.rb +2 -2
- data/lib/rudy/routines/shutdown.rb +2 -2
- data/lib/rudy/routines/startup.rb +4 -2
- data/rudy.gemspec +15 -8
- data/tryouts/10_require_time/10_rudy_tryouts.rb +1 -1
- data/tryouts/12_config/20_defaults_tryouts.rb +1 -1
- data/tryouts/12_config/40_machines_tryouts.rb +1 -1
- data/tryouts/15_huxtable/20_user_tryouts.rb +1 -1
- data/tryouts/25_ec2/10_keypairs_tryouts.rb +1 -0
- data/tryouts/30_metadata/10_include_tryouts.rb +1 -1
- data/tryouts/30_metadata/13_object_tryouts.rb +4 -0
- data/tryouts/30_metadata/50_disk_tryouts.rb +4 -2
- data/tryouts/30_metadata/51_disk_digest_tryouts.rb +1 -1
- data/tryouts/30_metadata/53_disk_list_tryouts.rb +2 -1
- data/tryouts/30_metadata/56_disk_volume_tryouts.rb +1 -1
- data/tryouts/30_metadata/60_backup_tryouts.rb +4 -2
- data/tryouts/30_metadata/63_backup_list_tryouts.rb +1 -1
- data/tryouts/30_metadata/64_backup_disk_tryouts.rb +3 -1
- data/tryouts/30_metadata/66_backup_snapshot_tryouts.rb +1 -1
- data/tryouts/30_metadata/70_machine_tryouts.rb +5 -2
- data/tryouts/30_metadata/73_machine_list_tryouts.rb +1 -1
- data/tryouts/30_metadata/76_machine_instance_tryouts.rb +15 -3
- data/tryouts/30_metadata/77_machines_tryouts.rb +1 -1
- data/tryouts/40_routines/10_keypair_handler_tryouts.rb +6 -5
- data/tryouts/40_routines/11_group_handler_tryouts.rb +1 -1
- metadata +13 -6
- data/lib/rudy/cli/status.rb +0 -60
@@ -77,16 +77,55 @@ module Rudy
|
|
77
77
|
|
78
78
|
def postprocess
|
79
79
|
@position &&= @position.to_s.rjust(2, '0')
|
80
|
+
@os &&= @os.to_sym
|
80
81
|
end
|
81
82
|
|
82
83
|
def to_s(*args)
|
83
|
-
self.name
|
84
|
+
[self.name.bright, self.instid, self.dns_public].join '; '
|
84
85
|
end
|
85
86
|
|
87
|
+
def rbox
|
88
|
+
r = Rudy::Routines::Handlers::RyeTools.create_box self
|
89
|
+
end
|
90
|
+
|
91
|
+
def disks
|
92
|
+
Rudy::Disks.list
|
93
|
+
end
|
94
|
+
|
95
|
+
|
86
96
|
def get_instance
|
87
97
|
Rudy::AWS::EC2::Instances.get @instid
|
88
98
|
end
|
89
99
|
|
100
|
+
def get_console
|
101
|
+
raise "Instance not running" unless instance_running?
|
102
|
+
raw = Rudy::AWS::EC2::Instances.console @instid
|
103
|
+
console = Base64.decode64(raw)
|
104
|
+
# The linux console can include ANSI escape codes for color,
|
105
|
+
# clear screen etc... We strip them out to get rid of the
|
106
|
+
# clear specifically. Otherwise the display is messed!
|
107
|
+
console &&= console.noansi if console.respond_to? :noansi
|
108
|
+
console
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_password
|
112
|
+
unless windows?
|
113
|
+
raise "Password support is Windows only (this is #{@os})"
|
114
|
+
end
|
115
|
+
console = get_console
|
116
|
+
|
117
|
+
raise "Console output not yet available. Please wait." if console.nil?
|
118
|
+
|
119
|
+
unless console.match(/<Password>(.+)<\/Password>/m)
|
120
|
+
# /m, match multiple lines
|
121
|
+
raise "Password not yet available. Is this a custom AMI?"
|
122
|
+
end
|
123
|
+
|
124
|
+
encrtypted_text = ($1 || '').strip
|
125
|
+
k = Rye::Key.from_file root_keypairpath
|
126
|
+
k.decrypt encrtypted_text
|
127
|
+
end
|
128
|
+
|
90
129
|
def create
|
91
130
|
raise "#{name} is already running" if instance_running?
|
92
131
|
|
@@ -103,6 +142,10 @@ module Rudy
|
|
103
142
|
|
104
143
|
Rudy::Huxtable.ld "OPTS: #{opts.inspect}"
|
105
144
|
|
145
|
+
#@dns_public = @dns_private = nil
|
146
|
+
#inst = Rudy::AWS::EC2::Instances.list(:running).first
|
147
|
+
#@instid = inst.awsid
|
148
|
+
|
106
149
|
Rudy::AWS::EC2::Instances.create(opts) do |inst|
|
107
150
|
@instid = inst.awsid
|
108
151
|
@created = @started = Time.now
|
@@ -125,6 +168,7 @@ module Rudy
|
|
125
168
|
STDERR.puts ex.backtrace if Rudy.debug?
|
126
169
|
end
|
127
170
|
end
|
171
|
+
|
128
172
|
self.save
|
129
173
|
self
|
130
174
|
end
|
@@ -138,9 +182,15 @@ module Rudy
|
|
138
182
|
Rudy::AWS::EC2::Instances.restart(@instid) if instance_running?
|
139
183
|
end
|
140
184
|
|
185
|
+
def attached_volumes
|
186
|
+
volumes = []
|
187
|
+
return volumes if @instid.nil?
|
188
|
+
Rudy::AWS::EC2::Volumes.list_by_instance( @instid) || []
|
189
|
+
end
|
190
|
+
|
141
191
|
def refresh!(metadata=true)
|
142
192
|
## Updating the metadata isn't necessary
|
143
|
-
|
193
|
+
super() if metadata # update metadata
|
144
194
|
@instance = get_instance
|
145
195
|
if @instance.is_a?(Rudy::AWS::EC2::Instance)
|
146
196
|
@dns_public, @dns_private = @instance.dns_public, @instance.dns_private
|
@@ -161,6 +211,20 @@ module Rudy
|
|
161
211
|
d
|
162
212
|
end
|
163
213
|
|
214
|
+
def default_fstype
|
215
|
+
windows? ? Rudy::DEFAULT_WINDOWS_FS : Rudy::DEFAULT_LINUX_FS
|
216
|
+
end
|
217
|
+
|
218
|
+
def default_device
|
219
|
+
windows? ? Rudy::DEFAULT_WINDOWS_DEVICE : Rudy::DEFAULT_LINUX_DEVICE
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
def os?(v); @os.to_s == v.to_s; end
|
224
|
+
def windows?; os? 'windows'; end
|
225
|
+
def linux?; os? 'linux'; end
|
226
|
+
def solaris?; os? 'solaris'; end
|
227
|
+
|
164
228
|
def dns_public?; !@dns_public.nil? && !@dns_public.empty?; end
|
165
229
|
def dns_private?; !@dns_private.nil? && !@dns_private.empty?; end
|
166
230
|
|
data/lib/rudy/routines.rb
CHANGED
@@ -95,9 +95,10 @@ module Rudy
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def self.rescue(ret=nil, &bloc_party)
|
98
|
+
|
98
99
|
begin
|
99
100
|
ret = bloc_party.call
|
100
|
-
rescue NameError, ArgumentError, RuntimeError => ex
|
101
|
+
rescue NameError, ArgumentError, RuntimeError, Errno::ECONNREFUSED => ex
|
101
102
|
STDERR.puts " #{ex.class}: #{ex.message}".color(:red)
|
102
103
|
STDERR.puts ex.backtrace if Rudy.debug?
|
103
104
|
unless Rudy::Huxtable.global.parallel
|
data/lib/rudy/routines/base.rb
CHANGED
@@ -49,7 +49,10 @@ module Rudy; module Routines;
|
|
49
49
|
end
|
50
50
|
|
51
51
|
# Share one Rye::Box instance for localhost across all routines
|
52
|
-
|
52
|
+
unless defined?(@@lbox)
|
53
|
+
host, opts = @@global.localhost, { :user => Rudy.sysinfo.user }
|
54
|
+
@@lbox = Rudy::Routines::Handlers::RyeTools.create_box host, opts
|
55
|
+
end
|
53
56
|
|
54
57
|
disable_run if @@global.testrun
|
55
58
|
|
@@ -68,162 +71,6 @@ module Rudy; module Routines;
|
|
68
71
|
def raise_early_exceptions; raise "Please override"; end
|
69
72
|
def execute; raise "Please override"; end
|
70
73
|
|
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
74
|
end
|
228
75
|
|
229
76
|
end; end;
|
@@ -12,11 +12,14 @@ module Rudy; module Routines; module Handlers;
|
|
12
12
|
print_response(ret)
|
13
13
|
rescue IOError => ex
|
14
14
|
STDERR.puts " Connection Error (#{ex.message})".color(:red)
|
15
|
-
choice = Annoy.get_user_input('(S)kip (A)bort: ', nil, 3600) || ''
|
15
|
+
choice = Annoy.get_user_input('(S)kip (R)etry (F)orce (A)bort: ', nil, 3600) || ''
|
16
16
|
if choice.match(/\AS/i)
|
17
17
|
return
|
18
|
-
|
19
|
-
|
18
|
+
elsif choice.match(/\AR/i)
|
19
|
+
retry
|
20
|
+
elsif choice.match(/\AF/i)
|
21
|
+
@@global.force = true
|
22
|
+
retry
|
20
23
|
else
|
21
24
|
exit 12
|
22
25
|
end
|
@@ -5,10 +5,16 @@ module Rudy::Routines::Handlers;
|
|
5
5
|
extend self
|
6
6
|
|
7
7
|
ACTIONS = [:create, :destroy, :archive, :mount, :restore,
|
8
|
-
:attach, :detach, :mount, :umount].freeze
|
8
|
+
:attach, :detach, :mount, :umount, :fstype].freeze
|
9
9
|
|
10
10
|
Rudy::Routines.add_handler :disks, self
|
11
11
|
|
12
|
+
Rye::Cmd.add_command(:rudy_rm, 'rm')
|
13
|
+
Rye::Cmd.add_command(:rudy_mkfs, 'mkfs')
|
14
|
+
Rye::Cmd.add_command(:rudy_blkid, 'blkid')
|
15
|
+
Rye::Cmd.add_command(:rudy_format, 'C:/windows/system32/format.com')
|
16
|
+
Rye::Cmd.add_command(:rudy_diskpart, 'diskpart')
|
17
|
+
|
12
18
|
def raise_early_exceptions(type, batch, rset, lbox, argv=nil)
|
13
19
|
|
14
20
|
end
|
@@ -34,43 +40,54 @@ module Rudy::Routines::Handlers;
|
|
34
40
|
|
35
41
|
def execute(type, routine, rset, lbox, argv=nil)
|
36
42
|
original_user = rset.user
|
37
|
-
rset.add_key user_keypairpath(
|
38
|
-
rset.switch_user
|
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
|
+
rset.add_key user_keypairpath(current_machine_user)
|
44
|
+
rset.switch_user current_machine_user
|
43
45
|
|
44
46
|
routine.each_pair do |action, disks|
|
45
47
|
unless respond_to?(action.to_sym)
|
46
|
-
Rudy::Huxtable.le %Q(
|
48
|
+
Rudy::Huxtable.le %Q(DiskHandler: unknown action "#{action}")
|
47
49
|
next
|
48
50
|
end
|
49
51
|
# A quick hack to take advantage of the threading in Rye::Set.
|
50
52
|
# The action method does not run in the context of a Rye::Box
|
51
53
|
# object so we need to send rset as an argument.
|
52
54
|
rset.batch do
|
55
|
+
# Windows EC2 instances have 2 disks by default (C: and D:)
|
56
|
+
volumes = self.stash.attached_volumes
|
53
57
|
disks.each_pair do |path, props|
|
54
58
|
# self contains the current instance of Rye::Box.
|
55
59
|
disk = Rudy::Disk.new(self.stash.position, path, props)
|
56
|
-
|
60
|
+
disk.refresh! if disk.exists? # We need the volume ID if available
|
61
|
+
# don't include the current disk in the count.
|
62
|
+
volumes.reject! { |v| v.awsid == disk.volid } if disk.volid && disk.volume_attached?
|
63
|
+
disk_index = volumes.size + 2
|
64
|
+
Rudy::Routines::Handlers::Disks.send(action, self, disk, disk_index)
|
57
65
|
end
|
58
66
|
end
|
59
67
|
|
60
68
|
end
|
61
69
|
|
62
|
-
Rye::Cmd.remove_command(:rudy_mkfs)
|
63
|
-
|
64
70
|
rset.switch_user original_user
|
65
71
|
end
|
66
72
|
|
73
|
+
def fstype(rbox, disk, index)
|
74
|
+
|
75
|
+
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
76
|
+
disk.refresh!
|
77
|
+
|
78
|
+
#p rbox.rudy_blkid :s, 'TYPE', :o, 'value', disk.device
|
79
|
+
|
80
|
+
end
|
81
|
+
|
67
82
|
|
68
|
-
def create(rbox, disk)
|
83
|
+
def create(rbox, disk, index)
|
69
84
|
if disk.exists?
|
70
85
|
puts "Disk found: #{disk.name}"
|
71
86
|
disk.refresh!
|
72
87
|
end
|
73
88
|
|
89
|
+
disk.index = index # Needed for windows
|
90
|
+
|
74
91
|
unless @@global.force
|
75
92
|
raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
|
76
93
|
end
|
@@ -83,25 +100,27 @@ module Rudy::Routines::Handlers;
|
|
83
100
|
}
|
84
101
|
end
|
85
102
|
|
86
|
-
attach rbox, disk unless disk.volume_attached?
|
87
|
-
format rbox, disk if disk.raw?
|
88
|
-
mount rbox, disk unless disk.mounted?
|
103
|
+
attach rbox, disk, index unless disk.volume_attached?
|
104
|
+
format rbox, disk, index if disk.raw?
|
105
|
+
mount rbox, disk, index unless disk.mounted?
|
89
106
|
|
90
107
|
disk.save :replace
|
91
108
|
end
|
92
109
|
|
93
110
|
|
94
111
|
|
95
|
-
def detach(rbox, disk)
|
112
|
+
def detach(rbox, disk, index)
|
96
113
|
|
97
114
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
98
115
|
disk.refresh!
|
99
116
|
|
100
|
-
|
117
|
+
unless @@global.force
|
118
|
+
raise Rudy::Disks::NotAttached, disk.name unless disk.volume_attached?
|
119
|
+
end
|
101
120
|
|
102
|
-
umount rbox, disk if disk.mounted?
|
121
|
+
umount rbox, disk, index if disk.mounted?
|
103
122
|
raise Rudy::Disks::InUse, disk.name if disk.mounted?
|
104
|
-
|
123
|
+
|
105
124
|
msg = "Detaching #{disk.volid}..."
|
106
125
|
disk.volume_detach
|
107
126
|
Rudy::Utils.waiter(2, 60, STDOUT, msg) {
|
@@ -110,25 +129,48 @@ module Rudy::Routines::Handlers;
|
|
110
129
|
|
111
130
|
end
|
112
131
|
|
113
|
-
def attach(rbox, disk)
|
132
|
+
def attach(rbox, disk, index)
|
133
|
+
|
134
|
+
unless disk.volume_exists?
|
135
|
+
msg = "Creating volume... "
|
136
|
+
disk.create
|
137
|
+
Rudy::Utils.waiter(2, 60, STDOUT, msg) {
|
138
|
+
disk.volume_available?
|
139
|
+
}
|
140
|
+
end
|
114
141
|
|
115
142
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
116
143
|
disk.refresh!
|
117
144
|
|
118
|
-
|
145
|
+
unless @@global.force
|
146
|
+
raise Rudy::Disks::AlreadyAttached, disk.name if disk.volume_attached?
|
147
|
+
end
|
148
|
+
|
149
|
+
devices = rbox.stash.attached_volumes.collect { |v| v.device }
|
150
|
+
if devices.member? disk.device
|
151
|
+
li "Device ID #{disk.device} is taken. Using #{devices.sort.last.succ}"
|
152
|
+
disk.device = devices.sort.last.succ
|
153
|
+
disk.save :replace
|
154
|
+
end
|
119
155
|
|
120
156
|
msg = "Attaching #{disk.volid} to #{rbox.stash.instid}... "
|
121
157
|
disk.volume_attach(rbox.stash.instid)
|
122
|
-
Rudy::Utils.waiter(
|
158
|
+
Rudy::Utils.waiter(3, 30, STDOUT, msg) {
|
123
159
|
disk.volume_attached?
|
124
160
|
}
|
125
161
|
|
126
162
|
end
|
127
163
|
|
128
|
-
def mount(rbox, disk)
|
164
|
+
def mount(rbox, disk, index)
|
129
165
|
|
130
166
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
131
167
|
disk.refresh!
|
168
|
+
|
169
|
+
if rbox.stash.windows?
|
170
|
+
Rudy::Huxtable.li "Skipping for Windows"
|
171
|
+
return
|
172
|
+
end
|
173
|
+
|
132
174
|
attach rbox, disk unless disk.volume_attached?
|
133
175
|
|
134
176
|
unless @@global.force
|
@@ -137,35 +179,42 @@ module Rudy::Routines::Handlers;
|
|
137
179
|
raise Rudy::Disks::AlreadyMounted, disk.name if disk.mounted?
|
138
180
|
end
|
139
181
|
|
140
|
-
rbox.mkdir(:p, disk.path)
|
141
|
-
|
142
182
|
puts "Mounting at #{disk.path}... "
|
143
|
-
|
183
|
+
|
184
|
+
|
185
|
+
rbox.mkdir(:p, disk.path)
|
144
186
|
rbox.mount(:t, disk.fstype, disk.device, disk.path)
|
145
187
|
disk.mounted = true
|
146
188
|
disk.save :replace
|
147
189
|
sleep 1
|
190
|
+
|
148
191
|
end
|
149
192
|
|
150
193
|
|
151
|
-
def umount(rbox, disk)
|
194
|
+
def umount(rbox, disk, index)
|
195
|
+
|
152
196
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
153
197
|
disk.refresh!
|
154
198
|
|
155
|
-
|
156
|
-
|
199
|
+
unless @@global.force
|
200
|
+
raise Rudy::Disks::NotAttached, disk.name if !disk.volume_attached?
|
157
201
|
raise Rudy::Disks::NotMounted, disk.name if !disk.mounted?
|
158
202
|
end
|
159
203
|
|
160
204
|
puts "Unmounting #{disk.path}... "
|
161
|
-
|
205
|
+
|
206
|
+
unless rbox.nil? || rbox.stash.windows?
|
207
|
+
rbox.umount(disk.path)
|
208
|
+
end
|
209
|
+
|
162
210
|
disk.mounted = false
|
163
211
|
disk.save :replace
|
164
212
|
sleep 2
|
213
|
+
|
165
214
|
end
|
166
215
|
alias_method :unmount, :umount
|
167
216
|
|
168
|
-
def format(rbox, disk)
|
217
|
+
def format(rbox, disk, index)
|
169
218
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
170
219
|
disk.refresh!
|
171
220
|
|
@@ -177,20 +226,32 @@ module Rudy::Routines::Handlers;
|
|
177
226
|
raise Rudy::Disks::AlreadyFormatted, disk.name if !disk.raw?
|
178
227
|
end
|
179
228
|
|
180
|
-
|
229
|
+
if disk.fstype.nil? || disk.fstype.empty?
|
230
|
+
disk.fstype = rbox.stash.default_fstype
|
231
|
+
end
|
232
|
+
|
233
|
+
print "Creating #{disk.fstype} filesystem for #{disk.path}... "
|
234
|
+
if rbox.stash.windows?
|
235
|
+
puts "(index: #{index})"
|
236
|
+
windows_diskpart_partition rbox, disk, index
|
237
|
+
disk.mounted = true
|
238
|
+
else
|
239
|
+
puts $/
|
240
|
+
rbox.rudy_mkfs(:t, disk.fstype, :F, disk.device)
|
241
|
+
end
|
181
242
|
|
182
|
-
puts "Creating #{disk.fstype} filesystem for #{disk.device}... "
|
183
|
-
rbox.rudy_mkfs(:t, disk.fstype, :F, disk.device)
|
184
243
|
disk.raw = false
|
185
244
|
disk.save :replace
|
245
|
+
sleep 1
|
246
|
+
disk
|
186
247
|
end
|
187
248
|
|
188
|
-
def destroy(rbox, disk)
|
249
|
+
def destroy(rbox, disk, index)
|
189
250
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
190
251
|
disk.refresh!
|
191
252
|
|
192
|
-
umount rbox,
|
193
|
-
detach rbox,
|
253
|
+
umount rbox,disk,index if disk.mounted? && !rbox.nil? && !rbox.stash.windows?
|
254
|
+
detach rbox,disk,index if disk.volume_attached?
|
194
255
|
|
195
256
|
unless @@global.force
|
196
257
|
raise Rudy::Disks::InUse, disk.name if disk.volume_attached?
|
@@ -200,7 +261,7 @@ module Rudy::Routines::Handlers;
|
|
200
261
|
disk.destroy
|
201
262
|
end
|
202
263
|
|
203
|
-
def archive(rbox, disk)
|
264
|
+
def archive(rbox, disk, index)
|
204
265
|
raise Rudy::Metadata::UnknownObject, disk.name unless disk.exists?
|
205
266
|
disk.refresh!
|
206
267
|
|
@@ -210,7 +271,7 @@ module Rudy::Routines::Handlers;
|
|
210
271
|
puts "Created backup: #{back.name}"
|
211
272
|
end
|
212
273
|
|
213
|
-
def restore(rbox, disk)
|
274
|
+
def restore(rbox, disk, index)
|
214
275
|
|
215
276
|
if disk.exists?
|
216
277
|
puts "Disk found: #{disk.name}"
|
@@ -222,7 +283,11 @@ module Rudy::Routines::Handlers;
|
|
222
283
|
end
|
223
284
|
|
224
285
|
latest_backup = disk.backups.last
|
225
|
-
|
286
|
+
|
287
|
+
if latest_backup.fstype.nil? || latest_backup.fstype.empty?
|
288
|
+
latest_backup.fstype = rbox.stash.default_fstype
|
289
|
+
end
|
290
|
+
|
226
291
|
disk.size, disk.fstype = latest_backup.size, latest_backup.fstype
|
227
292
|
|
228
293
|
puts "Backup found: #{latest_backup.name}"
|
@@ -237,13 +302,33 @@ module Rudy::Routines::Handlers;
|
|
237
302
|
disk.save :replace
|
238
303
|
end
|
239
304
|
|
240
|
-
attach rbox, disk unless disk.volume_attached?
|
241
|
-
mount rbox, disk unless disk.mounted?
|
305
|
+
attach rbox, disk, index unless disk.volume_attached?
|
306
|
+
mount rbox, disk, index unless disk.mounted?
|
242
307
|
|
243
308
|
disk.save :replace
|
244
309
|
|
245
310
|
end
|
246
311
|
|
312
|
+
private
|
313
|
+
|
314
|
+
# See:
|
315
|
+
# * http://social.technet.microsoft.com/Forums/en-US/winserversetup/thread/2cfbaae1-6e33-4197-bb71-63434a34eb3c
|
316
|
+
# * http://technet.microsoft.com/en-us/library/cc766465(WS.10).aspx
|
317
|
+
def windows_diskpart_partition(rbox, disk, disk_num)
|
318
|
+
rbox.quietly { rudy_rm :f, 'diskpart-script' }
|
319
|
+
rbox.file_append 'diskpart-script', %Q{
|
320
|
+
select disk #{disk_num}
|
321
|
+
clean
|
322
|
+
create partition primary
|
323
|
+
select partition 1
|
324
|
+
active
|
325
|
+
assign letter=#{disk.path.tr(':/', '')}
|
326
|
+
exit}
|
327
|
+
rbox.rudy_diskpart '/s', 'diskpart-script'
|
328
|
+
rbox.quietly { rudy_rm :f, 'diskpart-script' }
|
329
|
+
rbox.rudy_format disk.path, '/V:RUDY', "/FS:#{disk.fstype}", '/Q', '/Y'
|
330
|
+
end
|
331
|
+
|
247
332
|
|
248
333
|
end
|
249
334
|
end
|