The Spice Kaffein must flow

Using the Opennebula monitoring driver to populate host attributes

An example of collecting and exposing Opennebula IAAS VM host information. We use this to schedule VMs to specific hardware stacks, but the options are endless!

May 1, 2019

Opennebula is a customizable IAAS platform that sits right about in the middle of the spectrum if you took VMWare on one side and OpenStack on the other. It has just the right amount of complexity to provide a high level of customizability without necessitating its upkeep take one or more FTEs, and fits well with our requirements. If you have anywhere between a handful and 10,000 servers to manage in datacenters and satellite locations, it is definitely worth taking a look at Opennebula.

One of the customization features we leverage is the use of KVM host attributes to help drive guest provisioning scheduling decisions. By default the scheduler takes into account resource attributes like host CPU count, RAM availability, and disk size when allocating guests. Our server fleet spans a number of different hardware models and generations. So how could we go about ensuring that a particular workload goes to a specific server vendor, hardware model, or server generation?

That’s where the extensible monitoring drivers come in. Putting a monitoring driver on the central controller cluster distributes and runs the code on all hosts in the cluster, storing the standard output as a set of key-value pairs we can use later for guest scheduling (eg VENDOR=dell). Getting back to the example, we want to collect the vendor name, server model, server family, and normalized server generation.

Thankfully all of that information is available from a single command with dmidecode -t 1, so now we just have to parse that output and clean it up.

System Information
        Manufacturer: HPE
        Product Name: ProLiant DL160 Gen10
        Family: ProLiant

Since we are a Chef shop we leveraged the Chef ruby installation and its preinstalled mixlib-shellout library to process the output since we knew if would be on every host. Here is a ruby snippet that takes care of running the shell command, parsing the relevant output, and presenting it as an Opennebula-consumable set of key-value pairs. Since this branches on the manufacturer, we can adapt to the different output and naming schemes of multiple vendors.

require 'mixlib/shellout'

def print_info(name, value)
  value = value.to_s
  value = '0' if value.nil? || value.strip.empty?
  puts "#{name.upcase}=#{value.upcase}"
end

dmide = Mixlib::ShellOut.new('sudo dmidecode -t 1').run_command
dmide_out = dmide.stdout.split("\n").grep(/:/).map(&:lstrip)
dm_hash = dmide_out.map do |str|
  k, v = str.split(':')
  ks = k.strip
  vs = v.strip
  [ks, vs]
end.to_h

manufacturer = dm_hash['Manufacturer']
case manufacturer
when 'HP', 'HPE' then
  manufacturer = 'HPE'
  model = dm_hash['Product Name'].split(' ')[1]
  gen = dm_hash['Product Name'].split(' ')[-1].gsub(/[a-zA-Z]/, '')
end

print_info('MANUFACTURER', manufacturer)
print_info('MODEL', model)
print_info('GEN', gen)

In the future we may use the Ohai gem to gather more detailed information and present it in a format Opennebula can consume, but for now this is a good starting point.