rbvmomi 1.6.0 → 1.8.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.
@@ -13,6 +13,7 @@ class VIM < Connection
13
13
  # @option opts [Numeric] :port (443) Port to connect to.
14
14
  # @option opts [Boolean] :ssl (true) Whether to use SSL.
15
15
  # @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
16
+ # @option opts [String] :cookie If set, use cookie to connect instead of user/password
16
17
  # @option opts [String] :user (root) Username.
17
18
  # @option opts [String] :password Password.
18
19
  # @option opts [String] :path (/sdk) SDK endpoint path.
@@ -20,6 +21,7 @@ class VIM < Connection
20
21
  def self.connect opts
21
22
  fail unless opts.is_a? Hash
22
23
  fail "host option required" unless opts[:host]
24
+ opts[:cookie] ||= nil
23
25
  opts[:user] ||= 'root'
24
26
  opts[:password] ||= ''
25
27
  opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
@@ -32,10 +34,12 @@ class VIM < Connection
32
34
  opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
33
35
 
34
36
  new(opts).tap do |vim|
35
- vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
37
+ unless opts[:cookie]
38
+ vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
39
+ end
36
40
  unless rev_given
37
41
  rev = vim.serviceContent.about.apiVersion
38
- vim.rev = [rev, '5.0'].min
42
+ vim.rev = [rev, '5.5'].min
39
43
  end
40
44
  end
41
45
  end
@@ -45,7 +49,7 @@ class VIM < Connection
45
49
  self.cookie = nil
46
50
  super
47
51
  end
48
-
52
+
49
53
  def rev= x
50
54
  super
51
55
  @serviceContent = nil
@@ -86,6 +90,35 @@ class VIM < Connection
86
90
  pp.text "VIM(#{@opts[:host]})"
87
91
  end
88
92
 
93
+ def instanceUuid
94
+ serviceContent.about.instanceUuid
95
+ end
96
+
97
+ def get_log_lines logKey, lines=5, start=nil, host=nil
98
+ diagMgr = self.serviceContent.diagnosticManager
99
+ if !start
100
+ log = diagMgr.BrowseDiagnosticLog(host: host, key: logKey, start: 999999999)
101
+ lineEnd = log.lineEnd
102
+ start = lineEnd - lines
103
+ end
104
+ start = start < 0 ? 0 : start
105
+ log = diagMgr.BrowseDiagnosticLog(host: host, key: logKey, start: start)
106
+ if log.lineText.size > 0
107
+ [log.lineText.slice(-lines, log.lineText.size), log.lineEnd]
108
+ else
109
+ [log.lineText, log.lineEnd]
110
+ end
111
+ end
112
+
113
+ def get_log_keys host=nil
114
+ diagMgr = self.serviceContent.diagnosticManager
115
+ keys = []
116
+ diagMgr.QueryDescriptions(host: host).each do |desc|
117
+ keys << "#{desc.key}"
118
+ end
119
+ keys
120
+ end
121
+
89
122
  add_extension_dir File.join(File.dirname(__FILE__), "vim")
90
123
  (ENV['RBVMOMI_VIM_EXTENSION_PATH']||'').split(':').each { |dir| add_extension_dir dir }
91
124
 
@@ -53,6 +53,16 @@ class RbVmomi::VIM::Folder
53
53
  x if x.is_a? type
54
54
  end
55
55
 
56
+ # Retrieve a managed entity by inventory path.
57
+ # @param path [String] A path of the form "My Folder/My Datacenter/vm/Discovered VM/VM1"
58
+ # @return [VIM::ManagedEntity]
59
+ def findByInventoryPath path
60
+ propSpecs = {
61
+ :entity => self, :inventoryPath => path
62
+ }
63
+ x = _connection.searchIndex.FindByInventoryPath(propSpecs)
64
+ end
65
+
56
66
  # Alias to <tt>traverse path, type, true</tt>
57
67
  # @see #traverse
