mkuzmin-rbvmomi 1.8.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +6 -0
  3. data/LICENSE +19 -0
  4. data/README.rdoc +78 -0
  5. data/Rakefile +45 -0
  6. data/VERSION +1 -0
  7. data/bin/rbvmomish +138 -0
  8. data/devel/analyze-vim-declarations.rb +213 -0
  9. data/devel/analyze-xml.rb +46 -0
  10. data/devel/benchmark.rb +117 -0
  11. data/devel/collisions.rb +18 -0
  12. data/devel/merge-internal-vmodl.rb +59 -0
  13. data/devel/merge-manual-vmodl.rb +32 -0
  14. data/examples/annotate.rb +54 -0
  15. data/examples/cached_ovf_deploy.rb +120 -0
  16. data/examples/clone_vm.rb +84 -0
  17. data/examples/create_vm-1.9.rb +93 -0
  18. data/examples/create_vm.rb +93 -0
  19. data/examples/extraConfig.rb +54 -0
  20. data/examples/lease_tool.rb +102 -0
  21. data/examples/logbundle.rb +63 -0
  22. data/examples/logtail.rb +60 -0
  23. data/examples/nfs_datastore.rb +95 -0
  24. data/examples/power.rb +59 -0
  25. data/examples/readme-1.rb +35 -0
  26. data/examples/readme-2.rb +51 -0
  27. data/examples/run.sh +41 -0
  28. data/examples/screenshot.rb +48 -0
  29. data/examples/vdf.rb +81 -0
  30. data/examples/vm_drs_behavior.rb +76 -0
  31. data/lib/rbvmomi.rb +12 -0
  32. data/lib/rbvmomi/basic_types.rb +375 -0
  33. data/lib/rbvmomi/connection.rb +270 -0
  34. data/lib/rbvmomi/deserialization.rb +248 -0
  35. data/lib/rbvmomi/fault.rb +17 -0
  36. data/lib/rbvmomi/pbm.rb +66 -0
  37. data/lib/rbvmomi/sms.rb +61 -0
  38. data/lib/rbvmomi/sms/SmsStorageManager.rb +7 -0
  39. data/lib/rbvmomi/trivial_soap.rb +114 -0
  40. data/lib/rbvmomi/trollop.rb +70 -0
  41. data/lib/rbvmomi/type_loader.rb +136 -0
  42. data/lib/rbvmomi/utils/admission_control.rb +398 -0
  43. data/lib/rbvmomi/utils/deploy.rb +314 -0
  44. data/lib/rbvmomi/utils/leases.rb +142 -0
  45. data/lib/rbvmomi/utils/perfdump.rb +628 -0
  46. data/lib/rbvmomi/vim.rb +128 -0
  47. data/lib/rbvmomi/vim/ComputeResource.rb +51 -0
  48. data/lib/rbvmomi/vim/Datacenter.rb +17 -0
  49. data/lib/rbvmomi/vim/Datastore.rb +68 -0
  50. data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +75 -0
  51. data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +20 -0
  52. data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +46 -0
  53. data/lib/rbvmomi/vim/Folder.rb +207 -0
  54. data/lib/rbvmomi/vim/HostSystem.rb +174 -0
  55. data/lib/rbvmomi/vim/ManagedEntity.rb +57 -0
  56. data/lib/rbvmomi/vim/ManagedObject.rb +60 -0
  57. data/lib/rbvmomi/vim/ObjectContent.rb +23 -0
  58. data/lib/rbvmomi/vim/ObjectUpdate.rb +23 -0
  59. data/lib/rbvmomi/vim/OvfManager.rb +200 -0
  60. data/lib/rbvmomi/vim/PerfCounterInfo.rb +26 -0
  61. data/lib/rbvmomi/vim/PerformanceManager.rb +110 -0
  62. data/lib/rbvmomi/vim/PropertyCollector.rb +25 -0
  63. data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +30 -0
  64. data/lib/rbvmomi/vim/ResourcePool.rb +55 -0
  65. data/lib/rbvmomi/vim/ServiceInstance.rb +55 -0
  66. data/lib/rbvmomi/vim/Task.rb +65 -0
  67. data/lib/rbvmomi/vim/VirtualMachine.rb +74 -0
  68. data/test/test_deserialization.rb +383 -0
  69. data/test/test_emit_request.rb +128 -0
  70. data/test/test_exceptions.rb +14 -0
  71. data/test/test_helper.rb +14 -0
  72. data/test/test_misc.rb +24 -0
  73. data/test/test_parse_response.rb +69 -0
  74. data/test/test_serialization.rb +311 -0
  75. data/vmodl.db +0 -0
  76. metadata +163 -0
