mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-27 14:03:40 +03:00
Update vendorized rbvmomi to version 1.8.2
This commit is contained in:
parent
8474dd89a5
commit
1fb5f9aeff
2
share/vendor/ruby/gems/rbvmomi/Rakefile
vendored
2
share/vendor/ruby/gems/rbvmomi/Rakefile
vendored
@ -1,5 +1,5 @@
|
|||||||
require 'rake/testtask'
|
require 'rake/testtask'
|
||||||
require 'rake/rdoctask'
|
require 'rdoc/task'
|
||||||
require 'yard'
|
require 'yard'
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
2
share/vendor/ruby/gems/rbvmomi/VERSION
vendored
2
share/vendor/ruby/gems/rbvmomi/VERSION
vendored
@ -1 +1 @@
|
|||||||
1.6.0
|
1.8.2
|
||||||
|
@ -185,7 +185,9 @@ class ManagedObject < ObjectWithMethods
|
|||||||
:objectSet => [{ :obj => self }],
|
:objectSet => [{ :obj => self }],
|
||||||
}])[0]
|
}])[0]
|
||||||
|
|
||||||
if ret.propSet.empty?
|
if !ret
|
||||||
|
return nil
|
||||||
|
elsif ret.propSet.empty?
|
||||||
return nil if ret.missingSet.empty?
|
return nil if ret.missingSet.empty?
|
||||||
raise ret.missingSet[0].fault
|
raise ret.missingSet[0].fault
|
||||||
else
|
else
|
||||||
@ -217,7 +219,7 @@ class ManagedObject < ObjectWithMethods
|
|||||||
|
|
||||||
def == x
|
def == x
|
||||||
out = (x.class == self.class && x._ref == @ref)
|
out = (x.class == self.class && x._ref == @ref)
|
||||||
out = (out && x._connection.instanceUuid == self._connection.instanceUuid)
|
out = (x._connection.instanceUuid == self._connection.instanceUuid) if out && x._connection.host
|
||||||
out
|
out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -115,27 +115,29 @@ class Connection < TrivialSoap
|
|||||||
# hic sunt dracones
|
# hic sunt dracones
|
||||||
def obj2xml xml, name, type, is_array, o, attrs={}
|
def obj2xml xml, name, type, is_array, o, attrs={}
|
||||||
expected = type(type)
|
expected = type(type)
|
||||||
fail "expected array, got #{o.class.wsdl_name}" if is_array and not (o.is_a? Array or (o.is_a? Hash and expected == BasicTypes::KeyValue))
|
fail "expected array for '#{name}', got #{o.class.wsdl_name}" if is_array and not (o.is_a? Array or (o.is_a? Hash and expected == BasicTypes::KeyValue))
|
||||||
case o
|
case o
|
||||||
when Array, BasicTypes::KeyValue
|
when Array, BasicTypes::KeyValue
|
||||||
if o.is_a? BasicTypes::KeyValue and expected != BasicTypes::KeyValue
|
if o.is_a? BasicTypes::KeyValue and expected != BasicTypes::KeyValue
|
||||||
fail "expected #{expected.wsdl_name}, got KeyValue"
|
fail "expected #{expected.wsdl_name} for '#{name}', got KeyValue"
|
||||||
elsif expected == BasicTypes::KeyValue and not is_array
|
elsif expected == BasicTypes::KeyValue and not is_array
|
||||||
xml.tag! name, attrs do
|
xml.tag! name, attrs do
|
||||||
xml.tag! 'key', o[0].to_s
|
xml.tag! 'key', o[0].to_s
|
||||||
xml.tag! 'value', o[1].to_s
|
xml.tag! 'value', o[1].to_s
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
fail "expected #{expected.wsdl_name}, got array" unless is_array
|
fail "expected #{expected.wsdl_name} for '#{name}', got array" unless is_array
|
||||||
o.each do |e|
|
o.each do |e|
|
||||||
obj2xml xml, name, expected.wsdl_name, false, e, attrs
|
obj2xml xml, name, expected.wsdl_name, false, e, attrs
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
when BasicTypes::ManagedObject
|
when BasicTypes::ManagedObject
|
||||||
fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
|
fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
|
||||||
xml.tag! name, o._ref, :type => o.class.wsdl_name
|
xml.tag! name, o._ref, :type => o.class.wsdl_name
|
||||||
when BasicTypes::DataObject
|
when BasicTypes::DataObject
|
||||||
fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
|
if expected and not expected >= o.class and not expected == BasicTypes::AnyType
|
||||||
|
fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}"
|
||||||
|
end
|
||||||
xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
|
xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
|
||||||
o.class.full_props_desc.each do |desc|
|
o.class.full_props_desc.each do |desc|
|
||||||
if o.props.member? desc['name'].to_sym
|
if o.props.member? desc['name'].to_sym
|
||||||
@ -151,11 +153,11 @@ class Connection < TrivialSoap
|
|||||||
if expected == BasicTypes::KeyValue and is_array
|
if expected == BasicTypes::KeyValue and is_array
|
||||||
obj2xml xml, name, type, is_array, o.to_a, attrs
|
obj2xml xml, name, type, is_array, o.to_a, attrs
|
||||||
else
|
else
|
||||||
fail "expected #{expected.wsdl_name}, got a hash" unless expected <= BasicTypes::DataObject
|
fail "expected #{expected.wsdl_name} for '#{name}', got a hash" unless expected <= BasicTypes::DataObject
|
||||||
obj2xml xml, name, type, false, expected.new(o), attrs
|
obj2xml xml, name, type, false, expected.new(o), attrs
|
||||||
end
|
end
|
||||||
when true, false
|
when true, false
|
||||||
fail "expected #{expected.wsdl_name}, got a boolean" unless [BasicTypes::Boolean, BasicTypes::AnyType].member? expected
|
fail "expected #{expected.wsdl_name} for '#{name}', got a boolean" unless [BasicTypes::Boolean, BasicTypes::AnyType].member? expected
|
||||||
attrs['xsi:type'] = 'xsd:boolean' if expected == BasicTypes::AnyType
|
attrs['xsi:type'] = 'xsd:boolean' if expected == BasicTypes::AnyType
|
||||||
xml.tag! name, (o ? '1' : '0'), attrs
|
xml.tag! name, (o ? '1' : '0'), attrs
|
||||||
when Symbol, String
|
when Symbol, String
|
||||||
@ -181,7 +183,7 @@ class Connection < TrivialSoap
|
|||||||
when BasicTypes::Int
|
when BasicTypes::Int
|
||||||
attrs['xsi:type'] = 'xsd:int'
|
attrs['xsi:type'] = 'xsd:int'
|
||||||
xml.tag! name, o.to_s, attrs
|
xml.tag! name, o.to_s, attrs
|
||||||
else fail "unexpected object class #{o.class}"
|
else fail "unexpected object class #{o.class} for '#{name}'"
|
||||||
end
|
end
|
||||||
xml
|
xml
|
||||||
rescue
|
rescue
|
||||||
|
@ -43,6 +43,13 @@ class NewDeserializer
|
|||||||
|
|
||||||
def deserialize node, type=nil
|
def deserialize node, type=nil
|
||||||
type_attr = node['type']
|
type_attr = node['type']
|
||||||
|
|
||||||
|
# Work around for 1.5.x which doesn't populate node['type']
|
||||||
|
# XXX what changed
|
||||||
|
if node.attributes['type'] and not type_attr
|
||||||
|
type_attr = node.attributes['type'].value
|
||||||
|
end
|
||||||
|
|
||||||
type = type_attr if type_attr
|
type = type_attr if type_attr
|
||||||
|
|
||||||
if action = BUILTIN_TYPE_ACTIONS[type]
|
if action = BUILTIN_TYPE_ACTIONS[type]
|
||||||
@ -64,15 +71,18 @@ class NewDeserializer
|
|||||||
else fail
|
else fail
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
if type =~ /:/
|
||||||
|
type = type.split(":", 2)[1]
|
||||||
|
end
|
||||||
if type =~ /^ArrayOf/
|
if type =~ /^ArrayOf/
|
||||||
type = DEMANGLED_ARRAY_TYPES[$'] || $'
|
type = DEMANGLED_ARRAY_TYPES[$'] || $'
|
||||||
return node.children.select(&:element?).map { |c| deserialize c, type }
|
return node.children.select(&:element?).map { |c| deserialize c, type }
|
||||||
end
|
end
|
||||||
|
|
||||||
if type =~ /:/
|
if type =~ /:/
|
||||||
type = type.split(":", 2)[1]
|
type = type.split(":", 2)[1]
|
||||||
end
|
end
|
||||||
klass = @loader.get(type) or fail "no such type #{type}"
|
|
||||||
|
klass = @loader.get(type) or fail "no such type '#{type}'"
|
||||||
case klass.kind
|
case klass.kind
|
||||||
when :data
|
when :data
|
||||||
traverse_data node, klass
|
traverse_data node, klass
|
||||||
@ -229,7 +239,7 @@ class OldDeserializer
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV['RBVMOMI_NEW_DESERIALIZER'] == '1'
|
if ENV['RBVMOMI_NEW_DESERIALIZER'] == '1' || true # Always use new one now
|
||||||
Deserializer = NewDeserializer
|
Deserializer = NewDeserializer
|
||||||
else
|
else
|
||||||
Deserializer = OldDeserializer
|
Deserializer = OldDeserializer
|
||||||
|
@ -49,9 +49,9 @@ class PBM < Connection
|
|||||||
@serviceInstance ||= VIM::PbmServiceInstance self, 'ServiceInstance'
|
@serviceInstance ||= VIM::PbmServiceInstance self, 'ServiceInstance'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Alias to serviceInstance.RetrieveServiceContent
|
# Alias to serviceInstance.PbmRetrieveServiceContent
|
||||||
def serviceContent
|
def serviceContent
|
||||||
@serviceContent ||= serviceInstance.RetrieveServiceContent
|
@serviceContent ||= serviceInstance.PbmRetrieveServiceContent
|
||||||
end
|
end
|
||||||
|
|
||||||
# @private
|
# @private
|
||||||
|
61
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/sms.rb
vendored
Normal file
61
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/sms.rb
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# Copyright (c) 2013 VMware, Inc. All Rights Reserved.
|
||||||
|
require 'rbvmomi'
|
||||||
|
module RbVmomi
|
||||||
|
|
||||||
|
# A connection to one vSphere SMS endpoint.
|
||||||
|
# @see #serviceInstance
|
||||||
|
class SMS < Connection
|
||||||
|
# Connect to a vSphere SMS endpoint
|
||||||
|
#
|
||||||
|
# @param [VIM] Connection to main vSphere API endpoint
|
||||||
|
# @param [Hash] opts The options hash.
|
||||||
|
# @option opts [String] :host Host to connect to.
|
||||||
|
# @option opts [Numeric] :port (443) Port to connect to.
|
||||||
|
# @option opts [Boolean] :ssl (true) Whether to use SSL.
|
||||||
|
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
|
||||||
|
# @option opts [String] :path (/sms/sdk) SDK endpoint path.
|
||||||
|
# @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
|
||||||
|
def self.connect vim, opts = {}
|
||||||
|
fail unless opts.is_a? Hash
|
||||||
|
opts[:host] = vim.host
|
||||||
|
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
|
||||||
|
opts[:insecure] ||= true
|
||||||
|
opts[:port] ||= (opts[:ssl] ? 443 : 80)
|
||||||
|
opts[:path] ||= '/sms/sdk'
|
||||||
|
opts[:ns] ||= 'urn:sms'
|
||||||
|
rev_given = opts[:rev] != nil
|
||||||
|
opts[:rev] = '4.0' unless rev_given
|
||||||
|
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
|
||||||
|
|
||||||
|
new(opts).tap do |sms|
|
||||||
|
sms.vcSessionCookie = vim.cookie.split('"')[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def vcSessionCookie= cookie
|
||||||
|
@vcSessionCookie = cookie
|
||||||
|
end
|
||||||
|
|
||||||
|
def rev= x
|
||||||
|
super
|
||||||
|
@serviceContent = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return the ServiceInstance
|
||||||
|
#
|
||||||
|
# The ServiceInstance is the root of the vSphere inventory.
|
||||||
|
def serviceInstance
|
||||||
|
@serviceInstance ||= VIM::SmsServiceInstance self, 'ServiceInstance'
|
||||||
|
end
|
||||||
|
|
||||||
|
# @private
|
||||||
|
def pretty_print pp
|
||||||
|
pp.text "SMS(#{@opts[:host]})"
|
||||||
|
end
|
||||||
|
|
||||||
|
add_extension_dir File.join(File.dirname(__FILE__), "sms")
|
||||||
|
load_vmodl(ENV['VMODL'] || File.join(File.dirname(__FILE__), "../../vmodl.db"))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
7
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/sms/SmsStorageManager.rb
vendored
Normal file
7
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/sms/SmsStorageManager.rb
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
class RbVmomi::SMS::SmsStorageManager
|
||||||
|
|
||||||
|
def RegisterProvider_Task2 providerSpec
|
||||||
|
self.RegisterProvider_Task providerSpec
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -14,7 +14,7 @@ class RbVmomi::TrivialSoap
|
|||||||
@opts = opts
|
@opts = opts
|
||||||
return unless @opts[:host] # for testcases
|
return unless @opts[:host] # for testcases
|
||||||
@debug = @opts[:debug]
|
@debug = @opts[:debug]
|
||||||
@cookie = nil
|
@cookie = @opts[:cookie]
|
||||||
@lock = Mutex.new
|
@lock = Mutex.new
|
||||||
@http = nil
|
@http = nil
|
||||||
restart_http
|
restart_http
|
||||||
@ -36,7 +36,6 @@ class RbVmomi::TrivialSoap
|
|||||||
puts ex.backtrace.join("\n")
|
puts ex.backtrace.join("\n")
|
||||||
end
|
end
|
||||||
@http = Net::HTTP.new(@opts[:host], @opts[:port], @opts[:proxyHost], @opts[:proxyPort])
|
@http = Net::HTTP.new(@opts[:host], @opts[:port], @opts[:proxyHost], @opts[:proxyPort])
|
||||||
|
|
||||||
if @opts[:ssl]
|
if @opts[:ssl]
|
||||||
require 'net/https'
|
require 'net/https'
|
||||||
@http.use_ssl = true
|
@http.use_ssl = true
|
||||||
@ -45,10 +44,6 @@ class RbVmomi::TrivialSoap
|
|||||||
else
|
else
|
||||||
@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||||
end
|
end
|
||||||
|
|
||||||
@http.ssl_version = :TLSv1
|
|
||||||
|
|
||||||
|
|
||||||
@http.cert = OpenSSL::X509::Certificate.new(@opts[:cert]) if @opts[:cert]
|
@http.cert = OpenSSL::X509::Certificate.new(@opts[:cert]) if @opts[:cert]
|
||||||
@http.key = OpenSSL::PKey::RSA.new(@opts[:key]) if @opts[:key]
|
@http.key = OpenSSL::PKey::RSA.new(@opts[:key]) if @opts[:key]
|
||||||
end
|
end
|
||||||
|
@ -52,7 +52,7 @@ class TypeLoader
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get name
|
def get name
|
||||||
fail unless name.is_a? String
|
fail "name '#{name}' is #{name.class} expecting String" unless name.is_a? String
|
||||||
|
|
||||||
first_char = name[0].chr
|
first_char = name[0].chr
|
||||||
if first_char.downcase == first_char
|
if first_char.downcase == first_char
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
# computer (cluster), resource pool, vm_folder and datastore. Currently once
|
# computer (cluster), resource pool, vm_folder and datastore. Currently once
|
||||||
# computed, a new updated placement can't be generated.
|
# computed, a new updated placement can't be generated.
|
||||||
class AdmissionControlledResourceScheduler
|
class AdmissionControlledResourceScheduler
|
||||||
|
attr_reader :rp
|
||||||
|
|
||||||
def initialize vim, opts = {}
|
def initialize vim, opts = {}
|
||||||
@vim = vim
|
@vim = vim
|
||||||
|
|
||||||
@ -330,6 +332,10 @@ class AdmissionControlledResourceScheduler
|
|||||||
# datastore without much intelligence, as long as it passes admission control.
|
# datastore without much intelligence, as long as it passes admission control.
|
||||||
# @return [VIM::Datastore] Chosen datastore
|
# @return [VIM::Datastore] Chosen datastore
|
||||||
def datastore placementHint = nil
|
def datastore placementHint = nil
|
||||||
|
if @datastore
|
||||||
|
return @datastore
|
||||||
|
end
|
||||||
|
|
||||||
pod_datastores = pick_computer.datastore & datastores
|
pod_datastores = pick_computer.datastore & datastores
|
||||||
|
|
||||||
eligible = pod_datastores.select do |ds|
|
eligible = pod_datastores.select do |ds|
|
||||||
|
@ -102,6 +102,13 @@ class CachedOvfDeployer
|
|||||||
# simplicity this function assumes we need to read the OVF file
|
# simplicity this function assumes we need to read the OVF file
|
||||||
# ourselves to know the names, and we map all of them to the same
|
# ourselves to know the names, and we map all of them to the same
|
||||||
# VIM::Network.
|
# VIM::Network.
|
||||||
|
|
||||||
|
# If we're handling a file:// URI we need to strip the scheme as open-uri
|
||||||
|
# can't handle them.
|
||||||
|
if URI(ovf_url).scheme == "file" && URI(ovf_url).host.nil?
|
||||||
|
ovf_url = URI(ovf_url).path
|
||||||
|
end
|
||||||
|
|
||||||
ovf = open(ovf_url, 'r'){|io| Nokogiri::XML(io.read)}
|
ovf = open(ovf_url, 'r'){|io| Nokogiri::XML(io.read)}
|
||||||
ovf.remove_namespaces!
|
ovf.remove_namespaces!
|
||||||
networks = ovf.xpath('//NetworkSection/Network').map{|x| x['name']}
|
networks = ovf.xpath('//NetworkSection/Network').map{|x| x['name']}
|
||||||
@ -178,11 +185,10 @@ class CachedOvfDeployer
|
|||||||
# prepare it for (linked) cloning and mark it as a template to signal
|
# prepare it for (linked) cloning and mark it as a template to signal
|
||||||
# we are done.
|
# we are done.
|
||||||
if !wait_for_template
|
if !wait_for_template
|
||||||
vm.add_delta_disk_layer_on_all_disks
|
config = opts[:config] || {}
|
||||||
if opts[:config]
|
config = vm.update_spec_add_delta_disk_layer_on_all_disks(config)
|
||||||
# XXX: Should we add a version that does retries?
|
# XXX: Should we add a version that does retries?
|
||||||
vm.ReconfigVM_Task(:spec => opts[:config]).wait_for_completion
|
vm.ReconfigVM_Task(:spec => config).wait_for_completion
|
||||||
end
|
|
||||||
vm.MarkAsTemplate
|
vm.MarkAsTemplate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -207,7 +213,7 @@ class CachedOvfDeployer
|
|||||||
# or nil
|
# or nil
|
||||||
def lookup_template template_name
|
def lookup_template template_name
|
||||||
template_path = "#{template_name}-#{@computer.name}"
|
template_path = "#{template_name}-#{@computer.name}"
|
||||||
template = @template_folder.traverse(template_path, VIM::VirtualMachine)
|
template = @template_folder.traverse(template_path, RbVmomi::VIM::VirtualMachine)
|
||||||
if template
|
if template
|
||||||
config = template.config
|
config = template.config
|
||||||
is_template = config && config.template
|
is_template = config && config.template
|
||||||
|
@ -93,7 +93,8 @@ class PerfAggregator
|
|||||||
RbVmomi::VIM.SelectionSpec(:name => 'tsFolder'),
|
RbVmomi::VIM.SelectionSpec(:name => 'tsFolder'),
|
||||||
RbVmomi::VIM.SelectionSpec(:name => 'tsDatacenterVmFolder'),
|
RbVmomi::VIM.SelectionSpec(:name => 'tsDatacenterVmFolder'),
|
||||||
RbVmomi::VIM.SelectionSpec(:name => 'tsDatacenterHostFolder'),
|
RbVmomi::VIM.SelectionSpec(:name => 'tsDatacenterHostFolder'),
|
||||||
RbVmomi::VIM.SelectionSpec(:name => 'tsCluster'),
|
RbVmomi::VIM.SelectionSpec(:name => 'tsClusterRP'),
|
||||||
|
RbVmomi::VIM.SelectionSpec(:name => 'tsClusterHost'),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
RbVmomi::VIM.TraversalSpec(
|
RbVmomi::VIM.TraversalSpec(
|
||||||
@ -115,7 +116,7 @@ class PerfAggregator
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
RbVmomi::VIM.TraversalSpec(
|
RbVmomi::VIM.TraversalSpec(
|
||||||
:name => 'tsCluster',
|
:name => 'tsClusterRP',
|
||||||
:type => 'ClusterComputeResource',
|
:type => 'ClusterComputeResource',
|
||||||
:path => 'resourcePool',
|
:path => 'resourcePool',
|
||||||
:skip => false,
|
:skip => false,
|
||||||
@ -123,6 +124,13 @@ class PerfAggregator
|
|||||||
RbVmomi::VIM.SelectionSpec(:name => 'tsRP'),
|
RbVmomi::VIM.SelectionSpec(:name => 'tsRP'),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
RbVmomi::VIM.TraversalSpec(
|
||||||
|
:name => 'tsClusterHost',
|
||||||
|
:type => 'ClusterComputeResource',
|
||||||
|
:path => 'host',
|
||||||
|
:skip => false,
|
||||||
|
:selectSet => []
|
||||||
|
),
|
||||||
RbVmomi::VIM.TraversalSpec(
|
RbVmomi::VIM.TraversalSpec(
|
||||||
:name => 'tsRP',
|
:name => 'tsRP',
|
||||||
:type => 'ResourcePool',
|
:type => 'ResourcePool',
|
||||||
@ -141,6 +149,7 @@ class PerfAggregator
|
|||||||
:pathSet => ['name', 'parent', 'summary.effectiveCpu', 'summary.effectiveMemory']
|
:pathSet => ['name', 'parent', 'summary.effectiveCpu', 'summary.effectiveMemory']
|
||||||
},
|
},
|
||||||
{ :type => 'ResourcePool', :pathSet => ['name', 'parent'] },
|
{ :type => 'ResourcePool', :pathSet => ['name', 'parent'] },
|
||||||
|
{ :type => 'HostSystem', :pathSet => ['name', 'parent', 'runtime.connectionState'] },
|
||||||
{ :type => 'VirtualMachine', :pathSet => vm_prop_names },
|
{ :type => 'VirtualMachine', :pathSet => vm_prop_names },
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -316,9 +325,18 @@ class PerfAggregator
|
|||||||
'virtualDisk.totalWriteLatency' => :avg_ignore_zero,
|
'virtualDisk.totalWriteLatency' => :avg_ignore_zero,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
host_perf_metrics = opts[:host_perf_metrics]
|
||||||
|
if !host_perf_metrics
|
||||||
|
host_perf_metrics = {
|
||||||
|
'cpu.usage' => :avg,
|
||||||
|
'mem.usage' => :avg,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
vms_props, inventory = all_inventory_flat root_folder, prop_names
|
vms_props, inventory = all_inventory_flat root_folder, prop_names
|
||||||
vms = vms_props.keys
|
vms = vms_props.keys
|
||||||
|
|
||||||
|
hosts_props = inventory.select{|k, v| k.is_a?(VIM::HostSystem)}
|
||||||
|
|
||||||
conn = root_folder._connection
|
conn = root_folder._connection
|
||||||
sc = conn.serviceContent
|
sc = conn.serviceContent
|
||||||
@ -349,8 +367,31 @@ class PerfAggregator
|
|||||||
end
|
end
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
connected_hosts = hosts_props.select do |k,v|
|
||||||
|
v['runtime.connectionState'] != "disconnected"
|
||||||
|
end
|
||||||
|
if connected_hosts.length > 0
|
||||||
|
hosts_stats = pm.retrieve_stats(
|
||||||
|
connected_hosts.keys, host_perf_metrics.keys,
|
||||||
|
:max_samples => 3
|
||||||
|
)
|
||||||
|
end
|
||||||
|
hosts_props.each do |host, props|
|
||||||
|
if !connected_hosts[host]
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
stats = hosts_stats[host] || {}
|
||||||
|
stats = stats[:metrics] || {}
|
||||||
|
stats = _aggregate_metrics [stats], host_perf_metrics
|
||||||
|
props.merge!(stats)
|
||||||
|
end
|
||||||
|
|
||||||
vms_props.each do |vm, props|
|
vms_props.each do |vm, props|
|
||||||
|
if !connected_vms.member?(vm)
|
||||||
|
next
|
||||||
|
end
|
||||||
props['num.vm'] = 1
|
props['num.vm'] = 1
|
||||||
powered_on = (props['runtime.powerState'] == 'poweredOn')
|
powered_on = (props['runtime.powerState'] == 'poweredOn')
|
||||||
props['num.poweredonvm'] = powered_on ? 1 : 0
|
props['num.poweredonvm'] = powered_on ? 1 : 0
|
||||||
@ -392,25 +433,35 @@ class PerfAggregator
|
|||||||
props['vc_uuid'] = vc_uuid
|
props['vc_uuid'] = vc_uuid
|
||||||
end
|
end
|
||||||
|
|
||||||
[vms_props, inventory]
|
[vms_props, inventory, hosts_props]
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect_info_on_all_vms root_folders, opts = {}
|
def collect_info_on_all_vms root_folders, opts = {}
|
||||||
log "Fetching information from all VCs ..."
|
log "Fetching information from all VCs ..."
|
||||||
vms_props = {}
|
vms_props = {}
|
||||||
|
hosts_props = {}
|
||||||
inventory = {}
|
inventory = {}
|
||||||
lock = Mutex.new
|
lock = Mutex.new
|
||||||
root_folders.map do |root_folder|
|
root_folders.map do |root_folder|
|
||||||
Thread.new do
|
Thread.new do
|
||||||
single_vms_props, single_inventory =
|
begin
|
||||||
_collect_info_on_all_vms_single(root_folder, opts)
|
single_vms_props, single_inventory, single_hosts_props =
|
||||||
|
_collect_info_on_all_vms_single(root_folder, opts)
|
||||||
lock.synchronize do
|
|
||||||
vms_props.merge!(single_vms_props)
|
lock.synchronize do
|
||||||
if inventory['root']
|
vms_props.merge!(single_vms_props)
|
||||||
single_inventory['root']['children'] += inventory['root']['children']
|
if inventory['root']
|
||||||
|
single_inventory['root']['children'] += inventory['root']['children']
|
||||||
|
end
|
||||||
|
inventory.merge!(single_inventory)
|
||||||
|
hosts_props.merge!(single_hosts_props)
|
||||||
end
|
end
|
||||||
inventory.merge!(single_inventory)
|
rescue Exception => ex
|
||||||
|
log "#{ex.class}: #{ex.message}"
|
||||||
|
ex.backtrace.each do |line|
|
||||||
|
log line
|
||||||
|
end
|
||||||
|
raise
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end.each{|t| t.join}
|
end.each{|t| t.join}
|
||||||
@ -418,6 +469,7 @@ class PerfAggregator
|
|||||||
log "Make data marshal friendly ..."
|
log "Make data marshal friendly ..."
|
||||||
inventory = _make_marshal_friendly(inventory)
|
inventory = _make_marshal_friendly(inventory)
|
||||||
vms_props = _make_marshal_friendly(vms_props)
|
vms_props = _make_marshal_friendly(vms_props)
|
||||||
|
hosts_props = _make_marshal_friendly(hosts_props)
|
||||||
|
|
||||||
log "Perform external post processing ..."
|
log "Perform external post processing ..."
|
||||||
if @vm_processing_callback
|
if @vm_processing_callback
|
||||||
@ -442,7 +494,11 @@ class PerfAggregator
|
|||||||
@inventory = inventory
|
@inventory = inventory
|
||||||
@vms_props = vms_props
|
@vms_props = vms_props
|
||||||
|
|
||||||
nil
|
{
|
||||||
|
'inventory' => inventory,
|
||||||
|
'vms_props' => vms_props,
|
||||||
|
'hosts_props' => hosts_props,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def _make_marshal_friendly hash
|
def _make_marshal_friendly hash
|
||||||
|
@ -13,6 +13,7 @@ class VIM < Connection
|
|||||||
# @option opts [Numeric] :port (443) Port to connect to.
|
# @option opts [Numeric] :port (443) Port to connect to.
|
||||||
# @option opts [Boolean] :ssl (true) Whether to use SSL.
|
# @option opts [Boolean] :ssl (true) Whether to use SSL.
|
||||||
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
|
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
|
||||||
|
# @option opts [String] :cookie If set, use cookie to connect instead of user/password
|
||||||
# @option opts [String] :user (root) Username.
|
# @option opts [String] :user (root) Username.
|
||||||
# @option opts [String] :password Password.
|
# @option opts [String] :password Password.
|
||||||
# @option opts [String] :path (/sdk) SDK endpoint path.
|
# @option opts [String] :path (/sdk) SDK endpoint path.
|
||||||
@ -20,6 +21,7 @@ class VIM < Connection
|
|||||||
def self.connect opts
|
def self.connect opts
|
||||||
fail unless opts.is_a? Hash
|
fail unless opts.is_a? Hash
|
||||||
fail "host option required" unless opts[:host]
|
fail "host option required" unless opts[:host]
|
||||||
|
opts[:cookie] ||= nil
|
||||||
opts[:user] ||= 'root'
|
opts[:user] ||= 'root'
|
||||||
opts[:password] ||= ''
|
opts[:password] ||= ''
|
||||||
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
|
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
|
||||||
@ -32,10 +34,12 @@ class VIM < Connection
|
|||||||
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
|
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
|
||||||
|
|
||||||
new(opts).tap do |vim|
|
new(opts).tap do |vim|
|
||||||
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
|
unless opts[:cookie]
|
||||||
|
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
|
||||||
|
end
|
||||||
unless rev_given
|
unless rev_given
|
||||||
rev = vim.serviceContent.about.apiVersion
|
rev = vim.serviceContent.about.apiVersion
|
||||||
vim.rev = [rev, '5.0'].min
|
vim.rev = [rev, '5.5'].min
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -45,7 +49,7 @@ class VIM < Connection
|
|||||||
self.cookie = nil
|
self.cookie = nil
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def rev= x
|
def rev= x
|
||||||
super
|
super
|
||||||
@serviceContent = nil
|
@serviceContent = nil
|
||||||
@ -85,11 +89,36 @@ class VIM < Connection
|
|||||||
def pretty_print pp
|
def pretty_print pp
|
||||||
pp.text "VIM(#{@opts[:host]})"
|
pp.text "VIM(#{@opts[:host]})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def instanceUuid
|
def instanceUuid
|
||||||
serviceContent.about.instanceUuid
|
serviceContent.about.instanceUuid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_log_lines logKey, lines=5, start=nil, host=nil
|
||||||
|
diagMgr = self.serviceContent.diagnosticManager
|
||||||
|
if !start
|
||||||
|
log = diagMgr.BrowseDiagnosticLog(:host => host, :key => logKey, :start => 999999999)
|
||||||
|
lineEnd = log.lineEnd
|
||||||
|
start = lineEnd - lines
|
||||||
|
end
|
||||||
|
start = start < 0 ? 0 : start
|
||||||
|
log = diagMgr.BrowseDiagnosticLog(:host => host, :key => logKey, :start => start)
|
||||||
|
if log.lineText.size > 0
|
||||||
|
[log.lineText.slice(-lines, log.lineText.size), log.lineEnd]
|
||||||
|
else
|
||||||
|
[log.lineText, log.lineEnd]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_log_keys host=nil
|
||||||
|
diagMgr = self.serviceContent.diagnosticManager
|
||||||
|
keys = []
|
||||||
|
diagMgr.QueryDescriptions(:host => host).each do |desc|
|
||||||
|
keys << "#{desc.key}"
|
||||||
|
end
|
||||||
|
keys
|
||||||
|
end
|
||||||
|
|
||||||
add_extension_dir File.join(File.dirname(__FILE__), "vim")
|
add_extension_dir File.join(File.dirname(__FILE__), "vim")
|
||||||
(ENV['RBVMOMI_VIM_EXTENSION_PATH']||'').split(':').each { |dir| add_extension_dir dir }
|
(ENV['RBVMOMI_VIM_EXTENSION_PATH']||'').split(':').each { |dir| add_extension_dir dir }
|
||||||
|
|
||||||
|
@ -14,3 +14,4 @@ class RbVmomi::VIM::Datacenter
|
|||||||
vmFolder.traverse path, RbVmomi::VIM::VirtualMachine
|
vmFolder.traverse path, RbVmomi::VIM::VirtualMachine
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,61 +35,6 @@ class RbVmomi::VIM::Datastore
|
|||||||
fail "download failed" unless $?.success?
|
fail "download failed" unless $?.success?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Download a file from this datastore.
|
|
||||||
# @param remote_path [String] Source path on the datastore.
|
|
||||||
# @param local_path [String] Destination path on the local machine.
|
|
||||||
# @return [void]
|
|
||||||
def download_to_stdout remote_path
|
|
||||||
url = "http#{_connection.http.use_ssl? ? 's' : ''}://#{_connection.http.address}:#{_connection.http.port}#{mkuripath(remote_path)}"
|
|
||||||
|
|
||||||
pid = spawn CURLBIN, "-k", '--noproxy', '*', '-f',
|
|
||||||
"-b", _connection.cookie,
|
|
||||||
url
|
|
||||||
|
|
||||||
|
|
||||||
Process.waitpid(pid, 0)
|
|
||||||
fail "download failed" unless $?.success?
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_descriptor? remote_path
|
|
||||||
url = "http#{_connection.http.use_ssl? ? 's' : ''}://#{_connection.http.address}:#{_connection.http.port}#{mkuripath(remote_path)}"
|
|
||||||
|
|
||||||
rout, wout = IO.pipe
|
|
||||||
|
|
||||||
pid = spawn CURLBIN, "-I", "-k", '--noproxy', '*', '-f',
|
|
||||||
"-b", _connection.cookie,
|
|
||||||
url,
|
|
||||||
:out => wout,
|
|
||||||
:err => '/dev/null'
|
|
||||||
|
|
||||||
Process.waitpid(pid, 0)
|
|
||||||
fail "read image header failed" unless $?.success?
|
|
||||||
|
|
||||||
wout.close
|
|
||||||
size = rout.readlines.select{|l| l.start_with?("Content-Length")}[0].sub("Content-Length: ","")
|
|
||||||
rout.close
|
|
||||||
size.chomp.to_i < 4096 # If <4k, then is a descriptor
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_text_file remote_path
|
|
||||||
url = "http#{_connection.http.use_ssl? ? 's' : ''}://#{_connection.http.address}:#{_connection.http.port}#{mkuripath(remote_path)}"
|
|
||||||
|
|
||||||
rout, wout = IO.pipe
|
|
||||||
pid = spawn CURLBIN, "-k", '--noproxy', '*', '-f',
|
|
||||||
"-b", _connection.cookie,
|
|
||||||
url,
|
|
||||||
:out => wout,
|
|
||||||
:err => '/dev/null'
|
|
||||||
|
|
||||||
Process.waitpid(pid, 0)
|
|
||||||
fail "get text file failed" unless $?.success?
|
|
||||||
|
|
||||||
wout.close
|
|
||||||
output = rout.readlines
|
|
||||||
rout.close
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
# Upload a file to this datastore.
|
# Upload a file to this datastore.
|
||||||
# @param remote_path [String] Destination path on the datastore.
|
# @param remote_path [String] Destination path on the datastore.
|
||||||
# @param local_path [String] Source path on the local machine.
|
# @param local_path [String] Source path on the local machine.
|
||||||
|
@ -53,6 +53,16 @@ class RbVmomi::VIM::Folder
|
|||||||
x if x.is_a? type
|
x if x.is_a? type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Retrieve a managed entity by inventory path.
|
||||||
|
# @param path [String] A path of the form "My Folder/My Datacenter/vm/Discovered VM/VM1"
|
||||||
|
# @return [VIM::ManagedEntity]
|
||||||
|
def findByInventoryPath path
|
||||||
|
propSpecs = {
|
||||||
|
:entity => self, :inventoryPath => path
|
||||||
|
}
|
||||||
|
x = _connection.searchIndex.FindByInventoryPath(propSpecs)
|
||||||
|
end
|
||||||
|
|
||||||
# Alias to <tt>traverse path, type, true</tt>
|
# Alias to <tt>traverse path, type, true</tt>
|
||||||
# @see #traverse
|
# @see #traverse
|
||||||
def traverse! path, type=Object
|
def traverse! path, type=Object
|
||||||
|
@ -35,7 +35,12 @@ class RbVmomi::VIM::ManagedObject
|
|||||||
:type => self.class.wsdl_name
|
:type => self.class.wsdl_name
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
_connection.propertyCollector.RetrieveProperties(:specSet => [spec])[0].to_hash
|
ret = _connection.propertyCollector.RetrieveProperties(:specSet => [spec])
|
||||||
|
if ret && ret.length > 0
|
||||||
|
ret[0].to_hash
|
||||||
|
else
|
||||||
|
{}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Efficiently retrieve multiple properties from an object.
|
# Efficiently retrieve multiple properties from an object.
|
||||||
|
@ -48,7 +48,16 @@ class RbVmomi::VIM::OvfManager
|
|||||||
result.warning.each{|x| puts "OVF Warning: #{x.localizedMessage.chomp}" }
|
result.warning.each{|x| puts "OVF Warning: #{x.localizedMessage.chomp}" }
|
||||||
end
|
end
|
||||||
|
|
||||||
nfcLease = opts[:resourcePool].ImportVApp(:spec => result.importSpec,
|
importSpec = result.importSpec
|
||||||
|
if importSpec && importSpec.instantiationOst && importSpec.instantiationOst.child
|
||||||
|
importSpec.instantiationOst.child.each do |child|
|
||||||
|
child.section.map do |section|
|
||||||
|
section.xml = _handle_ost(section.xml, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
nfcLease = opts[:resourcePool].ImportVApp(:spec => importSpec,
|
||||||
:folder => opts[:vmFolder],
|
:folder => opts[:vmFolder],
|
||||||
:host => opts[:host])
|
:host => opts[:host])
|
||||||
|
|
||||||
@ -56,30 +65,70 @@ class RbVmomi::VIM::OvfManager
|
|||||||
raise nfcLease.error if nfcLease.state == "error"
|
raise nfcLease.error if nfcLease.state == "error"
|
||||||
begin
|
begin
|
||||||
nfcLease.HttpNfcLeaseProgress(:percent => 5)
|
nfcLease.HttpNfcLeaseProgress(:percent => 5)
|
||||||
|
timeout, = nfcLease.collect 'info.leaseTimeout'
|
||||||
|
puts "DEBUG: Timeout: #{timeout}"
|
||||||
|
if timeout < 4 * 60
|
||||||
|
puts "WARNING: OVF upload NFC lease timeout less than 4 minutes"
|
||||||
|
end
|
||||||
progress = 5.0
|
progress = 5.0
|
||||||
result.fileItem.each do |fileItem|
|
result.fileItem.each do |fileItem|
|
||||||
deviceUrl = nfcLease.info.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
|
leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
|
||||||
|
# Retry nfcLease.collect because of PR 969599:
|
||||||
|
# If retrying property collector works, this means there is a network
|
||||||
|
# or VC overloading problem.
|
||||||
|
retrynum = 5
|
||||||
|
i = 1
|
||||||
|
while i <= retrynum && !leaseState
|
||||||
|
puts "Retrying at iteration #{i}"
|
||||||
|
sleep 1
|
||||||
|
leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
if leaseState != "ready"
|
||||||
|
raise "NFC lease is no longer ready: #{leaseState}: #{leaseError}"
|
||||||
|
end
|
||||||
|
if leaseInfo == nil
|
||||||
|
raise "NFC lease disappeared?"
|
||||||
|
end
|
||||||
|
deviceUrl = leaseInfo.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
|
||||||
if !deviceUrl
|
if !deviceUrl
|
||||||
raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'"
|
raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
# XXX handle file:// URIs
|
|
||||||
ovfFilename = opts[:uri].to_s
|
ovfFilename = opts[:uri].to_s
|
||||||
tmp = ovfFilename.split(/\//)
|
tmp = ovfFilename.split(/\//)
|
||||||
tmp.pop
|
tmp.pop
|
||||||
tmp << fileItem.path
|
tmp << fileItem.path
|
||||||
filename = tmp.join("/")
|
filename = tmp.join("/")
|
||||||
|
|
||||||
|
# If filename doesn't have a URI scheme, we're considering it a local file
|
||||||
|
if URI(filename).scheme.nil?
|
||||||
|
filename = "file://" + filename
|
||||||
|
end
|
||||||
|
|
||||||
method = fileItem.create ? "PUT" : "POST"
|
method = fileItem.create ? "PUT" : "POST"
|
||||||
|
|
||||||
keepAliveThread = Thread.new do
|
keepAliveThread = Thread.new do
|
||||||
while true
|
while true
|
||||||
sleep 2 * 60
|
|
||||||
nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
|
nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
|
||||||
|
sleep 1 * 60
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
href = deviceUrl.url.gsub("*", opts[:host].config.network.vnic[0].spec.ip.ipAddress)
|
i = 1
|
||||||
|
ip = nil
|
||||||
|
begin
|
||||||
|
begin
|
||||||
|
puts "Iteration #{i}: Trying to get host's IP address ..."
|
||||||
|
ip = opts[:host].config.network.vnic[0].spec.ip.ipAddress
|
||||||
|
rescue Exception=>e
|
||||||
|
puts "Iteration #{i}: Couldn't get host's IP address: #{e}"
|
||||||
|
end
|
||||||
|
sleep 1
|
||||||
|
i += 1
|
||||||
|
end while i <= 5 && !ip
|
||||||
|
raise "Couldn't get host's IP address" unless ip
|
||||||
|
href = deviceUrl.url.gsub("*", ip)
|
||||||
downloadCmd = "#{CURLBIN} -L '#{URI::escape(filename)}'"
|
downloadCmd = "#{CURLBIN} -L '#{URI::escape(filename)}'"
|
||||||
uploadCmd = "#{CURLBIN} -Ss -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' '#{URI::escape(href)}'"
|
uploadCmd = "#{CURLBIN} -Ss -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' '#{URI::escape(href)}'"
|
||||||
# Previously we used to append "-H 'Content-Length: #{fileItem.size}'"
|
# Previously we used to append "-H 'Content-Length: #{fileItem.size}'"
|
||||||
@ -96,12 +145,56 @@ class RbVmomi::VIM::OvfManager
|
|||||||
end
|
end
|
||||||
|
|
||||||
nfcLease.HttpNfcLeaseProgress(:percent => 100)
|
nfcLease.HttpNfcLeaseProgress(:percent => 100)
|
||||||
vm = nfcLease.info.entity
|
raise nfcLease.error if nfcLease.state == "error"
|
||||||
nfcLease.HttpNfcLeaseComplete
|
i = 1
|
||||||
|
vm = nil
|
||||||
|
begin
|
||||||
|
begin
|
||||||
|
puts "Iteration #{i}: Trying to access nfcLease.info.entity ..."
|
||||||
|
vm = nfcLease.info.entity
|
||||||
|
rescue Exception=>e
|
||||||
|
puts "Iteration #{i}: Couldn't access nfcLease.info.entity: #{e}"
|
||||||
|
end
|
||||||
|
sleep 1
|
||||||
|
i += 1
|
||||||
|
end while i <= 5 && !vm
|
||||||
|
raise "Couldn't access nfcLease.info.entity" unless vm
|
||||||
|
|
||||||
|
# Ignore sporadic connection errors caused by PR 1019166..
|
||||||
|
# Three attempts are made to execute HttpNfcLeaseComplete.
|
||||||
|
# Not critical if none goes through, as long as vm is obtained
|
||||||
|
#
|
||||||
|
# TODO: find the reason why HttpNfcLeaseComplete gets a wrong
|
||||||
|
# response (RetrievePropertiesResponse)
|
||||||
|
i = 0
|
||||||
|
begin
|
||||||
|
nfcLease.HttpNfcLeaseComplete
|
||||||
|
puts "HttpNfcLeaseComplete succeeded"
|
||||||
|
rescue RbVmomi::VIM::InvalidState
|
||||||
|
puts "HttpNfcLeaseComplete already finished.."
|
||||||
|
rescue Exception => e
|
||||||
|
puts "HttpNfcLeaseComplete failed at iteration #{i} with exception: #{e}"
|
||||||
|
i += 1
|
||||||
|
retry if i < 3
|
||||||
|
puts "Giving up HttpNfcLeaseComplete.."
|
||||||
|
end
|
||||||
vm
|
vm
|
||||||
end
|
end
|
||||||
rescue Exception
|
rescue Exception
|
||||||
(nfcLease.HttpNfcLeaseAbort rescue nil) if nfcLease
|
(nfcLease.HttpNfcLeaseAbort rescue nil) if nfcLease
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _handle_ost ost, opts = {}
|
||||||
|
ost = Nokogiri::XML(ost)
|
||||||
|
if opts[:vservice] == ['com.vmware.vim.vsm:extension_vservice']
|
||||||
|
ost.xpath('//vmw:Annotations/vmw:Providers/vmw:Provider').each do |x|
|
||||||
|
x['vmw:selected'] = 'selected'
|
||||||
|
end
|
||||||
|
ost.xpath('//vmw:Annotations/vmw:Providers').each do |x|
|
||||||
|
x['vmw:selected'] = 'com.vmware.vim.vsm:extension_vservice'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ost.to_s
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -46,13 +46,21 @@ class RbVmomi::VIM::PerformanceManager
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
metric_ids = metrics.map do |x|
|
instances = opts[:instance] || '*'
|
||||||
|
if !instances.is_a?(Array)
|
||||||
|
instances = [instances]
|
||||||
|
end
|
||||||
|
metric_ids = []
|
||||||
|
metrics.each do |x|
|
||||||
counter = perfcounter_hash[x]
|
counter = perfcounter_hash[x]
|
||||||
if !counter
|
if !counter
|
||||||
pp perfcounter_hash.keys
|
pp perfcounter_hash.keys
|
||||||
fail "Counter for #{x} couldn't be found"
|
fail "Counter for #{x} couldn't be found"
|
||||||
end
|
end
|
||||||
RbVmomi::VIM::PerfMetricId(:counterId => counter.key, :instance => '*')
|
instances.each do |instance|
|
||||||
|
metric_ids << RbVmomi::VIM::PerfMetricId(:counterId => counter.key,
|
||||||
|
:instance => instance)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
query_specs = objects.map do |obj|
|
query_specs = objects.map do |obj|
|
||||||
RbVmomi::VIM::PerfQuerySpec({
|
RbVmomi::VIM::PerfQuerySpec({
|
||||||
@ -65,19 +73,36 @@ class RbVmomi::VIM::PerformanceManager
|
|||||||
end
|
end
|
||||||
stats = QueryPerf(:querySpec => query_specs)
|
stats = QueryPerf(:querySpec => query_specs)
|
||||||
|
|
||||||
Hash[stats.map do |res|
|
if !opts[:multi_instance]
|
||||||
[
|
Hash[stats.map do |res|
|
||||||
res.entity,
|
[
|
||||||
{
|
res.entity,
|
||||||
:sampleInfo => res.sampleInfo,
|
{
|
||||||
:metrics => Hash[res.value.map do |metric|
|
:sampleInfo => res.sampleInfo,
|
||||||
[perfcounter_idhash[metric.id.counterId].name, metric.value]
|
:metrics => Hash[res.value.map do |metric|
|
||||||
end]
|
metric_name = perfcounter_idhash[metric.id.counterId].name
|
||||||
}
|
[metric_name, metric.value]
|
||||||
]
|
end]
|
||||||
end]
|
}
|
||||||
|
]
|
||||||
|
end]
|
||||||
|
else
|
||||||
|
Hash[stats.map do |res|
|
||||||
|
[
|
||||||
|
res.entity,
|
||||||
|
{
|
||||||
|
:sampleInfo => res.sampleInfo,
|
||||||
|
:metrics => Hash[res.value.map do |metric|
|
||||||
|
metric_name = perfcounter_idhash[metric.id.counterId].name
|
||||||
|
[[metric_name, metric.id.instance], metric.value]
|
||||||
|
end]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def active_intervals
|
def active_intervals
|
||||||
intervals = historicalInterval
|
intervals = historicalInterval
|
||||||
Hash[(1..4).map { |level| [level, intervals.select { |x| x.enabled && x.level >= level }] }]
|
Hash[(1..4).map { |level| [level, intervals.select { |x| x.enabled && x.level >= level }] }]
|
||||||
|
@ -34,26 +34,41 @@ class RbVmomi::VIM::VirtualMachine
|
|||||||
def add_delta_disk_layer_on_all_disks
|
def add_delta_disk_layer_on_all_disks
|
||||||
devices, = self.collect 'config.hardware.device'
|
devices, = self.collect 'config.hardware.device'
|
||||||
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
|
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
|
||||||
# XXX: Should create a single reconfig spec instead of one per disk
|
spec = update_spec_add_delta_disk_layer_on_all_disks
|
||||||
|
self.ReconfigVM_Task(:spec => spec).wait_for_completion
|
||||||
|
end
|
||||||
|
|
||||||
|
# Updates a passed in spec to perform the task of adding a delta disk layer
|
||||||
|
# on top of all disks. Does the same as add_delta_disk_layer_on_all_disks
|
||||||
|
# but instead of issuing the ReconfigVM_Task, it just constructs the
|
||||||
|
# spec, so that the caller can batch a couple of updates into one
|
||||||
|
# ReconfigVM_Task.
|
||||||
|
def update_spec_add_delta_disk_layer_on_all_disks spec = {}
|
||||||
|
devices, = self.collect 'config.hardware.device'
|
||||||
|
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
|
||||||
|
device_change = []
|
||||||
disks.each do |disk|
|
disks.each do |disk|
|
||||||
spec = {
|
device_change << {
|
||||||
:deviceChange => [
|
:operation => :remove,
|
||||||
{
|
:device => disk
|
||||||
:operation => :remove,
|
}
|
||||||
:device => disk
|
device_change << {
|
||||||
},
|
:operation => :add,
|
||||||
{
|
:fileOperation => :create,
|
||||||
:operation => :add,
|
:device => disk.dup.tap { |x|
|
||||||
:fileOperation => :create,
|
x.backing = x.backing.dup
|
||||||
:device => disk.dup.tap { |x|
|
x.backing.fileName = "[#{disk.backing.datastore.name}]"
|
||||||
x.backing = x.backing.dup
|
x.backing.parent = disk.backing
|
||||||
x.backing.fileName = "[#{disk.backing.datastore.name}]"
|
},
|
||||||
x.backing.parent = disk.backing
|
|
||||||
},
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
self.ReconfigVM_Task(:spec => spec).wait_for_completion
|
|
||||||
end
|
end
|
||||||
|
if spec.is_a?(RbVmomi::VIM::VirtualMachineConfigSpec)
|
||||||
|
spec.deviceChange ||= []
|
||||||
|
spec.deviceChange += device_change
|
||||||
|
else
|
||||||
|
spec[:deviceChange] ||= []
|
||||||
|
spec[:deviceChange] += device_change
|
||||||
|
end
|
||||||
|
spec
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
BIN
share/vendor/ruby/gems/rbvmomi/vmodl.db
vendored
BIN
share/vendor/ruby/gems/rbvmomi/vmodl.db
vendored
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user