58
68
  def traverse! path, type=Object
@@ -35,7 +35,12 @@ class RbVmomi::VIM::ManagedObject
35
35
  :type => self.class.wsdl_name
36
36
  }]
37
37
  }
38
- _connection.propertyCollector.RetrieveProperties(:specSet => [spec])[0].to_hash
38
+ ret = _connection.propertyCollector.RetrieveProperties(:specSet => [spec])
39
+ if ret && ret.length > 0
40
+ ret[0].to_hash
41
+ else
42
+ {}
43
+ end
39
44
  end
40
45
 
41
46
  # Efficiently retrieve multiple properties from an object.
@@ -48,7 +48,16 @@ class RbVmomi::VIM::OvfManager
48
48
  result.warning.each{|x| puts "OVF Warning: #{x.localizedMessage.chomp}" }
49
49
  end
50
50
 
51
- nfcLease = opts[:resourcePool].ImportVApp(:spec => result.importSpec,
51
+ importSpec = result.importSpec
52
+ if importSpec && importSpec.instantiationOst && importSpec.instantiationOst.child
53
+ importSpec.instantiationOst.child.each do |child|
54
+ child.section.map do |section|
55
+ section.xml = _handle_ost(section.xml, opts)
56
+ end
57
+ end
58
+ end
59
+
60
+ nfcLease = opts[:resourcePool].ImportVApp(:spec => importSpec,
52
61
  :folder => opts[:vmFolder],
53
62
  :host => opts[:host])
54
63
 
@@ -56,9 +65,32 @@ class RbVmomi::VIM::OvfManager
56
65
  raise nfcLease.error if nfcLease.state == "error"
57
66
  begin
58
67
  nfcLease.HttpNfcLeaseProgress(:percent => 5)
68
+ timeout, = nfcLease.collect 'info.leaseTimeout'
69
+ puts "DEBUG: Timeout: #{timeout}"
70
+ if timeout < 4 * 60
71
+ puts "WARNING: OVF upload NFC lease timeout less than 4 minutes"
72
+ end
59
73
  progress = 5.0
60
74
  result.fileItem.each do |fileItem|
61
- deviceUrl = nfcLease.info.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
75
+ leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
76
+ # Retry nfcLease.collect because of PR 969599:
77
+ # If retrying property collector works, this means there is a network
78
+ # or VC overloading problem.
79
+ retrynum = 5
80
+ i = 1
81
+ while i <= retrynum && !leaseState
82
+ puts "Retrying at iteration #{i}"
83
+ sleep 1
84
+ leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
85
+ i += 1
86
+ end
87
+ if leaseState != "ready"
88
+ raise "NFC lease is no longer ready: #{leaseState}: #{leaseError}"
89
+ end
90
+ if leaseInfo == nil
91
+ raise "NFC lease disappeared?"
92
+ end
93
+ deviceUrl = leaseInfo.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
62
94
  if !deviceUrl
63
95
  raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'"
64
96
  end
@@ -74,12 +106,25 @@ class RbVmomi::VIM::OvfManager
74
106
 
75
107
  keepAliveThread = Thread.new do
76
108
  while true
77
- sleep 2 * 60
78
109
  nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
110
+ sleep 1 * 60
79
111
  end
80
112
  end
81
113
 
82
- href = deviceUrl.url.gsub("*", opts[:host].config.network.vnic[0].spec.ip.ipAddress)
114
+ i = 1
115
+ ip = nil
116
+ begin
117
+ begin
118
+ puts "Iteration #{i}: Trying to get host's IP address ..."
119
+ ip = opts[:host].config.network.vnic[0].spec.ip.ipAddress
120
+ rescue Exception=>e
121
+ puts "Iteration #{i}: Couldn't get host's IP address: #{e}"
122
+ end
123
+ sleep 1
124
+ i += 1
125
+ end while i <= 5 && !ip
126
+ raise "Couldn't get host's IP address" unless ip
127
+ href = deviceUrl.url.gsub("*", ip)
83
128
  downloadCmd = "#{CURLBIN} -L '#{URI::escape(filename)}'"
84
129
  uploadCmd = "#{CURLBIN} -Ss -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' '#{URI::escape(href)}'"
85
130
  # Previously we used to append "-H 'Content-Length: #{fileItem.size}'"
@@ -96,12 +141,56 @@ class RbVmomi::VIM::OvfManager
96
141
  end
97
142
 
98
143
  nfcLease.HttpNfcLeaseProgress(:percent => 100)
99
- vm = nfcLease.info.entity
100
- nfcLease.HttpNfcLeaseComplete
144
+ raise nfcLease.error if nfcLease.state == "error"
145
+ i = 1
146
+ vm = nil
147
+ begin
148
+ begin
149
+ puts "Iteration #{i}: Trying to access nfcLease.info.entity ..."
150
+ vm = nfcLease.info.entity
151
+ rescue Exception=>e
152
+ puts "Iteration #{i}: Couldn't access nfcLease.info.entity: #{e}"
153
+ end
154
+ sleep 1
155
+ i += 1
156
+ end while i <= 5 && !vm
157
+ raise "Couldn't access nfcLease.info.entity" unless vm
158
+
159
+ # Ignore sporadic connection errors caused by PR 1019166..
160
+ # Three attempts are made to execute HttpNfcLeaseComplete.
161
+ # Not critical if none goes through, as long as vm is obtained
162
+ #
163
+ # TODO: find the reason why HttpNfcLeaseComplete gets a wrong
164
+ # response (RetrievePropertiesResponse)
165
+ i = 0
166
+ begin
167
+ nfcLease.HttpNfcLeaseComplete
168
+ puts "HttpNfcLeaseComplete succeeded"
169
+ rescue RbVmomi::VIM::InvalidState
170
+ puts "HttpNfcLeaseComplete already finished.."
171
+ rescue Exception => e
172
+ puts "HttpNfcLeaseComplete failed at iteration #{i} with exception: #{e}"
173
+ i += 1
174
+ retry if i < 3
175
+ puts "Giving up HttpNfcLeaseComplete.."
176
+ end
101
177
  vm
102
178
  end
103
179
  rescue Exception
104
180
  (nfcLease.HttpNfcLeaseAbort rescue nil) if nfcLease
105
181
  raise
106
182
  end
183
+
184
+ def _handle_ost ost, opts = {}
185
+ ost = Nokogiri::XML(ost)
186
+ if opts[:vservice] == ['com.vmware.vim.vsm:extension_vservice']
187
+ ost.xpath('//vmw:Annotations/vmw:Providers/vmw:Provider').each do |x|
188
+ x['vmw:selected'] = 'selected'
189
+ end
190
+ ost.xpath('//vmw:Annotations/vmw:Providers').each do |x|
191
+ x['vmw:selected'] = 'com.vmware.vim.vsm:extension_vservice'
192
+ end
193
+ end
194
+ ost.to_s
195
+ end
107
196
  end
@@ -46,13 +46,21 @@ class RbVmomi::VIM::PerformanceManager
46
46
  end
47
47
  end
48
48
 
49
- metric_ids = metrics.map do |x|
49
+ instances = opts[:instance] || '*'
50
+ if !instances.is_a?(Array)
51
+ instances = [instances]
52
+ end
53
+ metric_ids = []
54
+ metrics.each do |x|
50
55
  counter = perfcounter_hash[x]
51
56
  if !counter
52
57
  pp perfcounter_hash.keys
53
58
  fail "Counter for #{x} couldn't be found"
54
59
  end
55
- RbVmomi::VIM::PerfMetricId(:counterId => counter.key, :instance => '*')
60
+ instances.each do |instance|
61
+ metric_ids << RbVmomi::VIM::PerfMetricId(:counterId => counter.key,
62
+ :instance => instance)
63
+ end
56
64
  end
57
65
  query_specs = objects.map do |obj|
58
66
  RbVmomi::VIM::PerfQuerySpec({
@@ -65,19 +73,36 @@ class RbVmomi::VIM::PerformanceManager
65
73
  end
66
74
  stats = QueryPerf(:querySpec => query_specs)
67
75
 
68
- Hash[stats.map do |res|
69
- [
70
- res.entity,
71
- {
72
- :sampleInfo => res.sampleInfo,
73
- :metrics => Hash[res.value.map do |metric|
74
- [perfcounter_idhash[metric.id.counterId].name, metric.value]
75
- end]
76
- }
77
- ]
78
- end]
76
+ if !opts[:multi_instance]
77
+ Hash[stats.map do |res|
78
+ [
79
+ res.entity,
80
+ {
81
+ :sampleInfo => res.sampleInfo,
82
+ :metrics => Hash[res.value.map do |metric|
83
+ metric_name = perfcounter_idhash[metric.id.counterId].name
84
+ [metric_name, metric.value]
85
+ end]
86
+ }
87
+ ]
88
+ end]
89
+ else
90
+ Hash[stats.map do |res|
91
+ [
92
+ res.entity,
93
+ {
94
+ :sampleInfo => res.sampleInfo,
95
+ :metrics => Hash[res.value.map do |metric|
96
+ metric_name = perfcounter_idhash[metric.id.counterId].name
97
+ [[metric_name, metric.id.instance], metric.value]
98
+ end]
99
+ }
100
+ ]
101
+ end]
102
+ end
79
103
  end
80
104
 
105
+
81
106
  def active_intervals
82
107
  intervals = historicalInterval
83
108
  Hash[(1..4).map { |level| [level, intervals.select { |x| x.enabled && x.level >= level }] }]
@@ -54,7 +54,7 @@ class RbVmomi::VIM::Task
54
54
  def child_tasks
55
55
  tm = _connection.serviceContent.taskManager
56
56
  col = tm.CreateCollectorForTasks(:filter => {
57
- :rootTaskKey => self.info.key
57
+ :rootTaskKey => [self.info.key],
58
58
  })
59
59
  # XXX: Likely this is not enough and we need to collect pages other
60
60
  # than the latest.
@@ -34,26 +34,41 @@ class RbVmomi::VIM::VirtualMachine
34
34
  def add_delta_disk_layer_on_all_disks
35
35
  devices, = self.collect 'config.hardware.device'
36
36
  disks = devices.grep(RbVmomi::VIM::VirtualDisk)
37
- # XXX: Should create a single reconfig spec instead of one per disk
37
+ spec = update_spec_add_delta_disk_layer_on_all_disks
38
+ self.ReconfigVM_Task(:spec => spec).wait_for_completion
39
+ end
40
+
41
+ # Updates a passed in spec to perform the task of adding a delta disk layer
42
+ # on top of all disks. Does the same as add_delta_disk_layer_on_all_disks
43
+ # but instead of issuing the ReconfigVM_Task, it just constructs the
44
+ # spec, so that the caller can batch a couple of updates into one
45
+ # ReconfigVM_Task.
46
+ def update_spec_add_delta_disk_layer_on_all_disks spec = {}
47
+ devices, = self.collect 'config.hardware.device'
48
+ disks = devices.grep(RbVmomi::VIM::VirtualDisk)
49
+ device_change = []
38
50
  disks.each do |disk|
39
- spec = {
40
- :deviceChange => [
41
- {
42
- :operation => :remove,
43
- :device => disk
44
- },
45
- {
46
- :operation => :add,
47
- :fileOperation => :create,
48
- :device => disk.dup.tap { |x|
49
- x.backing = x.backing.dup
50
- x.backing.fileName = "[#{disk.backing.datastore.name}]"
51
- x.backing.parent = disk.backing
52
- },
53
- }
54
- ]
51
+ device_change << {
52
+ :operation => :remove,
53
+ :device => disk
55
54
  }
56
- self.ReconfigVM_Task(:spec => spec).wait_for_completion
55
+ device_change << {
56
+ :operation => :add,
57
+ :fileOperation => :create,
58
+ :device => disk.dup.tap { |x|
59
+ x.backing = x.backing.dup
60
+ x.backing.fileName = "[#{disk.backing.datastore.name}]"
61
+ x.backing.parent = disk.backing
62
+ },
63
+ }
64
+ end
65
+ if spec.is_a?(RbVmomi::VIM::VirtualMachineConfigSpec)
66
+ spec.deviceChange ||= []
67
+ spec.deviceChange += device_change
68
+ else
69
+ spec[:deviceChange] ||= []
70
+ spec[:deviceChange] += device_change
57
71
  end
72
+ spec
58
73
  end
59
74
  end
@@ -252,11 +252,14 @@ end
252
252
  :connectionState => "connected",
253
253
  :dynamicProperty => [],
254
254
  :faultToleranceState => "notConfigured",
255
+ :featureMask => [],
256
+ :featureRequirement => [],
255
257
  :host => VIM::HostSystem(nil, "host-32"),
256
258
  :maxCpuUsage => 5612,
257
259
  :maxMemoryUsage => 3072,
258
260
  :memoryOverhead => 128671744,
259
261
  :numMksConnections => 1,
262
+ :offlineFeatureRequirement => [],
260
263
  :powerState => "poweredOn",
261
264
  :recordReplayState => "inactive",
262
265
  :suspendInterval => 0,
@@ -287,9 +287,9 @@ class SerializationTest < Test::Unit::TestCase
287
287
  end
288
288
 
289
289
  def test_time
290
- obj = Time.at DateTime.new(2011, 11, 16, 13, 36, 8, Rational(-8,24)).strftime("%s").to_i
290
+ obj = Time.at(DateTime.new(2011, 11, 16, 13, 36, 8, Rational(-8,24)).strftime("%s").to_i).getgm
291
291
  check <<-EOS, obj, 'xsd:dateTime', false
292
- <root>2011-11-16T13:36:08-08:00</root>
292
+ <root>2011-11-16T21:36:08Z</root>
293
293
  EOS
294
294
  end
295
295
 
data/vmodl.db CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbvmomi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-09-19 00:00:00.000000000 Z
13
+ date: 2013-12-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -80,6 +80,7 @@ files:
80
80
  - devel/benchmark.rb
81
81
  - devel/collisions.rb
82
82
  - devel/merge-internal-vmodl.rb
83
+ - devel/merge-manual-vmodl.rb
83
84
  - examples/annotate.rb
84
85
  - examples/cached_ovf_deploy.rb
85
86
  - examples/clone_vm.rb
@@ -102,12 +103,16 @@ files:
102
103
  - lib/rbvmomi/connection.rb
103
104
  - lib/rbvmomi/deserialization.rb
104
105
  - lib/rbvmomi/fault.rb
106
+ - lib/rbvmomi/pbm.rb
107
+ - lib/rbvmomi/sms.rb
108
+ - lib/rbvmomi/sms/SmsStorageManager.rb
105
109
  - lib/rbvmomi/trivial_soap.rb
106
110
  - lib/rbvmomi/trollop.rb
107
111
  - lib/rbvmomi/type_loader.rb
108
112
  - lib/rbvmomi/utils/admission_control.rb
109
113
  - lib/rbvmomi/utils/deploy.rb
110
114
  - lib/rbvmomi/utils/leases.rb
115
+ - lib/rbvmomi/utils/perfdump.rb
111
116
  - lib/rbvmomi/vim.rb
112
117
  - lib/rbvmomi/vim/ComputeResource.rb
113
118
  - lib/rbvmomi/vim/Datacenter.rb