esx 0.1.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|