solutious-rudy 0.9.1 → 0.9.2
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 +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
|