rvc 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/rvc +46 -70
- data/devel/test-dependencies.sh +4 -0
- data/lib/rvc.rb +5 -6
- data/lib/rvc/command.rb +65 -0
- data/lib/rvc/command_slate.rb +112 -0
- data/lib/rvc/completion.rb +89 -58
- data/lib/rvc/connection.rb +48 -0
- data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +1 -1
- data/lib/rvc/extensions/DistributedVirtualSwitch.rb +3 -3
- data/lib/rvc/extensions/HostSystem.rb +90 -0
- data/lib/rvc/extensions/VirtualMachine.rb +37 -7
- data/lib/rvc/field.rb +59 -12
- data/lib/rvc/fs.rb +34 -4
- data/lib/rvc/inventory.rb +5 -1
- data/lib/rvc/modules/alarm.rb +2 -0
- data/lib/rvc/modules/basic.rb +66 -61
- data/lib/rvc/modules/cluster.rb +117 -22
- data/lib/rvc/modules/connection.rb +40 -0
- data/lib/rvc/modules/core.rb +4 -16
- data/lib/rvc/modules/datacenter.rb +2 -0
- data/lib/rvc/modules/datastore.rb +11 -78
- data/lib/rvc/modules/device.rb +40 -5
- data/lib/rvc/modules/diagnostics.rb +169 -0
- data/lib/rvc/modules/esxcli.rb +9 -5
- data/lib/rvc/modules/find.rb +5 -3
- data/lib/rvc/modules/host.rb +46 -3
- data/lib/rvc/modules/issue.rb +2 -0
- data/lib/rvc/modules/mark.rb +5 -3
- data/lib/rvc/modules/perf.rb +99 -33
- data/lib/rvc/modules/permissions.rb +2 -0
- data/lib/rvc/modules/resource_pool.rb +2 -0
- data/lib/rvc/modules/role.rb +3 -1
- data/lib/rvc/modules/snapshot.rb +12 -4
- data/lib/rvc/modules/statsinterval.rb +13 -11
- data/lib/rvc/modules/vds.rb +67 -10
- data/lib/rvc/modules/vim.rb +19 -53
- data/lib/rvc/modules/vm.rb +27 -6
- data/lib/rvc/modules/vm_guest.rb +490 -0
- data/lib/rvc/modules/vmrc.rb +60 -32
- data/lib/rvc/modules/vnc.rb +2 -0
- data/lib/rvc/namespace.rb +114 -0
- data/lib/rvc/option_parser.rb +12 -15
- data/lib/rvc/readline-ffi.rb +4 -1
- data/lib/rvc/ruby_evaluator.rb +84 -0
- data/lib/rvc/shell.rb +68 -83
- data/lib/rvc/uri_parser.rb +59 -0
- data/lib/rvc/util.rb +134 -29
- data/lib/rvc/{extensions/PerfCounterInfo.rb → version.rb} +2 -4
- data/lib/rvc/{memory_session.rb → vim.rb} +10 -32
- data/test/modules/foo.rb +9 -0
- data/test/modules/foo/bar.rb +9 -0
- data/test/test_completion.rb +17 -0
- data/test/test_fs.rb +9 -11
- data/test/test_help.rb +46 -0
- data/test/test_helper.rb +12 -0
- data/test/test_metric.rb +1 -2
- data/test/test_modules.rb +38 -0
- data/test/test_parse_path.rb +1 -2
- data/test/test_shell.rb +138 -0
- data/test/test_uri.rb +34 -0
- metadata +115 -81
- data/lib/rvc/extensions/PerformanceManager.rb +0 -83
- data/lib/rvc/filesystem_session.rb +0 -101
- data/lib/rvc/modules.rb +0 -138
data/lib/rvc/modules/vim.rb
CHANGED
@@ -19,41 +19,9 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require 'rvc/known_hosts'
|
22
|
+
require 'rvc/vim'
|
22
23
|
|
23
|
-
|
24
|
-
^
|
25
|
-
(?:
|
26
|
-
([^@:]+)
|
27
|
-
(?::
|
28
|
-
([^@]*)
|
29
|
-
)?
|
30
|
-
@
|
31
|
-
)?
|
32
|
-
([^@:]+)
|
33
|
-
(?::(\d{1,5}))?
|
34
|
-
(?::([0-9a-z]{64}))?
|
35
|
-
$
|
36
|
-
}x
|
37
|
-
|
38
|
-
class RbVmomi::VIM
|
39
|
-
include RVC::InventoryObject
|
40
|
-
|
41
|
-
def children
|
42
|
-
rootFolder.children
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.folder?
|
46
|
-
true
|
47
|
-
end
|
48
|
-
|
49
|
-
def display_info
|
50
|
-
puts serviceContent.about.fullName
|
51
|
-
end
|
52
|
-
|
53
|
-
def _connection
|
54
|
-
self
|
55
|
-
end
|
56
|
-
end
|
24
|
+
RVC::SCHEMES['vim'] = lambda { |uri| connect uri, {} }
|
57
25
|
|
58
26
|
opts :connect do
|
59
27
|
summary 'Open a connection to ESX/VC'
|
@@ -64,14 +32,13 @@ end
|
|
64
32
|
rvc_alias :connect
|
65
33
|
|
66
34
|
def connect uri, opts
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
certdigest = match[5] || opts[:certdigest]
|
35
|
+
uri = RVC::URIParser.parse uri unless uri.is_a? URI
|
36
|
+
|
37
|
+
username = uri.user || ENV['RBVMOMI_USER']
|
38
|
+
password = uri.password || ENV['RBVMOMI_PASSWORD']
|
39
|
+
host = uri.host
|
40
|
+
port = uri.port || 443
|
41
|
+
certdigest = opts[:certdigest] # TODO put in URI
|
75
42
|
bad_cert = false
|
76
43
|
|
77
44
|
vim = nil
|
@@ -114,7 +81,7 @@ def connect uri, opts
|
|
114
81
|
if env_rev && env_rev.to_f == 0
|
115
82
|
vim.rev = env_rev
|
116
83
|
else
|
117
|
-
vim.rev = [rev, env_rev || '5.
|
84
|
+
vim.rev = [rev, env_rev || '5.1'].min
|
118
85
|
end
|
119
86
|
end
|
120
87
|
|
@@ -170,14 +137,10 @@ def connect uri, opts
|
|
170
137
|
vim.define_singleton_method(:_host) { host }
|
171
138
|
|
172
139
|
conn_name = host.dup
|
173
|
-
conn_name = "#{conn_name}:1" if
|
174
|
-
conn_name.succ! while
|
175
|
-
|
176
|
-
|
177
|
-
$shell.session.set_connection conn_name,
|
178
|
-
'host' => host,
|
179
|
-
'username' => username,
|
180
|
-
'rev' => opts[:rev]
|
140
|
+
conn_name = "#{conn_name}:1" if shell.connections.member? conn_name
|
141
|
+
conn_name.succ! while shell.connections.member? conn_name
|
142
|
+
|
143
|
+
shell.connections[conn_name] = vim
|
181
144
|
end
|
182
145
|
|
183
146
|
def prompt_password
|
@@ -242,7 +205,7 @@ opts :tasks do
|
|
242
205
|
end
|
243
206
|
|
244
207
|
def tasks
|
245
|
-
conn = single_connection [
|
208
|
+
conn = single_connection [shell.fs.cur]
|
246
209
|
|
247
210
|
begin
|
248
211
|
view = conn.serviceContent.viewManager.CreateListView
|
@@ -319,7 +282,10 @@ def logbundles servers, opts
|
|
319
282
|
puts "#{Time.now}: Generating log bundles..."
|
320
283
|
bundles =
|
321
284
|
begin
|
322
|
-
diagMgr.GenerateLogBundles_Task(
|
285
|
+
diagMgr.GenerateLogBundles_Task(
|
286
|
+
:includeDefault => include_default,
|
287
|
+
:host => hosts
|
288
|
+
).wait_for_completion
|
323
289
|
rescue VIM::TaskInProgress
|
324
290
|
$!.task.wait_for_completion
|
325
291
|
end
|
data/lib/rvc/modules/vm.rb
CHANGED
@@ -18,6 +18,9 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
+
require 'rvc/vim'
|
22
|
+
VIM::Datastore
|
23
|
+
|
21
24
|
opts :on do
|
22
25
|
summary "Power on VMs"
|
23
26
|
arg :vm, nil, :multi => true, :lookup => VIM::VirtualMachine
|
@@ -85,9 +88,10 @@ def wait_for_shutdown vms, opts
|
|
85
88
|
end
|
86
89
|
end
|
87
90
|
return if all_off
|
88
|
-
|
91
|
+
sleep_time = [opts[:delay], finish_time - Time.now].min
|
92
|
+
sleep sleep_time if sleep_time > 0
|
89
93
|
end
|
90
|
-
|
94
|
+
err "At least one VM did not shut down!"
|
91
95
|
end
|
92
96
|
|
93
97
|
|
@@ -272,7 +276,7 @@ rvc_alias :kill, :k
|
|
272
276
|
def kill vms
|
273
277
|
on_vms = vms.select { |x| x.summary.runtime.powerState == 'poweredOn' }
|
274
278
|
off on_vms unless on_vms.empty?
|
275
|
-
|
279
|
+
shell.cmds.basic.destroy vms unless vms.empty?
|
276
280
|
end
|
277
281
|
|
278
282
|
opts :answer do
|
@@ -285,9 +289,13 @@ def answer str, vms
|
|
285
289
|
vms.each do |vm|
|
286
290
|
begin
|
287
291
|
if q = vm.runtime.question
|
288
|
-
|
289
|
-
|
290
|
-
|
292
|
+
choices = q.choice.choiceInfo
|
293
|
+
choice = choices.find { |x| x.label == str }
|
294
|
+
if !choice
|
295
|
+
puts "#{vm.name}: #{choice} invalid, choices: #{choices.map{ |x| x.label }}"
|
296
|
+
else
|
297
|
+
vm.AnswerVM :questionId => q.id, :answerChoice => choice.key
|
298
|
+
end
|
291
299
|
end
|
292
300
|
rescue
|
293
301
|
puts "#{vm.name rescue vm}: #{$!.message}"
|
@@ -628,3 +636,16 @@ def vm_ip vm
|
|
628
636
|
err "no IP known for this VM"
|
629
637
|
end
|
630
638
|
end
|
639
|
+
|
640
|
+
|
641
|
+
opts :screenshot do
|
642
|
+
summary "Take a screenshot of a VM"
|
643
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
644
|
+
arg 'local-path', "Filename on the local machine"
|
645
|
+
end
|
646
|
+
|
647
|
+
rvc_alias :screenshot
|
648
|
+
|
649
|
+
def screenshot vm, local_path
|
650
|
+
http_download vm._connection, "/screen?id=#{vm._ref}", local_path
|
651
|
+
end
|
@@ -0,0 +1,490 @@
|
|
1
|
+
opts :authenticate do
|
2
|
+
summary "Authenticate within guest"
|
3
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
4
|
+
opt :interactive_session, "Allow command to interact with desktop", :default => false, :type => :bool
|
5
|
+
opt :password, "Password in guest", :type => :string
|
6
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
7
|
+
end
|
8
|
+
|
9
|
+
def authenticate vm, opts
|
10
|
+
auth = ((@auths ||= {})[vm] ||= {})[opts[:username]]
|
11
|
+
|
12
|
+
if opts[:password].nil? or opts[:password].empty?
|
13
|
+
opts[:password] = ask("password: ") { |q| q.echo = false }
|
14
|
+
end
|
15
|
+
|
16
|
+
auth = VIM.NamePasswordAuthentication(
|
17
|
+
:username => opts[:username],
|
18
|
+
:password => opts[:password],
|
19
|
+
:interactiveSession => opts[:interactive_session]
|
20
|
+
)
|
21
|
+
|
22
|
+
@auths[vm][opts[:username]] = auth
|
23
|
+
begin
|
24
|
+
check_auth vm, opts
|
25
|
+
rescue
|
26
|
+
clear_auth vm, opts
|
27
|
+
err "Could not authenticate: #{$!}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
opts :check_auth do
|
33
|
+
summary "Check credentials"
|
34
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
35
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_auth vm, opts
|
39
|
+
auth = get_auth vm, opts
|
40
|
+
|
41
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
42
|
+
|
43
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :authManager
|
44
|
+
guestOperationsManager.authManager.ValidateCredentialsInGuest(
|
45
|
+
:vm => vm,
|
46
|
+
:auth => auth
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
opts :list_auth do
|
52
|
+
summary "List available credentials"
|
53
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine, :required => false
|
54
|
+
end
|
55
|
+
|
56
|
+
def list_auth vm
|
57
|
+
if @auths.nil?
|
58
|
+
puts "No credentials available."
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
if vm.nil?
|
63
|
+
auth_list = @auths
|
64
|
+
elsif !@auths.member? vm
|
65
|
+
puts "No credentials available."
|
66
|
+
return
|
67
|
+
else
|
68
|
+
auth_list = { vm => @auths[vm] }
|
69
|
+
end
|
70
|
+
|
71
|
+
auth_list.each_key do |vmkey|
|
72
|
+
puts vmkey.rvc_path_str
|
73
|
+
auth_list[vmkey].each_key do |userkey|
|
74
|
+
puts " #{userkey}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
opts :clear_auth do
|
81
|
+
summary "Clear credentials"
|
82
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine, :required => false
|
83
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
84
|
+
end
|
85
|
+
|
86
|
+
def clear_auth vm, opts
|
87
|
+
unless @auths.nil? or vm.nil?
|
88
|
+
if @auths.member? vm
|
89
|
+
@auths[vm].delete opts[:username]
|
90
|
+
@auths.delete vm if @auths[vm].empty?
|
91
|
+
@auths = nil if @auths.empty?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def get_auth vm, opts
|
98
|
+
auth = @auths.fetch(vm).fetch(opts[:username])
|
99
|
+
ensure
|
100
|
+
err "No credentials found. You must authenticate before executing this command." if auth.nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
# File commands
|
105
|
+
opts :chmod do
|
106
|
+
summary "Change file attributes"
|
107
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
108
|
+
opt :group_id, "Group ID of file", :type => :int
|
109
|
+
opt :guest_path, "Path in guest to change ownership of", :required => true, :type => :string
|
110
|
+
opt :owner_id, "Owner ID of file", :type => :int
|
111
|
+
opt :permissions, "Permissions of file", :type => :string
|
112
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
113
|
+
end
|
114
|
+
|
115
|
+
def chmod vm, opts
|
116
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
117
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
118
|
+
fileManager = guestOperationsManager.fileManager
|
119
|
+
|
120
|
+
opts[:permissions] = opts[:permissions].to_i(8) if opts[:permissions]
|
121
|
+
|
122
|
+
auth = get_auth vm, opts
|
123
|
+
|
124
|
+
fileManager.
|
125
|
+
ChangeFileAttributesInGuest(
|
126
|
+
:vm => vm,
|
127
|
+
:auth => auth,
|
128
|
+
:guestFilePath => opts[:guest_path],
|
129
|
+
:fileAttributes => VIM.GuestPosixFileAttributes(
|
130
|
+
:groupId => opts[:group_id],
|
131
|
+
:ownerId => opts[:owner_id],
|
132
|
+
:permissions => opts[:permissions]
|
133
|
+
)
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
opts :mktmpdir do
|
139
|
+
summary "Create temporary directory in guest"
|
140
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
141
|
+
opt :guest_path, "Path in guest to create temporary directory in", :type => :string
|
142
|
+
opt :prefix, "Prefix of temporary directory", :required => true, :type => :string
|
143
|
+
opt :suffix, "Suffix of temporary directory", :required => true, :type => :string
|
144
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
145
|
+
end
|
146
|
+
|
147
|
+
def mktmpdir vm, opts
|
148
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
149
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
150
|
+
fileManager = guestOperationsManager.fileManager
|
151
|
+
|
152
|
+
auth = get_auth vm, opts
|
153
|
+
|
154
|
+
dirname = fileManager.
|
155
|
+
CreateTemporaryDirectoryInGuest(
|
156
|
+
:vm => vm,
|
157
|
+
:auth => auth,
|
158
|
+
:prefix => opts[:prefix],
|
159
|
+
:suffix => opts[:suffix],
|
160
|
+
:directoryPath => opts[:guest_path]
|
161
|
+
)
|
162
|
+
puts dirname
|
163
|
+
return dirname
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
opts :mktmpfile do
|
168
|
+
summary "Create temporary file in guest"
|
169
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
170
|
+
opt :guest_path, "Path in guest to create temporary file in", :type => :string
|
171
|
+
opt :prefix, "Prefix of temporary directory", :required => true, :type => :string
|
172
|
+
opt :suffix, "Suffix of temporary directory", :required => true, :type => :string
|
173
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
174
|
+
end
|
175
|
+
|
176
|
+
def mktmpfile vm, opts
|
177
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
178
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
179
|
+
fileManager = guestOperationsManager.fileManager
|
180
|
+
|
181
|
+
auth = get_auth vm, opts
|
182
|
+
|
183
|
+
filename = fileManager.
|
184
|
+
CreateTemporaryFileInGuest(
|
185
|
+
:vm => vm,
|
186
|
+
:auth => auth,
|
187
|
+
:prefix => opts[:prefix],
|
188
|
+
:suffix => opts[:suffix],
|
189
|
+
:directoryPath => opts[:guest_path]
|
190
|
+
)
|
191
|
+
puts filename
|
192
|
+
return filename
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
opts :rmdir do
|
197
|
+
summary "Delete directory in guest"
|
198
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
199
|
+
opt :guest_path, "Path of directory in guest to delete", :required => true, :type => :string
|
200
|
+
opt :recursive, "Delete all subdirectories", :default => false, :type => :bool
|
201
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
202
|
+
end
|
203
|
+
|
204
|
+
def rmdir vm, opts
|
205
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
206
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
207
|
+
fileManager = guestOperationsManager.fileManager
|
208
|
+
|
209
|
+
auth = get_auth vm, opts
|
210
|
+
|
211
|
+
fileManager.
|
212
|
+
DeleteDirectoryInGuest(
|
213
|
+
:vm => vm,
|
214
|
+
:auth => auth,
|
215
|
+
:directoryPath => opts[:guest_path],
|
216
|
+
:recursive => opts[:recursive]
|
217
|
+
)
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
opts :rmfile do
|
222
|
+
summary "Delete file in guest"
|
223
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
224
|
+
opt :guest_path, "Path of file in guest to delete", :required => true, :type => :string
|
225
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
226
|
+
end
|
227
|
+
|
228
|
+
def rmfile vm, opts
|
229
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
230
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
231
|
+
fileManager = guestOperationsManager.fileManager
|
232
|
+
|
233
|
+
auth = get_auth vm, opts
|
234
|
+
|
235
|
+
fileManager.
|
236
|
+
DeleteFileInGuest(
|
237
|
+
:vm => vm,
|
238
|
+
:auth => auth,
|
239
|
+
:filePath => opts[:guest_path]
|
240
|
+
)
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
opts :download_file do
|
245
|
+
summary "Download file from guest"
|
246
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
247
|
+
opt :guest_path, "Path in guest to download from", :required => true, :type => :string
|
248
|
+
opt :local_path, "Local file to download to", :required => true, :type => :string
|
249
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
250
|
+
end
|
251
|
+
|
252
|
+
def download_file vm, opts
|
253
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
254
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
255
|
+
fileManager = guestOperationsManager.fileManager
|
256
|
+
|
257
|
+
auth = get_auth vm, opts
|
258
|
+
|
259
|
+
download_url = fileManager.
|
260
|
+
InitiateFileTransferFromGuest(
|
261
|
+
:vm => vm,
|
262
|
+
:auth => auth,
|
263
|
+
:guestFilePath => opts[:guest_path]
|
264
|
+
).url
|
265
|
+
|
266
|
+
download_uri = URI.parse(download_url.gsub /http(s?):\/\/\*:[0-9]*/, "")
|
267
|
+
download_path = "#{download_uri.path}?#{download_uri.query}"
|
268
|
+
|
269
|
+
http_download vm._connection, download_path, opts[:local_path]
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
opts :upload_file do
|
274
|
+
summary "Upload file to guest"
|
275
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
276
|
+
opt :group_id, "Group ID of file", :type => :int
|
277
|
+
opt :guest_path, "Path in guest to upload to", :required => true, :type => :string
|
278
|
+
opt :local_path, "Local file to upload", :required => true, :type => :string
|
279
|
+
opt :overwrite, "Overwrite file", :default => false, :type => :bool
|
280
|
+
opt :owner_id, "Owner ID of file", :type => :int
|
281
|
+
opt :permissions, "Permissions of file", :type => :string
|
282
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
283
|
+
end
|
284
|
+
|
285
|
+
def upload_file vm, opts
|
286
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
287
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
288
|
+
fileManager = guestOperationsManager.fileManager
|
289
|
+
|
290
|
+
opts[:permissions] = opts[:permissions].to_i(8) if opts[:permissions]
|
291
|
+
|
292
|
+
auth = get_auth vm, opts
|
293
|
+
|
294
|
+
file = File.new(opts[:local_path], 'rb')
|
295
|
+
|
296
|
+
upload_url = fileManager.
|
297
|
+
InitiateFileTransferToGuest(
|
298
|
+
:vm => vm,
|
299
|
+
:auth => auth,
|
300
|
+
:guestFilePath => opts[:guest_path],
|
301
|
+
:fileAttributes => VIM.GuestPosixFileAttributes(
|
302
|
+
:groupId => opts[:group_id],
|
303
|
+
:ownerId => opts[:owner_id],
|
304
|
+
:permissions => opts[:permissions]
|
305
|
+
),
|
306
|
+
:fileSize => file.size,
|
307
|
+
:overwrite => opts[:overwrite]
|
308
|
+
)
|
309
|
+
|
310
|
+
upload_uri = URI.parse(upload_url.gsub /http(s?):\/\/\*:[0-9]*/, "")
|
311
|
+
upload_path = "#{upload_uri.path}?#{upload_uri.query}"
|
312
|
+
|
313
|
+
http_upload vm._connection, opts[:local_path], upload_path
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
opts :ls_guest do
|
318
|
+
summary "List files in guest"
|
319
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
320
|
+
opt :guest_path, "Path in guest to get directory listing", :required => true, :type => :string
|
321
|
+
opt :index, "Which to start the list with", :type => :int, :default => nil
|
322
|
+
opt :match_pattern, "Filename filter (regular expression)", :type => :string
|
323
|
+
opt :max_results, "Maximum number of results", :type => :int, :default => nil
|
324
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
325
|
+
end
|
326
|
+
|
327
|
+
def ls_guest vm, opts
|
328
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
329
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
330
|
+
fileManager = guestOperationsManager.fileManager
|
331
|
+
|
332
|
+
auth = get_auth vm, opts
|
333
|
+
|
334
|
+
files = fileManager.
|
335
|
+
ListFilesInGuest(
|
336
|
+
:vm => vm,
|
337
|
+
:auth => auth,
|
338
|
+
:filePath => opts[:guest_path],
|
339
|
+
:index => opts[:index],
|
340
|
+
:maxResults => opts[:max_results],
|
341
|
+
:matchPattern => opts[:match_pattern]
|
342
|
+
)
|
343
|
+
|
344
|
+
files.files.each do |file|
|
345
|
+
puts file.path
|
346
|
+
end
|
347
|
+
|
348
|
+
puts "Remaining: #{files.remaining}" unless files.remaining.zero?
|
349
|
+
|
350
|
+
return files
|
351
|
+
end
|
352
|
+
|
353
|
+
|
354
|
+
opts :mkdir do
|
355
|
+
summary "Make directory in guest"
|
356
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
357
|
+
opt :guest_path, "Path of directory in guest to create", :required => true, :type => :string
|
358
|
+
opt :create_parent_directories, "Create parent directories", :default => false, :type => :bool
|
359
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
360
|
+
end
|
361
|
+
|
362
|
+
def mkdir vm, opts
|
363
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
364
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
365
|
+
fileManager = guestOperationsManager.fileManager
|
366
|
+
|
367
|
+
auth = get_auth vm, opts
|
368
|
+
|
369
|
+
fileManager.
|
370
|
+
MakeDirectoryInGuest(
|
371
|
+
:vm => vm,
|
372
|
+
:auth => auth,
|
373
|
+
:directoryPath => opts[:guest_path],
|
374
|
+
:createParentDirectories => opts[:create_parent_directories]
|
375
|
+
)
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
opts :mvdir do
|
380
|
+
summary "Move directory in guest"
|
381
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
382
|
+
opt :src_guest_path, "Path in guest to move from", :required => true, :type => :string
|
383
|
+
opt :dst_guest_path, "Path in guest to move to", :required => true, :type => :string
|
384
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
385
|
+
end
|
386
|
+
|
387
|
+
def mvdir vm, opts
|
388
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
389
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
390
|
+
fileManager = guestOperationsManager.fileManager
|
391
|
+
|
392
|
+
auth = get_auth vm, opts
|
393
|
+
|
394
|
+
fileManager.
|
395
|
+
MoveDirectoryInGuest(
|
396
|
+
:vm => vm,
|
397
|
+
:auth => auth,
|
398
|
+
:srcDirectoryPath => opts[:src_guest_path],
|
399
|
+
:dstDirectoryPath => opts[:dst_guest_path]
|
400
|
+
)
|
401
|
+
end
|
402
|
+
|
403
|
+
|
404
|
+
opts :mvfile do
|
405
|
+
summary "Move file in guest"
|
406
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
407
|
+
opt :dst_guest_path, "Path in guest to move to", :required => true, :type => :string
|
408
|
+
opt :overwrite, "Overwrite file", :default => true, :type => :bool
|
409
|
+
opt :src_guest_path, "Path in guest to move from", :required => true, :type => :string
|
410
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
411
|
+
end
|
412
|
+
|
413
|
+
def mvfile vm, opts
|
414
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
415
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :fileManager
|
416
|
+
fileManager = guestOperationsManager.fileManager
|
417
|
+
|
418
|
+
auth = get_auth vm, opts
|
419
|
+
|
420
|
+
fileManager.
|
421
|
+
MoveFileInGuest(
|
422
|
+
:vm => vm,
|
423
|
+
:auth => auth,
|
424
|
+
:srcFilePath => opts[:src_guest_path],
|
425
|
+
:dstFilePath => opts[:dst_guest_path],
|
426
|
+
:overwrite => opts[:overwrite]
|
427
|
+
)
|
428
|
+
end
|
429
|
+
|
430
|
+
|
431
|
+
# Process commands
|
432
|
+
opts :start_program do
|
433
|
+
summary "Run program in guest"
|
434
|
+
arg :vm, nil, :lookup => VIM::VirtualMachine
|
435
|
+
opt :arguments, "Arguments of command", :default => "", :type => :string
|
436
|
+
opt :background, "Don't wait for process to finish", :default => false, :type => :bool
|
437
|
+
opt :delay, "Interval in seconds", :type => :float, :default => 5.0
|
438
|
+
opt :env, "Environment variable(s) to set (e.g. VAR=value)", :multi => true, :type => :string
|
439
|
+
opt :program_path, "Path to program in guest", :required => true, :type => :string
|
440
|
+
opt :timeout, "Timeout in seconds", :type => :int, :default => nil
|
441
|
+
opt :username, "Username in guest", :default => "root", :type => :string
|
442
|
+
opt :working_directory, "Working directory of the program to run", :type => :string
|
443
|
+
conflicts :background, :timeout
|
444
|
+
conflicts :background, :delay
|
445
|
+
end
|
446
|
+
|
447
|
+
def start_program vm, opts
|
448
|
+
guestOperationsManager = vm._connection.serviceContent.guestOperationsManager
|
449
|
+
err "This command requires vSphere 5 or greater" unless guestOperationsManager.respond_to? :processManager
|
450
|
+
processManager = guestOperationsManager.processManager
|
451
|
+
|
452
|
+
auth = get_auth vm, opts
|
453
|
+
|
454
|
+
pid = processManager.
|
455
|
+
StartProgramInGuest(
|
456
|
+
:vm => vm,
|
457
|
+
:auth => auth,
|
458
|
+
:spec => VIM.GuestProgramSpec(
|
459
|
+
:arguments => opts[:arguments],
|
460
|
+
:programPath => opts[:program_path],
|
461
|
+
:envVariables => opts[:env],
|
462
|
+
:workingDirectory => opts[:working_directory]
|
463
|
+
)
|
464
|
+
)
|
465
|
+
|
466
|
+
Timeout.timeout opts[:timeout] do
|
467
|
+
while true
|
468
|
+
processes = processManager.
|
469
|
+
ListProcessesInGuest(
|
470
|
+
:vm => vm,
|
471
|
+
:auth => auth,
|
472
|
+
:pids => [pid]
|
473
|
+
)
|
474
|
+
process = processes.first
|
475
|
+
|
476
|
+
if !process.endTime.nil?
|
477
|
+
if process.exitCode != 0
|
478
|
+
err "Process failed with exit code #{process.exitCode}"
|
479
|
+
end
|
480
|
+
break
|
481
|
+
elsif opts[:background]
|
482
|
+
break
|
483
|
+
end
|
484
|
+
|
485
|
+
sleep opts[:delay]
|
486
|
+
end
|
487
|
+
end
|
488
|
+
rescue Timeout::Error
|
489
|
+
err "Timed out waiting for process to finish."
|
490
|
+
end
|