lib/vagrant-libvirt/action/start_domain.rb in vagrant-libvirt-0.3.0 vs lib/vagrant-libvirt/action/start_domain.rb in vagrant-libvirt-0.4.0
- old
+ new
@@ -35,110 +35,156 @@
# XML definition manipulation
descr = libvirt_domain.xml_desc(1)
xml_descr = REXML::Document.new descr
descr_changed = false
+ # For outputting XML for comparison
+ formatter = REXML::Formatters::Pretty.new
+
# additional disk bus
config.disks.each do |disk|
device = disk[:device]
bus = disk[:bus]
REXML::XPath.each(xml_descr, '/domain/devices/disk[@device="disk"]/target[@dev="' + device + '"]') do |disk_target|
next unless disk_target.attributes['bus'] != bus
+ @logger.debug "disk #{device} bus updated from '#{disk_target.attributes['bus']}' to '#{bus}'"
descr_changed = true
disk_target.attributes['bus'] = bus
disk_target.parent.delete_element("#{disk_target.parent.xpath}/address")
end
end
# disk_bus
REXML::XPath.each(xml_descr, '/domain/devices/disk[@device="disk"]/target[@dev="vda"]') do |disk_target|
next unless disk_target.attributes['bus'] != config.disk_bus
+ @logger.debug "domain disk bus updated from '#{disk_target.attributes['bus']}' to '#{bus}'"
descr_changed = true
disk_target.attributes['bus'] = config.disk_bus
disk_target.parent.delete_element("#{disk_target.parent.xpath}/address")
end
# Iterface type
unless config.nic_model_type.nil?
REXML::XPath.each(xml_descr, '/domain/devices/interface/model') do |iface_model|
if iface_model.attributes['type'] != config.nic_model_type
+ @logger.debug "network type updated from '#{iface_model.attributes['type']}' to '#{config.nic_model_type}'"
descr_changed = true
iface_model.attributes['type'] = config.nic_model_type
end
end
end
# vCpu count
- if config.cpus.to_i != libvirt_domain.num_vcpus(0)
+ vcpus_count = libvirt_domain.num_vcpus(0)
+ if config.cpus.to_i != vcpus_count
+ @logger.debug "cpu count updated from '#{vcpus_count}' to '#{config.cpus}'"
descr_changed = true
REXML::XPath.first(xml_descr, '/domain/vcpu').text = config.cpus
end
# cpu_mode
cpu = REXML::XPath.first(xml_descr, '/domain/cpu')
if cpu.nil?
+ @logger.debug "cpu_mode updated from not set to '#{config.cpu_mode}'"
descr_changed = true
cpu = REXML::Element.new('cpu', REXML::XPath.first(xml_descr, '/domain'))
cpu.attributes['mode'] = config.cpu_mode
else
if cpu.attributes['mode'] != config.cpu_mode
+ @logger.debug "cpu_mode updated from '#{cpu.attributes['mode']}' to '#{config.cpu_mode}'"
descr_changed = true
cpu.attributes['mode'] = config.cpu_mode
end
end
if config.cpu_mode != 'host-passthrough'
cpu_model = REXML::XPath.first(xml_descr, '/domain/cpu/model')
if cpu_model.nil?
+ @logger.debug "cpu_model updated from not set to '#{config.cpu_model}'"
descr_changed = true
cpu_model = REXML::Element.new('model', REXML::XPath.first(xml_descr, '/domain/cpu'))
cpu_model.attributes['fallback'] = 'allow'
cpu_model.text = config.cpu_model
else
- if cpu_model.text.strip != config.cpu_model.strip
+ if (cpu_model.text or '').strip != config.cpu_model.strip
+ @logger.debug "cpu_model text updated from #{cpu_model.text} to '#{config.cpu_model}'"
descr_changed = true
cpu_model.text = config.cpu_model
end
if cpu_model.attributes['fallback'] != config.cpu_fallback
+ @logger.debug "cpu_model fallback attribute updated from #{cpu_model.attributes['fallback']} to '#{config.cpu_fallback}'"
descr_changed = true
cpu_model.attributes['fallback'] = config.cpu_fallback
end
end
vmx_feature = REXML::XPath.first(xml_descr, '/domain/cpu/feature[@name="vmx"]')
svm_feature = REXML::XPath.first(xml_descr, '/domain/cpu/feature[@name="svm"]')
if config.nested
if vmx_feature.nil?
+ @logger.debug "nested mode enabled from unset by setting cpu vmx feature"
descr_changed = true
vmx_feature = REXML::Element.new('feature', REXML::XPath.first(xml_descr, '/domain/cpu'))
vmx_feature.attributes['policy'] = 'optional'
vmx_feature.attributes['name'] = 'vmx'
end
if svm_feature.nil?
+ @logger.debug "nested mode enabled from unset by setting cpu svm feature"
descr_changed = true
svm_feature = REXML::Element.new('feature', REXML::XPath.first(xml_descr, '/domain/cpu'))
svm_feature.attributes['policy'] = 'optional'
svm_feature.attributes['name'] = 'svm'
end
else
unless vmx_feature.nil?
+ @logger.debug "nested mode disabled for cpu by removing vmx feature"
descr_changed = true
cpu.delete_element(vmx_feature)
end
unless svm_feature.nil?
+ @logger.debug "nested mode disabled for cpu by removing svm feature"
descr_changed = true
cpu.delete_element(svm_feature)
end
end
elsif config.numa_nodes == nil
unless cpu.elements.to_a.empty?
+ @logger.debug "switching cpu_mode to host-passthrough and removing emulated cpu features"
descr_changed = true
cpu.elements.each do |elem|
cpu.delete_element(elem)
end
end
end
+ # Clock
+ clock = REXML::XPath.first(xml_descr, '/domain/clock')
+ if clock.attributes['offset'] != config.clock_offset
+ @logger.debug "clock offset changed"
+ descr_changed = true
+ clock.attributes['offset'] = config.clock_offset
+ end
+
+ # clock timers - because timers can be added/removed, just rebuild and then compare
+ if !config.clock_timers.empty? || clock.has_elements?
+ oldclock = ''
+ formatter.write(REXML::XPath.first(xml_descr, '/domain/clock'), oldclock)
+ clock.delete_element('//timer')
+ config.clock_timers.each do |clock_timer|
+ timer = REXML::Element.new('timer', clock)
+ clock_timer.each do |attr, value|
+ timer.attributes[attr.to_s] = value
+ end
+ end
+
+ newclock = ''
+ formatter.write(clock, newclock)
+ unless newclock.eql? oldclock
+ @logger.debug "clock timers config changed"
+ descr_changed = true
+ end
+ end
+
# Graphics
graphics = REXML::XPath.first(xml_descr, '/domain/devices/graphics')
if config.graphics_type != 'none'
if graphics.nil?
descr_changed = true
@@ -176,52 +222,57 @@
# graphics_type = none, remove entire element
graphics.parent.delete_element(graphics) unless graphics.nil?
end
# TPM
- if config.tpm_path
- raise Errors::FogCreateServerError, 'The TPM Path must be fully qualified' unless config.tpm_path[0].chr == '/'
+ if [config.tpm_path, config.tpm_version].any?
+ if config.tpm_path
+ raise Errors::FogCreateServerError, 'The TPM Path must be fully qualified' unless config.tpm_path[0].chr == '/'
+ end
- tpm = REXML::XPath.first(xml_descr, '/domain/devices/tpm')
- if tpm.nil?
+ # just build the tpm element every time
+ # check at the end if it is different
+ oldtpm = REXML::XPath.first(xml_descr, '/domain/devices/tpm')
+ REXML::XPath.first(xml_descr, '/domain/devices').delete_element("tpm")
+ newtpm = REXML::Element.new('tpm', REXML::XPath.first(xml_descr, '/domain/devices'))
+
+ newtpm.attributes['model'] = config.tpm_model
+ backend = newtpm.add_element('backend')
+ backend.attributes['type'] = config.tpm_type
+
+ case config.tpm_type
+ when 'emulator'
+ backend.attributes['version'] = config.tpm_version
+ when 'passthrough'
+ backend.add_element('device').attributes['path'] = config.tpm_path
+ end
+
+ unless "'#{newtpm}'".eql? "'#{oldtpm}'"
+ @logger.debug "tpm config changed"
descr_changed = true
- tpm = REXML::Element.new('tpm', REXML::XPath.first(xml_descr, '/domain/devices/tpm/model'))
- tpm.attributes['model'] = config.tpm_model
- tpm_backend_type = tpm.add_element('backend')
- tpm_backend_type.attributes['type'] = config.tpm_type
- tpm_device_path = tpm_backend_type.add_element('device')
- tpm_device_path.attributes['path'] = config.tpm_path
- else
- if tpm.attributes['model'] != config.tpm_model
- descr_changed = true
- tpm.attributes['model'] = config.tpm_model
- end
- if tpm.elements['backend'].attributes['type'] != config.tpm_type
- descr_changed = true
- tpm.elements['backend'].attributes['type'] = config.tpm_type
- end
- if tpm.elements['backend'].elements['device'].attributes['path'] != config.tpm_path
- descr_changed = true
- tpm.elements['backend'].elements['device'].attributes['path'] = config.tpm_path
- end
end
end
# Video device
video = REXML::XPath.first(xml_descr, '/domain/devices/video')
if !video.nil? && (config.graphics_type == 'none')
# graphics_type = none, video devices are removed since there is no possible output
+ @logger.debug "deleting video elements as config.graphics_type is none"
descr_changed = true
video.parent.delete_element(video)
else
video_model = REXML::XPath.first(xml_descr, '/domain/devices/video/model')
if video_model.nil?
+ @logger.debug "video updated from not set to type '#{config.video_type}' and vram '#{config.video_vram}'"
+ descr_changed = true
video_model = REXML::Element.new('model', REXML::XPath.first(xml_descr, '/domain/devices/video'))
video_model.attributes['type'] = config.video_type
video_model.attributes['vram'] = config.video_vram
else
- if video_model.attributes['type'] != config.video_type || video_model.attributes['vram'] != config.video_vram
+ if video_model.attributes['type'] != config.video_type || video_model.attributes['vram'] != config.video_vram.to_s
+ @logger.debug "video type updated from '#{video_model.attributes['type']}' to '#{config.video_type}'"
+ @logger.debug "video vram updated from '#{video_model.attributes['vram']}' to '#{config.video_vram}'"
descr_changed = true
video_model.attributes['type'] = config.video_type
video_model.attributes['vram'] = config.video_vram
end
end
@@ -235,42 +286,48 @@
# dtb
if config.dtb
dtb = REXML::XPath.first(xml_descr, '/domain/os/dtb')
if dtb.nil?
+ @logger.debug "dtb updated from not set to '#{config.dtb}'"
descr_changed = true
dtb = REXML::Element.new('dtb', REXML::XPath.first(xml_descr, '/domain/os'))
dtb.text = config.dtb
else
- if dtb.text != config.dtb
+ if (dtb.text or '') != config.dtb
+ @logger.debug "dtb updated from '#{dtb.text}' to '#{config.dtb}'"
descr_changed = true
dtb.text = config.dtb
end
end
end
# kernel and initrd
if config.kernel
kernel = REXML::XPath.first(xml_descr, '/domain/os/kernel')
if kernel.nil?
+ @logger.debug "kernel updated from not set to '#{config.kernel}'"
descr_changed = true
kernel = REXML::Element.new('kernel', REXML::XPath.first(xml_descr, '/domain/os'))
kernel.text = config.kernel
else
- if kernel.text != config.kernel
+ if (kernel.text or '').strip != config.kernel
+ @logger.debug "kernel updated from '#{kernel.text}' to '#{config.kernel}'"
descr_changed = true
kernel.text = config.kernel
end
end
end
if config.initrd
initrd = REXML::XPath.first(xml_descr, '/domain/os/initrd')
if initrd.nil?
+ @logger.debug "initrd updated from not set to '#{config.initrd}'"
descr_changed = true
initrd = REXML::Element.new('initrd', REXML::XPath.first(xml_descr, '/domain/os'))
initrd.text = config.initrd
else
- if initrd.text != config.initrd
+ if (initrd.text or '').strip != config.initrd
+ @logger.debug "initrd updated from '#{initrd.text}' to '#{config.initrd}'"
descr_changed = true
initrd.text = config.initrd
end
end
end