rbvmomi 1.0.2 → 1.1.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/.yardopts +5 -0
- data/README.rdoc +71 -0
- data/Rakefile +11 -0
- data/VERSION +1 -1
- data/devel/analyze-xml.rb +29 -29
- data/{test/test.rb → examples/create_vm.rb} +40 -15
- data/examples/extraConfig.rb +54 -0
- data/examples/power.rb +57 -0
- data/examples/readme-1.rb +35 -0
- data/examples/readme-2.rb +51 -0
- data/lib/rbvmomi.rb +3 -282
- data/lib/rbvmomi/{types.rb → basic_types.rb} +37 -97
- data/lib/rbvmomi/connection.rb +239 -0
- data/lib/rbvmomi/fault.rb +17 -0
- data/lib/{trivial_soap.rb → rbvmomi/trivial_soap.rb} +31 -13
- data/lib/rbvmomi/trollop.rb +6 -2
- data/lib/rbvmomi/type_loader.rb +72 -0
- data/lib/rbvmomi/vim.rb +76 -0
- data/lib/rbvmomi/vim/ComputeResource.rb +51 -0
- data/lib/rbvmomi/vim/Datacenter.rb +17 -0
- data/lib/rbvmomi/vim/Datastore.rb +68 -0
- data/lib/rbvmomi/vim/Folder.rb +112 -0
- data/lib/rbvmomi/vim/ManagedEntity.rb +46 -0
- data/lib/rbvmomi/vim/ManagedObject.rb +55 -0
- data/lib/rbvmomi/vim/ObjectContent.rb +23 -0
- data/lib/rbvmomi/vim/ObjectUpdate.rb +23 -0
- data/lib/rbvmomi/vim/OvfManager.rb +93 -0
- data/lib/rbvmomi/vim/ResourcePool.rb +18 -0
- data/lib/rbvmomi/vim/ServiceInstance.rb +53 -0
- data/lib/rbvmomi/vim/Task.rb +31 -0
- data/lib/rbvmomi/vim/VirtualMachine.rb +7 -0
- data/test/test_deserialization.rb +11 -55
- data/test/test_emit_request.rb +13 -10
- data/test/test_exceptions.rb +16 -0
- data/test/test_parse_response.rb +2 -10
- data/test/test_serialization.rb +14 -11
- metadata +41 -25
- data/.gitignore +0 -4
- data/README.md +0 -12
- data/lib/rbvmomi/extensions.rb +0 -491
- data/lib/rbvmomi/profile.rb +0 -22
- data/test/runner.rb +0 -3
data/.yardopts
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
= RbVmomi
|
2
|
+
|
3
|
+
== Introduction
|
4
|
+
|
5
|
+
RbVmomi is a Ruby interface to the vSphere API. Like the Perl and Java SDKs,
|
6
|
+
you can use it to manage ESX and VirtualCenter servers. The current release
|
7
|
+
supports the vSphere 4.1 API. RbVmomi specific documentation is
|
8
|
+
online[http://rdoc.info/github/rlane/rbvmomi/master/frames] and is meant to
|
9
|
+
be used alongside the official documentation[http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/index.html].
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
A simple example of turning on a VM:
|
14
|
+
|
15
|
+
require 'rbvmomi'
|
16
|
+
vim = RbVmomi::VIM.connect host: 'foo', user: 'bar', password: 'baz'
|
17
|
+
dc = vim.serviceInstance.find_datacenter("mydatacenter") or fail "datacenter not found"
|
18
|
+
vm = dc.find_vm("myvm") or fail "VM not found"
|
19
|
+
vm.PowerOnVM_Task.wait_for_completion
|
20
|
+
|
21
|
+
This code uses several RbVmomi extensions to the VI API for concision. The
|
22
|
+
expanded snippet below uses only standard API calls and should be familiar to
|
23
|
+
users of the Java SDK:
|
24
|
+
|
25
|
+
require 'rbvmomi'
|
26
|
+
vim = RbVmomi::VIM.connect host: 'foo', user: 'bar', password: 'baz'
|
27
|
+
rootFolder = vim.serviceInstance.content.rootFolder
|
28
|
+
dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).find { |x| x.name == "mydatacenter" } or fail "datacenter not found"
|
29
|
+
vm = dc.vmFolder.childEntity.grep(RbVmomi::VIM::VirtualMachine).find { |x| x.name == "myvm" } or fail "VM not found"
|
30
|
+
task = vm.PowerOnVM_Task
|
31
|
+
filter = vim.propertyCollector.CreateFilter(
|
32
|
+
spec: {
|
33
|
+
propSet: [{ type: 'Task', all: false, pathSet: ['info.state']}],
|
34
|
+
objectSet: [{ obj: task }]
|
35
|
+
},
|
36
|
+
partialUpdates: false
|
37
|
+
)
|
38
|
+
ver = ''
|
39
|
+
while true
|
40
|
+
result = vim.propertyCollector.WaitForUpdates(version: ver)
|
41
|
+
ver = result.version
|
42
|
+
break if ['success', 'error'].member? task.info.state
|
43
|
+
end
|
44
|
+
filter.DestroyPropertyFilter
|
45
|
+
raise task.info.error if task.info.state == 'error'
|
46
|
+
|
47
|
+
As you can see, the extensions RbVmomi adds can dramatically decrease the code
|
48
|
+
needed to perform simple tasks while still letting you use the full power of
|
49
|
+
the API when necessary. RbVmomi extensions are often more efficient than a
|
50
|
+
naive implementation; for example, the find_vm method on VIM::Datacenter used
|
51
|
+
in the first example uses the SearchIndex for fast lookups.
|
52
|
+
|
53
|
+
A few important points:
|
54
|
+
|
55
|
+
* Ruby 1.9 is required.
|
56
|
+
* Properties are exposed as accessor methods.
|
57
|
+
* All class, method, parameter, and property names match the official documentation[http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/index.html].
|
58
|
+
* Data object types can usually be inferred from context, so you may use a hash instead.
|
59
|
+
* Enumeration values are simply strings.
|
60
|
+
* Example code is included in the examples/ directory.
|
61
|
+
* A set of helper methods for Trollop is included to speed up development of
|
62
|
+
command line apps. See the included examples for usage.
|
63
|
+
* This is a side project of a VMware employee and is entirely unsupported by VMware.
|
64
|
+
|
65
|
+
Built-in extensions are under +lib/rbvmomi/vim/+. You are encouraged to
|
66
|
+
reopen VIM classes in your applications and add extensions of your own. If you
|
67
|
+
write something generally useful please send it to me and I'll add it in.
|
68
|
+
|
69
|
+
== Development
|
70
|
+
|
71
|
+
Send patches to rlane@vmware.com.
|
data/Rakefile
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'yard'
|
4
|
+
|
1
5
|
begin
|
2
6
|
require 'jeweler'
|
3
7
|
Jeweler::Tasks.new do |gem|
|
@@ -18,3 +22,10 @@ rescue LoadError
|
|
18
22
|
puts "Jeweler not available. Install it with: gem install jeweler"
|
19
23
|
end
|
20
24
|
|
25
|
+
Rake::TestTask.new do |t|
|
26
|
+
t.libs << "test"
|
27
|
+
t.test_files = FileList['test/test_*.rb']
|
28
|
+
t.verbose = true
|
29
|
+
end
|
30
|
+
|
31
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/devel/analyze-xml.rb
CHANGED
@@ -2,45 +2,45 @@ require 'nokogiri'
|
|
2
2
|
|
3
3
|
# removes line breaks and whitespace between xml nodes.
|
4
4
|
def prepare_xml(xml)
|
5
|
-
|
6
|
-
|
5
|
+
xml = xml.gsub(/\n+/, "")
|
6
|
+
xml = xml.gsub(/(>)\s*(<)/, '\1\2')
|
7
7
|
end
|
8
8
|
|
9
9
|
def analyze_xml x, tree
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
subtree = (tree[x.name] ||= { :attributes => [], :min_occur => nil, :max_occur => nil })
|
11
|
+
attrs = x.attributes.keys.sort
|
12
|
+
subtree[:attributes] << attrs unless subtree[:attributes].member? attrs
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
child_occurs = Hash.new 0
|
15
|
+
x.children.select(&:element?).each do |c|
|
16
|
+
child_occurs[c.name] += 1
|
17
|
+
analyze_xml c, subtree
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
subtree.select { |k,v| k.is_a? String }.each do |k,v|
|
21
|
+
v[:min_occur] = [v[:min_occur], child_occurs[k]].compact.min
|
22
|
+
v[:max_occur] = [v[:max_occur], child_occurs[k]].compact.max
|
23
|
+
end
|
24
24
|
end
|
25
25
|
|
26
26
|
def print_tree tree, indent=0
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
27
|
+
tree.select { |k,v| k.is_a? String }.sort.each do |k,v|
|
28
|
+
attrs = v[:attributes] || []
|
29
|
+
min, max = v[:min_occur], v[:max_occur]
|
30
|
+
numsym = if min == 0 and max == 0 then fail
|
31
|
+
elsif min == 0 and max == 1 then '?'
|
32
|
+
elsif min == 0 then '*'
|
33
|
+
elsif min == 1 and max == 1 then ''
|
34
|
+
else '+'
|
35
|
+
end
|
36
|
+
puts "#{' '*indent}#{k}#{numsym}: #{attrs.sort.map { |a| "[#{a * ' '}]"} * ', '} {#{min},#{max}}"
|
37
|
+
print_tree v, (indent+1)
|
38
|
+
end
|
39
|
+
end
|
40
40
|
|
41
41
|
tree = {}
|
42
42
|
ARGV.each do |fn|
|
43
|
-
|
44
|
-
|
43
|
+
nk = Nokogiri(prepare_xml(File.read fn))
|
44
|
+
analyze_xml nk.root, tree
|
45
45
|
end
|
46
46
|
print_tree tree
|
@@ -1,23 +1,51 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'trollop'
|
2
3
|
require 'rbvmomi'
|
3
|
-
|
4
|
+
require 'rbvmomi/trollop'
|
4
5
|
|
5
|
-
|
6
|
+
VIM = RbVmomi::VIM
|
7
|
+
N = 2
|
8
|
+
|
9
|
+
opts = Trollop.options do
|
10
|
+
banner <<-EOS
|
11
|
+
Create and destroy a couple of VMs.
|
12
|
+
|
13
|
+
Usage:
|
14
|
+
create_vm.rb [options]
|
15
|
+
|
16
|
+
VIM connection options:
|
17
|
+
EOS
|
18
|
+
|
19
|
+
rbvmomi_connection_opts
|
20
|
+
|
21
|
+
text <<-EOS
|
6
22
|
|
7
|
-
|
23
|
+
VM location options:
|
24
|
+
EOS
|
8
25
|
|
9
|
-
|
26
|
+
rbvmomi_datacenter_opt
|
27
|
+
|
28
|
+
text <<-EOS
|
29
|
+
|
30
|
+
Other options:
|
31
|
+
EOS
|
32
|
+
end
|
33
|
+
|
34
|
+
Trollop.die("must specify host") unless opts[:host]
|
35
|
+
vm_name = ARGV[0] or abort "must specify VM name"
|
36
|
+
|
37
|
+
vim = VIM.connect opts
|
38
|
+
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found"
|
10
39
|
vmFolder = dc.vmFolder
|
11
|
-
|
12
|
-
hosts = dc.hostFolder.childEntity
|
40
|
+
hosts = dc.hostFolder.children
|
13
41
|
rp = hosts.first.resourcePool
|
14
42
|
|
15
43
|
vm_cfg = {
|
16
|
-
name:
|
17
|
-
guestId: '
|
44
|
+
name: vm_name,
|
45
|
+
guestId: 'otherGuest',
|
18
46
|
files: { vmPathName: '[datastore1]' },
|
19
|
-
numCPUs:
|
20
|
-
memoryMB:
|
47
|
+
numCPUs: 1,
|
48
|
+
memoryMB: 128,
|
21
49
|
deviceChange: [
|
22
50
|
{
|
23
51
|
operation: :add,
|
@@ -58,12 +86,9 @@ vm_cfg = {
|
|
58
86
|
extraConfig: [
|
59
87
|
{
|
60
88
|
key: 'bios.bootOrder',
|
61
|
-
value:
|
89
|
+
value: 'ethernet0'
|
62
90
|
}
|
63
91
|
]
|
64
92
|
}
|
65
93
|
|
66
|
-
|
67
|
-
create_tasks = (0...N).map { vmFolder.CreateVM_Task(:config => vm_cfg, :pool => rp) }
|
68
|
-
destroy_tasks = create_tasks.map { |x| x.wait_task.Destroy_Task }
|
69
|
-
destroy_tasks.each { |x| x.wait_task }
|
94
|
+
vmFolder.CreateVM_Task(:config => vm_cfg, :pool => rp).wait_for_completion
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
require 'rbvmomi'
|
3
|
+
require 'rbvmomi/trollop'
|
4
|
+
|
5
|
+
VIM = RbVmomi::VIM
|
6
|
+
CMDS = %w(list set)
|
7
|
+
|
8
|
+
opts = Trollop.options do
|
9
|
+
banner <<-EOS
|
10
|
+
View and modify VM extraConfig options.
|
11
|
+
|
12
|
+
Usage:
|
13
|
+
extraConfig.rb [options] VM list
|
14
|
+
extraConfig.rb [options] VM set key=value [key=value...]
|
15
|
+
|
16
|
+
Commands: #{CMDS * ' '}
|
17
|
+
|
18
|
+
VIM connection options:
|
19
|
+
EOS
|
20
|
+
|
21
|
+
rbvmomi_connection_opts
|
22
|
+
|
23
|
+
text <<-EOS
|
24
|
+
|
25
|
+
VM location options:
|
26
|
+
EOS
|
27
|
+
|
28
|
+
rbvmomi_datacenter_opt
|
29
|
+
|
30
|
+
text <<-EOS
|
31
|
+
|
32
|
+
Other options:
|
33
|
+
EOS
|
34
|
+
|
35
|
+
stop_on CMDS
|
36
|
+
end
|
37
|
+
|
38
|
+
vm_name = ARGV[0] or Trollop.die("no VM name given")
|
39
|
+
cmd = ARGV[1] or Trollop.die("no command given")
|
40
|
+
abort "invalid command" unless CMDS.member? cmd
|
41
|
+
Trollop.die("must specify host") unless opts[:host]
|
42
|
+
|
43
|
+
vim = VIM.connect opts
|
44
|
+
|
45
|
+
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found"
|
46
|
+
vm = dc.find_vm(vm_name) or abort "VM not found"
|
47
|
+
|
48
|
+
case cmd
|
49
|
+
when 'list'
|
50
|
+
vm.config.extraConfig.each { |x| puts "#{x.key}: #{x.value}" }
|
51
|
+
when 'set'
|
52
|
+
extraConfig = ARGV.map { |x| x.split("=", 2) }.map { |k,v| { key: k, value: v } }
|
53
|
+
vm.ReconfigVM_Task(spec: VIM.VirtualMachineConfigSpec(extraConfig: extraConfig)).wait_for_completion
|
54
|
+
end
|
data/examples/power.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
require 'rbvmomi'
|
3
|
+
require 'rbvmomi/trollop'
|
4
|
+
|
5
|
+
VIM = RbVmomi::VIM
|
6
|
+
CMDS = %w(on off reset suspend)
|
7
|
+
|
8
|
+
opts = Trollop.options do
|
9
|
+
banner <<-EOS
|
10
|
+
Perform VM power operations.
|
11
|
+
|
12
|
+
Usage:
|
13
|
+
power.rb [options] cmd VM
|
14
|
+
|
15
|
+
Commands: #{CMDS * ' '}
|
16
|
+
|
17
|
+
VIM connection options:
|
18
|
+
EOS
|
19
|
+
|
20
|
+
rbvmomi_connection_opts
|
21
|
+
|
22
|
+
text <<-EOS
|
23
|
+
|
24
|
+
VM location options:
|
25
|
+
EOS
|
26
|
+
|
27
|
+
rbvmomi_datacenter_opt
|
28
|
+
|
29
|
+
text <<-EOS
|
30
|
+
|
31
|
+
Other options:
|
32
|
+
EOS
|
33
|
+
|
34
|
+
stop_on CMDS
|
35
|
+
end
|
36
|
+
|
37
|
+
cmd = ARGV[0] or Trollop.die("no command given")
|
38
|
+
vm_name = ARGV[1] or Trollop.die("no VM name given")
|
39
|
+
Trollop.die("must specify host") unless opts[:host]
|
40
|
+
|
41
|
+
vim = VIM.connect opts
|
42
|
+
|
43
|
+
dc = vim.serviceInstance.content.rootFolder.traverse(opts[:datacenter], VIM::Datacenter) or abort "datacenter not found"
|
44
|
+
vm = dc.vmFolder.traverse(vm_name, VIM::VirtualMachine) or abort "VM not found"
|
45
|
+
|
46
|
+
case cmd
|
47
|
+
when 'on'
|
48
|
+
vm.PowerOnVM_Task.wait_for_completion
|
49
|
+
when 'off'
|
50
|
+
vm.PowerOffVM_Task.wait_for_completion
|
51
|
+
when 'reset'
|
52
|
+
vm.ResetVM_Task.wait_for_completion
|
53
|
+
when 'suspend'
|
54
|
+
vm.SuspendVM_Task.wait_for_completion
|
55
|
+
else
|
56
|
+
abort "invalid command"
|
57
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
require 'rbvmomi/trollop'
|
3
|
+
|
4
|
+
opts = Trollop.options do
|
5
|
+
banner <<-EOS
|
6
|
+
Example 1 from the README: Power on a VM.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
readme-1.rb [options] VM name
|
10
|
+
|
11
|
+
VIM connection options:
|
12
|
+
EOS
|
13
|
+
|
14
|
+
rbvmomi_connection_opts
|
15
|
+
|
16
|
+
text <<-EOS
|
17
|
+
|
18
|
+
VM location options:
|
19
|
+
EOS
|
20
|
+
|
21
|
+
rbvmomi_datacenter_opt
|
22
|
+
|
23
|
+
text <<-EOS
|
24
|
+
|
25
|
+
Other options:
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
|
29
|
+
Trollop.die("must specify host") unless opts[:host]
|
30
|
+
vm_name = ARGV[0] or abort "must specify VM name"
|
31
|
+
|
32
|
+
vim = RbVmomi::VIM.connect opts
|
33
|
+
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or fail "datacenter not found"
|
34
|
+
vm = dc.find_vm(vm_name) or fail "VM not found"
|
35
|
+
vm.PowerOnVM_Task.wait_for_completion
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
require 'rbvmomi/trollop'
|
3
|
+
|
4
|
+
opts = Trollop.options do
|
5
|
+
banner <<-EOS
|
6
|
+
Example 2 from the README: Power on a VM the hard way.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
readme-2.rb [options] VM name
|
10
|
+
|
11
|
+
VIM connection options:
|
12
|
+
EOS
|
13
|
+
|
14
|
+
rbvmomi_connection_opts
|
15
|
+
|
16
|
+
text <<-EOS
|
17
|
+
|
18
|
+
VM location options:
|
19
|
+
EOS
|
20
|
+
|
21
|
+
rbvmomi_datacenter_opt
|
22
|
+
|
23
|
+
text <<-EOS
|
24
|
+
|
25
|
+
Other options:
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
|
29
|
+
Trollop.die("must specify host") unless opts[:host]
|
30
|
+
vm_name = ARGV[0] or abort "must specify VM name"
|
31
|
+
|
32
|
+
vim = RbVmomi::VIM.connect opts
|
33
|
+
rootFolder = vim.serviceInstance.content.rootFolder
|
34
|
+
dc = rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).find { |x| x.name == opts[:datacenter] } or fail "datacenter not found"
|
35
|
+
vm = dc.vmFolder.childEntity.grep(RbVmomi::VIM::VirtualMachine).find { |x| x.name == vm_name } or fail "VM not found"
|
36
|
+
task = vm.PowerOnVM_Task
|
37
|
+
filter = vim.propertyCollector.CreateFilter(
|
38
|
+
spec: {
|
39
|
+
propSet: [{ type: 'Task', all: false, pathSet: ['info.state']}],
|
40
|
+
objectSet: [{ obj: task }]
|
41
|
+
},
|
42
|
+
partialUpdates: false
|
43
|
+
)
|
44
|
+
ver = ''
|
45
|
+
while true
|
46
|
+
result = vim.propertyCollector.WaitForUpdates(version: ver)
|
47
|
+
ver = result.version
|
48
|
+
break if ['success', 'error'].member? task.info.state
|
49
|
+
end
|
50
|
+
filter.DestroyPropertyFilter
|
51
|
+
raise task.info.error if task.info.state == 'error'
|