esx 0.1.1 → 0.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/README.md +13 -9
- data/Rakefile +4 -1
- data/bin/esx +178 -43
- data/lib/esx.rb +182 -17
- metadata +112 -122
data/README.md
CHANGED
@@ -12,11 +12,12 @@ If you want a full VMWare vSphere API ruby implementation have a look at https:/
|
|
12
12
|
|
13
13
|
# Usage
|
14
14
|
|
15
|
-
ESX ruby library includes a script to print ESX host information.
|
16
15
|
|
17
|
-
|
16
|
+
Usage: esx --help
|
18
17
|
|
19
|
-
|
18
|
+
## Available Commands
|
19
|
+
|
20
|
+
__esx info --user root --password foo 10.10.0.2__
|
20
21
|
|
21
22
|
Sample output:
|
22
23
|
|
@@ -27,14 +28,16 @@ Sample output:
|
|
27
28
|
Memory Usage: 7429
|
28
29
|
Cpu Cores: 8
|
29
30
|
Power State: poweredOn
|
31
|
+
Hosted VMs: 2
|
32
|
+
Running VMs: 1
|
30
33
|
|
31
34
|
Virtual Machines:
|
32
|
-
|
33
|
-
| NAME | MEMORY | CPUS | NICS | DISKS |
|
34
|
-
|
35
|
-
| foobar | 128 | 1 | 1 | 1 |
|
36
|
-
| foobar2 | 256 | 2 | 1 | 1 |
|
37
|
-
|
35
|
+
+-------------------------+--------+------+------+-------+------------+
|
36
|
+
| NAME | MEMORY | CPUS | NICS | DISKS | STATE |
|
37
|
+
+-------------------------+--------+------+------+-------+------------+
|
38
|
+
| foobar | 128 | 1 | 1 | 1 | poweredOn |
|
39
|
+
| foobar2 | 256 | 2 | 1 | 1 | poweredOff |
|
40
|
+
+-------------------------+--------+------+------+-------+------------+
|
38
41
|
|
39
42
|
Datastores:
|
40
43
|
+------------+--------------+--------------+-----------+------+---------------------------------------------------+
|
@@ -44,6 +47,7 @@ Sample output:
|
|
44
47
|
| datastore1 | 141465485312 | 20716716032 | VMFS | true | /vmfs/volumes/4e6117e7-35c82a3e-ba79-5cf3fc9699c2 |
|
45
48
|
+------------+--------------+--------------+-----------+------+---------------------------------------------------+
|
46
49
|
|
50
|
+
__esx create-vm --user root --password foo --name esx-rubiojr --disk-file /path/to/file.vmdk --datastore datastore1 --memory 2048 --poweron 10.10.0.2__
|
47
51
|
|
48
52
|
# Using the library
|
49
53
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
-
require 'lib/esx.rb'
|
3
|
+
require './lib/esx.rb'
|
4
4
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
@@ -18,6 +18,9 @@ Jeweler::Tasks.new do |gem|
|
|
18
18
|
gem.add_runtime_dependency 'alchemist'
|
19
19
|
gem.add_runtime_dependency 'rbvmomi'
|
20
20
|
gem.add_runtime_dependency 'terminal-table'
|
21
|
+
gem.add_runtime_dependency 'net-ssh'
|
22
|
+
gem.add_runtime_dependency 'net-scp'
|
23
|
+
gem.add_runtime_dependency 'clamp'
|
21
24
|
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
22
25
|
end
|
23
26
|
Jeweler::RubygemsDotOrgTasks.new
|
data/bin/esx
CHANGED
@@ -2,61 +2,196 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'esx'
|
4
4
|
require 'terminal-table/import'
|
5
|
+
require 'clamp'
|
6
|
+
require 'net/http'
|
7
|
+
require 'fileutils'
|
5
8
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
class BaseCommand < Clamp::Command
|
10
|
+
parameter "ADDRESS", "ESX host address"
|
11
|
+
option "--user", "USER", "Username", :default => "root"
|
12
|
+
option "--password", "PASSWORD", "Password", :default => ""
|
13
|
+
option "--debug", :flag, "Print debugging info"
|
11
14
|
end
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
class InfoCommand < BaseCommand
|
17
|
+
|
18
|
+
parameter "ADDRESS", "ESX host address"
|
19
|
+
option "--user", "USER", "Username", :default => "root"
|
20
|
+
option "--password", "PASSWORD", "Password", :default => ""
|
15
21
|
|
22
|
+
def execute
|
23
|
+
begin
|
16
24
|
|
17
|
-
|
18
|
-
print "Password: "
|
19
|
-
pass = $stdin.gets.strip.chomp
|
20
|
-
system "stty echo"
|
21
|
-
puts
|
25
|
+
host = ESX::Host.connect(address, user, password)
|
22
26
|
|
23
|
-
|
27
|
+
puts
|
28
|
+
name = host.name.upcase
|
29
|
+
puts "*" * name.size
|
30
|
+
puts name
|
31
|
+
puts "*" * name.size
|
32
|
+
puts "Memory Size: %s GB" % host.memory_size.bytes.to.gigabytes.to_f.round
|
33
|
+
puts "Memory Usage: %s GB" % host.memory_usage.bytes.to.gigabytes.to_f.round
|
34
|
+
puts "Cpu Cores: %s" % host.cpu_cores
|
35
|
+
puts "Power State: %s" % host.power_state
|
36
|
+
puts "Hosted VMs: %s" % host.virtual_machines.size
|
37
|
+
puts "Running VMs: %s" % (host.virtual_machines.find_all{ |vm| vm.power_state == 'poweredOn' }).size
|
24
38
|
|
25
|
-
|
39
|
+
if not host.virtual_machines.empty?
|
40
|
+
puts "\nVirtual Machines:"
|
41
|
+
user_table = table do |t|
|
42
|
+
t.headings = "NAME","MEMORY","CPUS","NICS","DISKS", "STATE"
|
43
|
+
host.virtual_machines.each do |vm|
|
44
|
+
t << [vm.name,vm.memory_size.bytes.to.megabytes.to_i, vm.cpus, vm.ethernet_cards_number, vm.virtual_disks_number, vm.power_state]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
puts user_table
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "\nDatastores:"
|
51
|
+
user_table = table do |t|
|
52
|
+
t.headings = "NAME","CAPACITY","FREESPACE","ACCESIBLE","TYPE","URL"
|
53
|
+
host.datastores.each do |ds|
|
54
|
+
dsname = ds.name
|
55
|
+
if dsname.size > 20
|
56
|
+
dsname = dsname[0..19] + '...'
|
57
|
+
end
|
58
|
+
t << [dsname,ds.capacity, ds.free_space, ds.datastore_type, ds.accessible, ds.url]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
puts user_table
|
62
|
+
puts
|
26
63
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
puts "Memory Usage: %s" % host.memory_usage.bytes.to.megabytes.to_i
|
34
|
-
puts "Cpu Cores: %s" % host.cpu_cores
|
35
|
-
puts "Power State: %s" % host.power_state
|
36
|
-
puts "\nVirtual Machines:"
|
37
|
-
user_table = table do |t|
|
38
|
-
t.headings = "NAME","MEMORY","CPUS","NICS","DISKS"
|
39
|
-
host.virtual_machines.each do |vm|
|
40
|
-
t << [vm.name,vm.memory_size.bytes.to.megabytes.to_i, vm.cpus, vm.ethernet_cards_number, vm.virtual_disks_number]
|
64
|
+
rescue Exception => e
|
65
|
+
puts "Error connecting to the ESX host"
|
66
|
+
puts "\n#{e.message}"
|
67
|
+
if debug?
|
68
|
+
puts e.backtrace
|
69
|
+
end
|
41
70
|
end
|
42
71
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
72
|
+
end
|
73
|
+
|
74
|
+
class CreateVMCommand < BaseCommand
|
75
|
+
|
76
|
+
parameter "ADDRESS", "ESX host address"
|
77
|
+
option "--disk-file", "DISK_FILE", "VMDK file to import", :attribute_name => :disk_file
|
78
|
+
option "--guest-id", "GUEST_ID", "GuestID value", :attribute_name => :guest_id, :default => 'otherGuest'
|
79
|
+
option "--name", "VM NAME", "Virtual Machine name (required)"
|
80
|
+
option "--memory", "MEMORY", "VM Memory size in MB", :default => 512
|
81
|
+
option "--tmpdir", "TMP DIR", "tmp dir used to download files", :default => "/tmp"
|
82
|
+
option "--datastore", "DATASTORE", "Datastore used to host the disk", :default => "datastore1"
|
83
|
+
option "--poweron", :flag, "Power on the VM after creation"
|
84
|
+
|
85
|
+
def execute
|
86
|
+
begin
|
87
|
+
host = ESX::Host.connect address, user, password
|
88
|
+
rescue Exception => e
|
89
|
+
$stderr.puts "Can't connect to the host #{address}."
|
90
|
+
if debug?
|
91
|
+
$stderr.puts e.message
|
92
|
+
end
|
93
|
+
exit 1
|
94
|
+
end
|
95
|
+
downloaded_file = nil
|
96
|
+
df = disk_file.dup
|
97
|
+
if df.strip.chomp =~ /^http/
|
98
|
+
begin
|
99
|
+
downloaded_file = disk_file.dup
|
100
|
+
tmpfile = "#{tmpdir}/#{Time.now.to_i}.esx"
|
101
|
+
puts "Downloading file... (#{tmpfile})"
|
102
|
+
download! downloaded_file, tmpfile
|
103
|
+
puts
|
104
|
+
df = tmpfile
|
105
|
+
rescue Exception => e
|
106
|
+
FileUtils.rm_f(tmpfile)
|
107
|
+
$stderr.puts "Error downloading file from #{downloaded_file}."
|
108
|
+
$stderr.puts e.message if debug?
|
109
|
+
exit 1
|
51
110
|
end
|
52
|
-
t << [dsname,ds.capacity, ds.free_space, ds.datastore_type, ds.accessible, ds.url]
|
53
111
|
end
|
112
|
+
raise Exception.new("Invalid disk file") if not File.exist?(df)
|
113
|
+
if not name
|
114
|
+
$stderr.puts "Invalid VM name."
|
115
|
+
$stderr.puts "Use --name option to specify the VM name"
|
116
|
+
exit 1
|
117
|
+
end
|
118
|
+
host.remote_command "mkdir /vmfs/volumes/#{datastore}/#{name}"
|
119
|
+
|
120
|
+
begin
|
121
|
+
host.import_disk df, "/vmfs/volumes/#{datastore}/#{name}/#{name}.vmdk"
|
122
|
+
rescue Exception => e
|
123
|
+
$stderr.puts "Error uploading file to /vmfs/volumes/#{datastore}/#{name}/#{name}.vmdk"
|
124
|
+
$stderr.puts e.message if debug?
|
125
|
+
exit 1
|
126
|
+
end
|
127
|
+
|
128
|
+
if not downloaded_file.nil?
|
129
|
+
puts "Deleting tmp file #{df}" if debug?
|
130
|
+
FileUtils.rm_f(df)
|
131
|
+
end
|
132
|
+
vm = host.create_vm :vm_name => name,
|
133
|
+
:disk_file => "#{name}/#{name}.vmdk",
|
134
|
+
:datastore => datastore, :disk_type => :flat, :memory => memory,
|
135
|
+
:guest_id => guest_id
|
136
|
+
if poweron?
|
137
|
+
vm.power_on
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def report_progress(progress, total, show_parts=true)
|
142
|
+
line_reset = "\r\e[0K"
|
143
|
+
percent = (progress.to_f / total.to_f) * 100
|
144
|
+
line = "Progress: #{percent.to_i}%"
|
145
|
+
line << " (#{progress} / #{total})" if show_parts
|
146
|
+
line = "#{line_reset}#{line}"
|
147
|
+
$stdout.sync = true
|
148
|
+
$stdout.print line
|
149
|
+
end
|
150
|
+
|
151
|
+
def download!(source_url, destination_file)
|
152
|
+
dst = File.open(destination_file, 'w')
|
153
|
+
proxy_uri = URI.parse(ENV["http_proxy"] || "")
|
154
|
+
uri = URI.parse(source_url)
|
155
|
+
http = Net::HTTP.new(uri.host, uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
|
156
|
+
|
157
|
+
if uri.scheme == "https"
|
158
|
+
http.use_ssl = true
|
159
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
160
|
+
end
|
161
|
+
|
162
|
+
res = http.start do |h|
|
163
|
+
h.request_get(uri.request_uri) do |response|
|
164
|
+
total = response.content_length
|
165
|
+
progress = 0
|
166
|
+
segment_count = 0
|
167
|
+
|
168
|
+
response.read_body do |segment|
|
169
|
+
# Report the progress out
|
170
|
+
progress += segment.length
|
171
|
+
segment_count += 1
|
172
|
+
|
173
|
+
# Progress reporting is limited to every 25 segments just so
|
174
|
+
# we're not constantly updating
|
175
|
+
if segment_count % 25 == 0
|
176
|
+
report_progress(progress, total)
|
177
|
+
segment_count = 0
|
178
|
+
end
|
179
|
+
# Store the segment
|
180
|
+
dst.write(segment)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
raise Exception.new("HTTP Error #{res}") if res.class != Net::HTTPOK
|
186
|
+
ensure
|
187
|
+
dst.close
|
54
188
|
end
|
55
|
-
puts user_table
|
56
|
-
puts
|
57
189
|
|
58
|
-
rescue Exception => e
|
59
|
-
puts "Error connecting to the ESX host"
|
60
|
-
puts "\n#{e.message}"
|
61
|
-
puts e.backtrace
|
62
190
|
end
|
191
|
+
|
192
|
+
class DefaultCommand < Clamp::Command
|
193
|
+
default_subcommand "info", "Display host info", InfoCommand
|
194
|
+
subcommand "create-vm", "Create a VM", CreateVMCommand
|
195
|
+
end
|
196
|
+
|
197
|
+
DefaultCommand.run
|
data/lib/esx.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rbvmomi'
|
3
3
|
require 'alchemist'
|
4
|
+
require 'net/scp'
|
5
|
+
require 'net/ssh'
|
4
6
|
|
5
7
|
module ESX
|
6
|
-
|
8
|
+
|
9
|
+
VERSION = '0.2'
|
7
10
|
|
8
11
|
class Host
|
9
12
|
|
13
|
+
attr_reader :address, :user, :password
|
14
|
+
|
15
|
+
def initialize(address, user, password)
|
16
|
+
@address = address
|
17
|
+
@password = password
|
18
|
+
@user = user
|
19
|
+
end
|
20
|
+
|
10
21
|
# Connect to a ESX host
|
11
22
|
#
|
12
23
|
# Requires hostname/ip, username and password
|
@@ -14,7 +25,7 @@ module ESX
|
|
14
25
|
# Host connection is insecure by default
|
15
26
|
def self.connect(host, user, password, insecure=true)
|
16
27
|
vim = RbVmomi::VIM.connect :host => host, :user => user, :password => password, :insecure => insecure
|
17
|
-
host = Host.new
|
28
|
+
host = Host.new(host, user,password)
|
18
29
|
host.vim = vim
|
19
30
|
host
|
20
31
|
end
|
@@ -77,6 +88,8 @@ module ESX
|
|
77
88
|
# :disk_size => 4096, #(in MB, optional)
|
78
89
|
# :memory => 128, #(in MB, optional)
|
79
90
|
# :datastore => datastore1 #(string, optional)
|
91
|
+
# :disk_file => path to vmdk inside datastore (optional)
|
92
|
+
# :disk_type => flat, sparse (default flat)
|
80
93
|
# }
|
81
94
|
#
|
82
95
|
# Default values above.
|
@@ -98,7 +111,7 @@ module ESX
|
|
98
111
|
vm_cfg = {
|
99
112
|
:name => spec[:vm_name],
|
100
113
|
:guestId => spec[:guest_id],
|
101
|
-
:files => { :vmPathName =>
|
114
|
+
:files => { :vmPathName => spec[:datastore] },
|
102
115
|
:numCPUs => spec[:cpus],
|
103
116
|
:memoryMB => spec[:memory],
|
104
117
|
:deviceChange => [
|
@@ -109,19 +122,6 @@ module ESX
|
|
109
122
|
:busNumber => 0,
|
110
123
|
:sharedBus => :noSharing)
|
111
124
|
},
|
112
|
-
{
|
113
|
-
:operation => :add,
|
114
|
-
:fileOperation => :create,
|
115
|
-
:device => RbVmomi::VIM.VirtualDisk(
|
116
|
-
:key => 0,
|
117
|
-
:backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
|
118
|
-
:fileName => spec[:datastore],
|
119
|
-
:diskMode => :persistent,
|
120
|
-
:thinProvisioned => true),
|
121
|
-
:controllerKey => 1000,
|
122
|
-
:unitNumber => 0,
|
123
|
-
:capacityInKB => spec[:disk_size])
|
124
|
-
},
|
125
125
|
{
|
126
126
|
:operation => :add,
|
127
127
|
:device => RbVmomi::VIM.VirtualE1000(
|
@@ -143,6 +143,10 @@ module ESX
|
|
143
143
|
}
|
144
144
|
]
|
145
145
|
}
|
146
|
+
vm_cfg[:deviceChange].push(create_disk_spec(:disk_file => spec[:disk_file],
|
147
|
+
:disk_type => spec[:disk_type],
|
148
|
+
:disk_size => spec[:disk_size],
|
149
|
+
:datastore => spec[:datastore]))
|
146
150
|
VM.wrap(@_datacenter.vmFolder.CreateVM_Task(:config => vm_cfg, :pool => @_datacenter.hostFolder.children.first.resourcePool).wait_for_completion)
|
147
151
|
end
|
148
152
|
|
@@ -172,6 +176,97 @@ module ESX
|
|
172
176
|
vms
|
173
177
|
end
|
174
178
|
|
179
|
+
#
|
180
|
+
# Run a command in the ESX host via SSH
|
181
|
+
#
|
182
|
+
def remote_command(cmd)
|
183
|
+
Net::SSH.start(@address, @user, :password => @password) do |ssh|
|
184
|
+
ssh.exec! cmd
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# Upload file
|
190
|
+
#
|
191
|
+
def upload_file(source, dest, print_progress = true)
|
192
|
+
Net::SSH.start(@address, @user, :password => @password) do |ssh|
|
193
|
+
puts "Uploading file... (#{File.basename(source)})"
|
194
|
+
ssh.scp.upload!(source, dest) do |ch, name, sent, total|
|
195
|
+
if print_progress
|
196
|
+
print "\rProgress: #{(sent.to_f * 100 / total.to_f).to_i}% completed"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
puts if print_progress
|
201
|
+
end
|
202
|
+
|
203
|
+
def import_disk(source, destination, print_progress = true)
|
204
|
+
tmp_dest = destination + ".tmp"
|
205
|
+
Net::SSH.start(@address, @user, :password => @password) do |ssh|
|
206
|
+
if not (ssh.exec! "ls #{destination} 2>/dev/null").nil?
|
207
|
+
raise Exception.new("Destination file #{destination} already exists")
|
208
|
+
end
|
209
|
+
puts "Uploading file... (#{File.basename(source)})"
|
210
|
+
ssh.scp.upload!(source, tmp_dest) do |ch, name, sent, total|
|
211
|
+
if print_progress
|
212
|
+
print "\rProgress: #{(sent.to_f * 100 / total.to_f).to_i}%"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
if print_progress
|
216
|
+
puts "\nConverting disk..."
|
217
|
+
ssh.exec "vmkfstools -i #{tmp_dest} --diskformat thin #{destination}; rm -f #{tmp_dest}"
|
218
|
+
else
|
219
|
+
ssh.exec "vmkfstools -i #{tmp_dest} --diskformat thin #{destination} >/dev/null 2>&1; rm -f #{tmp_dest}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
puts
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
#
|
227
|
+
# disk_file
|
228
|
+
# datastore
|
229
|
+
# disk_size
|
230
|
+
# disk_type
|
231
|
+
#
|
232
|
+
def create_disk_spec(params)
|
233
|
+
disk_type = params[:disk_type] || :flat
|
234
|
+
disk_file = params[:disk_file]
|
235
|
+
if disk_type == :sparse and disk_file.nil?
|
236
|
+
raise Exception.new("Creating sparse disks in ESX is not supported. Use an existing image.")
|
237
|
+
end
|
238
|
+
disk_size = params[:disk_size]
|
239
|
+
datastore = params[:datastore]
|
240
|
+
datastore = datastore + " #{disk_file}" if not disk_file.nil?
|
241
|
+
spec = {}
|
242
|
+
if disk_type == :sparse
|
243
|
+
spec = {
|
244
|
+
:operation => :add,
|
245
|
+
:device => RbVmomi::VIM.VirtualDisk(
|
246
|
+
:key => 0,
|
247
|
+
:backing => RbVmomi::VIM.VirtualDiskSparseVer2BackingInfo(
|
248
|
+
:fileName => datastore,
|
249
|
+
:diskMode => :persistent),
|
250
|
+
:controllerKey => 1000,
|
251
|
+
:unitNumber => 0,
|
252
|
+
:capacityInKB => disk_size)
|
253
|
+
}
|
254
|
+
else
|
255
|
+
spec = {
|
256
|
+
:operation => :add,
|
257
|
+
:device => RbVmomi::VIM.VirtualDisk(
|
258
|
+
:key => 0,
|
259
|
+
:backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
|
260
|
+
:fileName => datastore,
|
261
|
+
:diskMode => :persistent),
|
262
|
+
:controllerKey => 1000,
|
263
|
+
:unitNumber => 0,
|
264
|
+
:capacityInKB => disk_size)
|
265
|
+
}
|
266
|
+
end
|
267
|
+
spec[:fileOperation] = :create if disk_file.nil?
|
268
|
+
spec
|
269
|
+
end
|
175
270
|
end
|
176
271
|
|
177
272
|
class VM
|
@@ -231,19 +326,84 @@ module ESX
|
|
231
326
|
vm_object.Destroy_Task.wait_for_completion
|
232
327
|
end
|
233
328
|
|
329
|
+
def guest_info
|
330
|
+
GuestInfo.wrap(vm_object.guest)
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
# Shortcut to GuestInfo.ip_address
|
335
|
+
#
|
336
|
+
def ip_address
|
337
|
+
guest_info.ip_address
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
class NetworkInterface
|
343
|
+
|
344
|
+
attr_accessor :_wrapped_object
|
345
|
+
|
346
|
+
def self.wrap(obj)
|
347
|
+
ni = NetworkInterface.new
|
348
|
+
ni._wrapped_object = obj
|
349
|
+
ni
|
350
|
+
end
|
351
|
+
|
352
|
+
def ip_address
|
353
|
+
_wrapped_object.ipAddress.first
|
354
|
+
end
|
355
|
+
|
356
|
+
def mac
|
357
|
+
_wrapped_object.ipAddress.last
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
class GuestInfo
|
363
|
+
|
364
|
+
attr_accessor :_wrapped_object
|
365
|
+
|
366
|
+
def self.wrap(obj)
|
367
|
+
gi = GuestInfo.new
|
368
|
+
gi._wrapped_object = obj
|
369
|
+
gi
|
370
|
+
end
|
371
|
+
|
372
|
+
def ip_address
|
373
|
+
_wrapped_object.ipAddress
|
374
|
+
end
|
375
|
+
|
376
|
+
def nics
|
377
|
+
n = []
|
378
|
+
_wrapped_object.net.each do |nic|
|
379
|
+
n << NetworkInterface.wrap(nic)
|
380
|
+
end
|
381
|
+
n
|
382
|
+
end
|
383
|
+
|
384
|
+
def tools_running_status
|
385
|
+
_wrapped_object.toolsRunningStatus
|
386
|
+
end
|
387
|
+
|
388
|
+
def vmware_tools_installed?
|
389
|
+
_wrapped_object.toolsRunningStatus != 'guestToolsNotRunning'
|
390
|
+
end
|
391
|
+
|
234
392
|
end
|
235
393
|
|
236
394
|
class Datastore
|
237
395
|
|
238
396
|
attr_accessor :name, :capacity, :datastore_type, :free_space, :accessible
|
239
397
|
attr_accessor :url
|
398
|
+
# Internal use only
|
399
|
+
attr_accessor :_wrapped_object
|
240
400
|
|
241
401
|
#
|
242
402
|
# Internal method. Do not use
|
243
403
|
#
|
244
404
|
def self.wrap(ds)
|
245
|
-
@_datastore = ds
|
246
405
|
_ds = Datastore.new
|
406
|
+
_ds._wrapped_object = ds
|
247
407
|
_ds.name = ds.summary.name
|
248
408
|
_ds.capacity = ds.summary.capacity
|
249
409
|
_ds.free_space = ds.summary.freeSpace
|
@@ -252,5 +412,10 @@ module ESX
|
|
252
412
|
_ds.url = ds.summary.url
|
253
413
|
_ds
|
254
414
|
end
|
415
|
+
|
416
|
+
def method_missing(name, *args)
|
417
|
+
@_wrapped_object.send name, *args
|
418
|
+
end
|
419
|
+
|
255
420
|
end
|
256
421
|
end
|
metadata
CHANGED
@@ -1,134 +1,135 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: esx
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 1
|
10
|
-
version: 0.1.1
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Sergio Rubio
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
22
|
-
none: false
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
hash: 3
|
27
|
-
segments:
|
28
|
-
- 0
|
29
|
-
version: "0"
|
30
|
-
version_requirements: *id001
|
12
|
+
date: 2011-10-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
31
15
|
name: shoulda
|
32
|
-
|
16
|
+
requirement: &8606860 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :development
|
34
|
-
|
35
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *8606860
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bundler
|
27
|
+
requirement: &8620220 !ruby/object:Gem::Requirement
|
36
28
|
none: false
|
37
|
-
requirements:
|
29
|
+
requirements:
|
38
30
|
- - ~>
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
hash: 23
|
41
|
-
segments:
|
42
|
-
- 1
|
43
|
-
- 0
|
44
|
-
- 0
|
31
|
+
- !ruby/object:Gem::Version
|
45
32
|
version: 1.0.0
|
46
|
-
version_requirements: *id002
|
47
|
-
name: bundler
|
48
|
-
prerelease: false
|
49
33
|
type: :development
|
50
|
-
|
51
|
-
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *8620220
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: jeweler
|
38
|
+
requirement: &8618780 !ruby/object:Gem::Requirement
|
52
39
|
none: false
|
53
|
-
requirements:
|
40
|
+
requirements:
|
54
41
|
- - ~>
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
hash: 7
|
57
|
-
segments:
|
58
|
-
- 1
|
59
|
-
- 5
|
60
|
-
- 2
|
42
|
+
- !ruby/object:Gem::Version
|
61
43
|
version: 1.5.2
|
62
|
-
version_requirements: *id003
|
63
|
-
name: jeweler
|
64
|
-
prerelease: false
|
65
44
|
type: :development
|
66
|
-
- !ruby/object:Gem::Dependency
|
67
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
|
-
requirements:
|
70
|
-
- - ">="
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
hash: 3
|
73
|
-
segments:
|
74
|
-
- 0
|
75
|
-
version: "0"
|
76
|
-
version_requirements: *id004
|
77
|
-
name: rcov
|
78
45
|
prerelease: false
|
79
|
-
|
80
|
-
- !ruby/object:Gem::Dependency
|
81
|
-
|
46
|
+
version_requirements: *8618780
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rcov
|
49
|
+
requirement: &8617480 !ruby/object:Gem::Requirement
|
82
50
|
none: false
|
83
|
-
requirements:
|
84
|
-
- -
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *8617480
|
58
|
+
- !ruby/object:Gem::Dependency
|
91
59
|
name: alchemist
|
60
|
+
requirement: &8615740 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
92
67
|
prerelease: false
|
68
|
+
version_requirements: *8615740
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rbvmomi
|
71
|
+
requirement: &8614480 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
93
77
|
type: :runtime
|
94
|
-
|
95
|
-
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *8614480
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: terminal-table
|
82
|
+
requirement: &8631960 !ruby/object:Gem::Requirement
|
96
83
|
none: false
|
97
|
-
requirements:
|
98
|
-
- -
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
|
101
|
-
|
102
|
-
- 0
|
103
|
-
version: "0"
|
104
|
-
version_requirements: *id006
|
105
|
-
name: rbvmomi
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :runtime
|
106
89
|
prerelease: false
|
90
|
+
version_requirements: *8631960
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: net-ssh
|
93
|
+
requirement: &8630540 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
107
99
|
type: :runtime
|
108
|
-
|
109
|
-
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *8630540
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: net-scp
|
104
|
+
requirement: &8629100 !ruby/object:Gem::Requirement
|
110
105
|
none: false
|
111
|
-
requirements:
|
112
|
-
- -
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
|
115
|
-
|
116
|
-
- 0
|
117
|
-
version: "0"
|
118
|
-
version_requirements: *id007
|
119
|
-
name: terminal-table
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :runtime
|
120
111
|
prerelease: false
|
112
|
+
version_requirements: *8629100
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: clamp
|
115
|
+
requirement: &8627300 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
121
|
type: :runtime
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *8627300
|
122
124
|
description: Manage VMWare ESX hosts with ease
|
123
125
|
email: rubiojr@frameos.org
|
124
|
-
executables:
|
126
|
+
executables:
|
125
127
|
- esx
|
126
128
|
extensions: []
|
127
|
-
|
128
|
-
extra_rdoc_files:
|
129
|
+
extra_rdoc_files:
|
129
130
|
- LICENSE.txt
|
130
131
|
- README.md
|
131
|
-
files:
|
132
|
+
files:
|
132
133
|
- .document
|
133
134
|
- Gemfile
|
134
135
|
- LICENSE.txt
|
@@ -140,39 +141,28 @@ files:
|
|
140
141
|
- test/helper.rb
|
141
142
|
- test/test_esx.rb
|
142
143
|
homepage: http://github.com/rubiojr/esx
|
143
|
-
licenses:
|
144
|
+
licenses:
|
144
145
|
- MIT
|
145
146
|
post_install_message:
|
146
147
|
rdoc_options: []
|
147
|
-
|
148
|
-
require_paths:
|
148
|
+
require_paths:
|
149
149
|
- lib
|
150
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
151
|
none: false
|
152
|
-
requirements:
|
153
|
-
- -
|
154
|
-
- !ruby/object:Gem::Version
|
155
|
-
|
156
|
-
|
157
|
-
- 0
|
158
|
-
version: "0"
|
159
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ! '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
157
|
none: false
|
161
|
-
requirements:
|
162
|
-
- -
|
163
|
-
- !ruby/object:Gem::Version
|
164
|
-
|
165
|
-
segments:
|
166
|
-
- 0
|
167
|
-
version: "0"
|
158
|
+
requirements:
|
159
|
+
- - ! '>='
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
168
162
|
requirements: []
|
169
|
-
|
170
163
|
rubyforge_project:
|
171
|
-
rubygems_version: 1.
|
164
|
+
rubygems_version: 1.8.10
|
172
165
|
signing_key:
|
173
166
|
specification_version: 3
|
174
167
|
summary: Simple RbVmomi wrapper library to manage VMWare ESX hosts
|
175
|
-
test_files:
|
176
|
-
- examples/basics.rb
|
177
|
-
- test/helper.rb
|
178
|
-
- test/test_esx.rb
|
168
|
+
test_files: []
|