rbvmomi 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|