@@ -0,0 +1,46 @@
1
+ require 'nokogiri'
2
+
3
+ # removes line breaks and whitespace between xml nodes.
4
+ def prepare_xml(xml)
5
+ xml = xml.gsub(/\n+/, "")
6
+ xml = xml.gsub(/(>)\s*(<)/, '\1\2')
7
+ end
8
+
9
+ def analyze_xml x, tree
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
+
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
+
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
+ end
25
+
26
+ def print_tree tree, indent=0
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
+
41
+ tree = {}
42
+ ARGV.each do |fn|
43
+ nk = Nokogiri(prepare_xml(File.read fn))
44
+ analyze_xml nk.root, tree
45
+ end
46
+ print_tree tree
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env ruby
2
+ require 'tempfile'
3
+
4
+ if ENV['RBVMOMI_COVERAGE'] == '1'
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+ end
8
+
9
+ require 'rbvmomi'
10
+ require 'rbvmomi/deserialization'
11
+ require 'benchmark'
12
+ require 'libxml'
13
+
14
+ NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
15
+
16
+ VIM = RbVmomi::VIM
17
+ $conn = VIM.new(:ns => 'urn:vim25', :rev => '4.0')
18
+ raw = File.read(ARGV[0])
19
+
20
+ def diff a, b
21
+ a_io = Tempfile.new 'rbvmomi-diff-a'
22
+ b_io = Tempfile.new 'rbvmomi-diff-b'
23
+ PP.pp a, a_io
24
+ PP.pp b, b_io
25
+ a_io.close
26
+ b_io.close
27
+ system("diff -u #{a_io.path} #{b_io.path}")
28
+ a_io.unlink
29
+ b_io.unlink
30
+ end
31
+
32
+ begin
33
+ deserializer = RbVmomi::OldDeserializer.new($conn)
34
+ end_time = Time.now + 1
35
+ n = 0
36
+ while n == 0 or end_time > Time.now
37
+ deserializer.deserialize Nokogiri::XML(raw).root
38
+ n += 1
39
+ end
40
+ N = n*10
41
+ end
42
+
43
+ puts "iterations: #{N}"
44
+
45
+ parsed_nokogiri = Nokogiri::XML(raw)
46
+ parsed_libxml = LibXML::XML::Parser.string(raw).parse
47
+
48
+ if true
49
+ nokogiri_xml = parsed_nokogiri.root
50
+ libxml_xml = parsed_libxml.root
51
+
52
+ old_nokogiri_result = RbVmomi::OldDeserializer.new($conn).deserialize nokogiri_xml
53
+ new_nokogiri_result = RbVmomi::NewDeserializer.new($conn).deserialize nokogiri_xml
54
+ new_libxml_result = RbVmomi::NewDeserializer.new($conn).deserialize libxml_xml
55
+
56
+ if new_nokogiri_result != old_nokogiri_result
57
+ puts "new_nokogiri_result doesnt match old_nokogiri_result"
58
+ puts "old_nokogiri_result:"
59
+ pp old_nokogiri_result
60
+ puts "new_nokogiri_result:"
61
+ pp new_nokogiri_result
62
+ puts "diff:"
63
+ diff old_nokogiri_result, new_nokogiri_result
64
+ exit 1
65
+ end
66
+
67
+ if new_libxml_result != old_nokogiri_result
68
+ puts "new_libxml_result doesnt match old_nokogiri_result"
69
+ puts "old_nokogiri_result:"
70
+ pp old_nokogiri_result
71
+ puts "new_libxml_result:"
72
+ pp new_libxml_result
73
+ puts "diff:"
74
+ diff old_nokogiri_result, new_libxml_result
75
+ exit 1
76
+ end
77
+
78
+ puts "all results match"
79
+ end
80
+
81
+ Benchmark.bmbm do|b|
82
+ GC.start
83
+ b.report("nokogiri parsing") do
84
+ N.times { Nokogiri::XML(raw) }
85
+ end
86
+
87
+ GC.start
88
+ b.report("libxml parsing") do
89
+ N.times do
90
+ LibXML::XML::Parser.string(raw).parse
91
+ end
92
+ end
93
+
94
+ GC.start
95
+ b.report("old deserialization (nokogiri)") do
96
+ deserializer = RbVmomi::OldDeserializer.new($conn)
97
+ N.times do
98
+ deserializer.deserialize Nokogiri::XML(raw).root
99
+ end
100
+ end
101
+
102
+ GC.start
103
+ b.report("new deserialization (nokogiri)") do
104
+ deserializer = RbVmomi::NewDeserializer.new($conn)
105
+ N.times do
106
+ deserializer.deserialize Nokogiri::XML(raw).root
107
+ end
108
+ end
109
+
110
+ GC.start
111
+ b.report("new deserialization (libxml)") do
112
+ deserializer = RbVmomi::NewDeserializer.new($conn)
113
+ N.times do
114
+ deserializer.deserialize LibXML::XML::Parser.string(raw).parse.root
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # Find collisions between VMODL property names and Ruby methods
3
+ require 'rbvmomi'
4
+ VIM = RbVmomi::VIM
5
+
6
+ conn = VIM.new(:ns => 'urn:vim25', :rev => '4.0')
7
+
8
+ VIM.loader.typenames.each do |name|
9
+ klass = VIM.loader.get name
10
+ next unless klass.respond_to? :kind and [:managed, :data].member? klass.kind
11
+ methods = klass.kind == :managed ?
12
+ RbVmomi::BasicTypes::ObjectWithMethods.instance_methods :
13
+ RbVmomi::BasicTypes::ObjectWithProperties.instance_methods
14
+ klass.props_desc.each do |x|
15
+ name = x['name']
16
+ puts "collision: #{klass}##{name}" if methods.member? name.to_sym
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ # These types are not public and so may change between releases. Do not
3
+ # use them directly.
4
+
5
+ public_vmodl_filename = ARGV[0] or abort "public vmodl filename required"
6
+ internal_vmodl_filename = ARGV[1] or abort "internal vmodl filename required"
7
+ output_vmodl_filename = ARGV[2] or abort "output vmodl filename required"
8
+
9
+ TYPES = %w(
10
+ DVSKeyedOpaqueData
11
+ DVSOpaqueDataConfigSpec
12
+ DVPortgroupSelection
13
+ DVPortSelection
14
+ DVSSelection
15
+ DynamicTypeEnumTypeInfo
16
+ DynamicTypeMgrAllTypeInfo
17
+ DynamicTypeMgrAnnotation
18
+ DynamicTypeMgrDataTypeInfo
19
+ DynamicTypeMgrFilterSpec
20
+ DynamicTypeMgrManagedTypeInfo
21
+ DynamicTypeMgrMethodTypeInfo
22
+ DynamicTypeMgrMethodTypeInfoAnnotationType
23
+ DynamicTypeMgrMoFilterSpec
24
+ DynamicTypeMgrMoInstance
25
+ DynamicTypeMgrParamTypeInfo
26
+ DynamicTypeMgrParamTypeInfoAnnotationType
27
+ DynamicTypeMgrPropertyTypeInfo
28
+ DynamicTypeMgrPropertyTypeInfoAnnotationType
29
+ DynamicTypeMgrTypeFilterSpec
30
+ InternalDynamicTypeManager
31
+ ReflectManagedMethodExecuter
32
+ ReflectManagedMethodExecuterSoapArgument
33
+ ReflectManagedMethodExecuterSoapFault
34
+ ReflectManagedMethodExecuterSoapResult
35
+ SelectionSet
36
+ )
37
+
38
+ METHODS = %w(
39
+ DistributedVirtualSwitchManager.UpdateDvsOpaqueData_Task
40
+ HostSystem.RetrieveDynamicTypeManager
41
+ HostSystem.RetrieveManagedMethodExecuter
42
+ )
43
+
44
+ public_vmodl = File.open(public_vmodl_filename, 'r') { |io| Marshal.load io }
45
+ internal_vmodl = File.open(internal_vmodl_filename, 'r') { |io| Marshal.load io }
46
+
47
+ TYPES.each do |k|
48
+ puts "Merging in #{k}"
49
+ fail "Couldn't find type #{k} in internal VMODL" unless internal_vmodl.member? k
50
+ public_vmodl[k] = internal_vmodl[k]
51
+ end
52
+
53
+ METHODS.each do |x|
54
+ puts "Merging in #{x}"
55
+ type, method = x.split '.'
56
+ public_vmodl[type]['methods'][method] = internal_vmodl[type]['methods'][method] or fail
57
+ end
58
+
59
+ File.open(output_vmodl_filename, 'w') { |io| Marshal.dump public_vmodl, io }
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ # Manually merge two versions of vmodl.db
3
+
4
+ public_vmodl_filename = ARGV[0] or abort "public vmodl filename required"
5
+ internal_vmodl_filename = ARGV[1] or abort "internal vmodl filename required"
6
+ output_vmodl_filename = ARGV[2] or abort "output vmodl filename required"
7
+
8
+ public_vmodl = File.open(public_vmodl_filename, 'r') { |io| Marshal.load io }
9
+ internal_vmodl = File.open(internal_vmodl_filename, 'r') { |io| Marshal.load io }
10
+
11
+ db = {}
12
+ tn = {}
13
+ public_vmodl.each do |k,v|
14
+ unless k == '_typenames'
15
+ db[k] = v
16
+ else
17
+ tn['_typenames'] = v
18
+ end
19
+ end
20
+
21
+ internal_vmodl.each do |k, v|
22
+ unless k == '_typenames'
23
+ db[k] = v unless db[k]
24
+ else
25
+ tn['_typenames'] = tn['_typenames'] + v
26
+ end
27
+ end
28
+
29
+ db['_typenames'] = tn
30
+
31
+
32
+ File.open(output_vmodl_filename, 'w') { |io| Marshal.dump db, io }
@@ -0,0 +1,54 @@
1
+ require 'trollop'
2
+ require 'rbvmomi'
3
+ require 'rbvmomi/trollop'
4
+
5
+ VIM = RbVmomi::VIM
6
+ CMDS = %w(get set)
7
+
8
+ opts = Trollop.options do
9
+ banner <<-EOS
10
+ Annotate a VM.
11
+
12
+ Usage:
13
+ annotate.rb [options] VM get
14
+ annotate.rb [options] VM set annotation
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 'get'
50
+ puts vm.config.annotation
51
+ when 'set'
52
+ value = ARGV[2] or Trollop.die("no annotation given")
53
+ vm.ReconfigVM_Task(:spec => VIM.VirtualMachineConfigSpec(:annotation => value)).wait_for_completion
54
+ end
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env ruby
2
+ require 'trollop'
3
+ require 'rbvmomi'
4
+ require 'rbvmomi/trollop'
5
+ require 'rbvmomi/utils/deploy'
6
+ require 'rbvmomi/utils/admission_control'
7
+ require 'yaml'
8
+
9
+ VIM = RbVmomi::VIM
10
+
11
+ opts = Trollop.options do
12
+ banner <<-EOS
13
+ Deploy an OVF to a cluster, using a cached template if available.
14
+
15
+ Usage:
16
+ cached_ovf_deploy.rb [options] <vmname> <ovfurl>
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
+ rbvmomi_datastore_opt
30
+
31
+ text <<-EOS
32
+
33
+ Other options:
34
+ EOS
35
+
36
+ opt :template_name, "Name to give to the (cached) template", :type => :string
37
+ opt :template_path, "Path where templates are stored", :default => 'templates', :type => :string
38
+ opt :computer_path, "Path to the cluster to deploy into", :type => :string
39
+ opt :network, "Name of the network to attach template to", :type => :string
40
+ opt :vm_folder_path, "Path to VM folder to deploy VM into", :type => :string
41
+ opt :lease, "Lease in days", :type => :int, :default => 3
42
+ end
43
+
44
+ Trollop.die("must specify host") unless opts[:host]
45
+ Trollop.die("no cluster path given") unless opts[:computer_path]
46
+ template_folder_path = opts[:template_path]
47
+ template_name = opts[:template_name] or Trollop.die("no template name given")
48
+ vm_name = ARGV[0] or Trollop.die("no VM name given")
49
+ ovf_url = ARGV[1] or Trollop.die("No OVF URL given")
50
+
51
+ vim = VIM.connect opts
52
+ dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found"
53
+
54
+ root_vm_folder = dc.vmFolder
55
+ vm_folder = root_vm_folder
56
+ if opts[:vm_folder_path]
57
+ vm_folder = root_vm_folder.traverse(opts[:vm_folder_path], VIM::Folder)
58
+ end
59
+ template_folder = root_vm_folder.traverse!(template_folder_path, VIM::Folder)
60
+
61
+ scheduler = AdmissionControlledResourceScheduler.new(
62
+ vim,
63
+ :datacenter => dc,
64
+ :computer_names => [opts[:computer_path]],
65
+ :vm_folder => vm_folder,
66
+ :rp_path => '/',
67
+ :datastore_paths => [opts[:datastore]],
68
+ :max_vms_per_pod => nil, # No limits
69
+ :min_ds_free => nil, # No limits
70
+ )
71
+ scheduler.make_placement_decision
72
+
73
+ datastore = scheduler.datastore
74
+ computer = scheduler.pick_computer
75
+ # XXX: Do this properly
76
+ if opts[:network]
77
+ network = computer.network.find{|x| x.name == opts[:network]}
78
+ else
79
+ network = computer.network[0]
80
+ end
81
+
82
+ lease_tool = LeaseTool.new
83
+ lease = opts[:lease] * 24 * 60 * 60
84
+ deployer = CachedOvfDeployer.new(
85
+ vim, network, computer, template_folder, vm_folder, datastore
86
+ )
87
+ template = deployer.lookup_template template_name
88
+
89
+ if !template
90
+ puts "#{Time.now}: Uploading/Preparing OVF template ..."
91
+
92
+ template = deployer.upload_ovf_as_template(
93
+ ovf_url, template_name,
94
+ :run_without_interruptions => true,
95
+ :config => lease_tool.set_lease_in_vm_config({}, lease)
96
+ )
97
+ end
98
+
99
+ puts "#{Time.now}: Cloning template ..."
100
+ config = {
101
+ :numCPUs => opts[:cpus],
102
+ :memoryMB => opts[:memory],
103
+ }
104
+ config = lease_tool.set_lease_in_vm_config(config, lease)
105
+ vm = deployer.linked_clone template, vm_name, config
106
+
107
+ puts "#{Time.now}: Powering On VM ..."
108
+ # XXX: Add a retrying version?
109
+ vm.PowerOnVM_Task.wait_for_completion
110
+
111
+ puts "#{Time.now}: Waiting for VM to be up ..."
112
+ ip = nil
113
+ while !(ip = vm.guest_ip)
114
+ sleep 5
115
+ end
116
+
117
+ puts "#{Time.now}: VM got IP: #{ip}"
118
+
119
+ puts "#{Time.now}: Done"
120
+