Class: BoxGrinder::LibvirtCapabilities

Inherits:
Object
  • Object
show all
Defined in:
lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb

Defined Under Namespace

Classes: Domain, Plugin

Constant Summary collapse

DEFAULT_DOMAIN_MAPPINGS =

Arrays are populated in order of precedence. Best first.

{
  :xen =>  { :bus => :xen, :virt_rank => [:xen, :linux, :hvm] },
  :kqemu => { :bus => :virtio, :virt_rank => [:hvm] },
  :kvm => { :bus => :virtio, :virt_rank => [:xen, :linux, :hvm] },
  :qemu => { :bus => :ide, :virt_rank => [:xen, :linux, :hvm] },
  :vbox => { :bus => :virtio, :virt_rank => [:hvm] },
  :vmware => { :bus => :ide, :virt_rank => [:hvm] }
}
PLUGIN_MAPPINGS =
{
  :default => { :domain_rank => [:kvm, :xen, :kqemu, :qemu] },
  :virtualbox => { :domain_rank => [:vbox] },
  :xen => { :domain_rank => [:xen] },
  :citrix => { :domain_rank => [:xen] },
  :kvm => { :domain_rank => [:kvm] },
  :vmware => { :domain_rank => [:vmware] },
  :ec2 => { :domain_rank => [:xen, :qemu] }
}
DOMAINS =
DEFAULT_DOMAIN_MAPPINGS.inject({}) do |accum, mapping|
  accum.merge(mapping.first => Domain.new(mapping.first, mapping.last[:bus], mapping.last[:virt_rank]))
end
PLUGINS =
PLUGIN_MAPPINGS.inject({}) do |accum, mapping|
  d_refs = mapping.last[:domain_rank].collect{|d| DOMAINS[d]}
  accum.merge(mapping.first => Plugin.new(mapping.first, d_refs))
end

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ LibvirtCapabilities

Returns a new instance of LibvirtCapabilities.



90
91
92
# File 'lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb', line 90

def initialize(opts={})
  @log = opts[:log] || LogHelper.new
end

Instance Method Details

#build_guest(xml) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb', line 133

def build_guest(xml)
  dom = DOMAINS[xpath_first_intern(xml, ".//domain/@type")]
  bus = 'ide'
  bus = dom.bus if dom

  OpenStruct.new({
    :domain_type => xpath_first_intern(xml, ".//domain/@type"),
    :os_type => xpath_first_intern(xml, './/os_type'),
    :bus => bus
  })
end

#determine_capabilities(conn, previous_plugin_info) ⇒ Object

Connect to the remote machine and determine the best available settings



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb', line 95

def determine_capabilities(conn, previous_plugin_info)
  plugin = get_plugin(previous_plugin_info)
  root = Nokogiri::XML.parse(conn.capabilities)
  guests = root.xpath("//guest/arch[@name='x86_64']/..")

  guests = guests.sort do |a, b|
    dom_maps = [a,b].map { |x| plugin.domain_map[xpath_first_intern(x, './/domain/@type')] }

    # Handle unknown mappings
    next resolve_unknowns(dom_maps) if dom_maps.include?(nil)

    # Compare according to domain ranking
    dom_rank = dom_maps.map { |m| m[:rank]}.reduce(:<=>)

    # Compare according to virtualisation ranking
    virt_rank = [a,b].enum_for(:each_with_index).map do |x, i|
      dom_maps[i][:domain].virt_map[xpath_first_intern(x, './/os_type')]
    end

    # Handle unknown mappings
    next resolve_unknowns(virt_rank) if virt_rank.include?(nil)

    # Domain rank first
    next dom_rank unless dom_rank == 0

    # OS type rank second
    virt_rank.reduce(:<=>)
  end
  # Favourite!
  build_guest(guests.first)
end

#get_plugin(previous_plugin_info) ⇒ Object

At present we don't have enough meta-data to work with to easily generalise, so we have to assume defaults often. This is something to improve later.



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb', line 151

def get_plugin(previous_plugin_info)
  if previous_plugin_info[:type] == :platform
    if PLUGINS.has_key?(previous_plugin_info[:name])
      @log.debug("Using #{previous_plugin_info[:name]} mapping")
      return PLUGINS[previous_plugin_info[:name]]
    else
      @log.debug("This plugin does not know what mappings to choose, so will assume default values where user values are not provided.")
    end
  end
  @log.debug("Using default domain mappings.")
  PLUGINS[:default]
end

#resolve_unknowns(pair) ⇒ Object



127
128
129
130
131
# File 'lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb', line 127

def resolve_unknowns(pair)
  return 0 if pair.first.nil? and pair.last.nil?
  return 1 if pair.first.nil?
  -1 if pair.last.nil?
end

#xpath_first_intern(xml, path) ⇒ Object



145
146
147
# File 'lib/boxgrinder-build/plugins/delivery/libvirt/libvirt-capabilities.rb', line 145

def xpath_first_intern(xml, path)
  xml.xpath(path).first.text.intern
end