tools/vim_collect_perf_history.rb
#!/usr/bin/env ruby
require File.expand_path('../config/environment', __dir__)
require 'optimist'
ARGV.shift if ARGV.first == "--" # Handle when called through script/runner
opts = Optimist.options do
opt :ip, "IP address", :type => :string, :required => true
opt :user, "User Name", :type => :string, :required => true
opt :pass, "Password", :type => :string, :required => true
opt :bypass, "Bypass broker usage", :type => :boolean
opt :dir, "Output directory", :default => "."
end
Optimist.die :ip, "is an invalid format" unless /^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$/.match?(opts[:ip])
targets = eval(ARGV.first) rescue nil
if targets.nil? || !targets.kind_of?(Array) || targets.empty?
puts "Validation Errors:"
puts " First argument must be an eval-able array of arrays of"
puts " target, interval name, start_time, end_time"
puts " Target must be a MOR, or a class/id pair in the format 'Class:id'"
puts " Example: \"[['Vm:10', 'realtime', nil, nil]]\""
exit 1
end
targets = [targets] unless targets.first.kind_of?(Array)
targets.each do |t|
# Adjust the first argument to be a MOR
if t[0].include?(':')
klass, id = t[0].split(':')
t[0] = Object.const_get(klass).find(id).ems_ref_obj
else
mor = t[0]
vim_type = case mor
when /^vm-/ then "VirtualMachine"
when /^host-/ then "HostSystem"
when /^cluster-/ then "ClusterComputerResource"
else
puts "Validation Errors:"
puts " target must be a valid MOR"
exit 1
end
t[0] = VimString.new(mor, vim_type, "ManagedObjectReference")
end
# Adjust the second argument to be a perf interval
t[1] = case t[1]
when "realtime" then "20"
when "hourly" then "7200"
else
puts "Validation Errors:"
puts " unknown interval '#{t[1]}'"
exit 1
end
end
mors = targets.collect { |t| t[0] }.uniq
def process(accessor, dir)
puts "Reading #{accessor}..."
data = yield
puts "Writing #{accessor}..."
File.open(File.join(dir, "#{accessor}.yml"), "w") { |f| f.write(data.to_yaml(:SortKeys => true)) }
data
end
dir = File.expand_path(File.join(opts[:dir], "miq_vim_perf_history"))
Dir.mkdir(dir) unless File.directory?(dir)
puts "Output in #{dir}"
begin
require 'VMwareWebService/MiqVim'
vim = MiqVim.new(:server => opts[:ip], :username => opts[:user], :password => opts[:pass])
ph = vim.getVimPerfHistory
a = :intervals
process(a, dir) { ph.send(a) }
a = :id2Counter
process(a, dir) { ph.send(a) }
a = :queryProviderSummary
process(a, dir) do
mors.each_with_object({}) do |mor, data|
puts "Reading #{a} for #{mor.inspect}..."
data.store_path(mor, ph.send(a, mor))
end
end
a = :availMetricsForEntity
metrics_data = process(a, dir) do
targets.each_with_object({}) do |(mor, interval, _start_time, _end_time), data|
puts "Reading #{a} for #{mor.inspect}, #{interval.inspect}..."
data.store_path(mor, interval, ph.send(a, mor, :intervalId => interval))
end
end
a = :queryPerfMulti
process(a, dir) do
targets.each_with_object({}) do |(mor, interval, start_time, end_time), data|
query = [{
:entity => mor,
:intervalId => interval,
:startTime => start_time,
:endTime => end_time,
:metricId => metrics_data.fetch_path(mor, interval).collect { |m| {:counterId => m["counterId"], :instance => m["instance"]} }
}]
puts "Reading #{a} for #{mor.inspect}, #{interval.inspect}, #{start_time.inspect}, #{end_time.inspect}..."
data.store_path(mor, interval, start_time, end_time, ph.send(a, query))
end
end
ensure
ph.release unless ph.nil? rescue nil
vim.release unless vim.nil? rescue nil
end