lib/vagrant-libvirt/action/start_domain.rb in vagrant-libvirt-0.0.31 vs lib/vagrant-libvirt/action/start_domain.rb in vagrant-libvirt-0.0.32
- old
+ new
@@ -1,11 +1,11 @@
require 'log4r'
+require 'rexml/document'
module VagrantPlugins
module ProviderLibvirt
module Action
-
# Just start the domain.
class StartDomain
def initialize(app, env)
@logger = Log4r::Logger.new("vagrant_libvirt::action::start_domain")
@app = app
@@ -14,11 +14,173 @@
def call(env)
env[:ui].info(I18n.t("vagrant_libvirt.starting_domain"))
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
raise Errors::NoDomainError if domain == nil
+ config = env[:machine].provider_config
begin
+ # update domain settings on change.
+
+ libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(env[:machine].id)
+
+ if config.memory*1024 != libvirt_domain.max_memory
+ libvirt_domain.max_memory = config.memory*1024
+ libvirt_domain.memory = libvirt_domain.max_memory
+ end
+ begin
+ # XML definition manipulation
+ descr = libvirt_domain.xml_desc(1)
+ xml_descr = REXML::Document.new descr
+ descr_changed = false
+
+ # additional disk bus
+ config.disks.each {|disk|
+ device = disk[:device]
+ bus = disk[:bus]
+ REXML::XPath.each(xml_descr,'/domain/devices/disk[@device="disk"]/target[@dev="'+device+'"]') {|disk_target|
+ if disk_target.attributes['bus'] != bus
+ descr_changed = true
+ disk_target.attributes['bus'] = bus
+ disk_target.parent.delete_element("#{disk_target.parent.xpath}/address")
+ end
+ }
+ }
+
+ # disk_bus
+ REXML::XPath.each(xml_descr,'/domain/devices/disk[@device="disk"]/target[@dev="vda"]') {|disk_target|
+ if disk_target.attributes['bus'] != config.disk_bus
+ descr_changed = true
+ disk_target.attributes['bus'] = config.disk_bus
+ disk_target.parent.delete_element("#{disk_target.parent.xpath}/address")
+ end
+ }
+
+ # Iterface type
+ REXML::XPath.each(xml_descr,'/domain/devices/interface/model') {|iface_model|
+ if iface_model.attributes['type'] != config.nic_model_type
+ descr_changed = true
+ iface_model.attributes['type'] = config.nic_model_type
+ end
+ }
+
+ # vCpu count
+ if config.cpus.to_i != libvirt_domain.vcpus.length
+ 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?
+ 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
+ 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?
+ descr_changed = true
+ cpu_model = REXML::Element.new('model', REXML::XPath.first(xml_descr,'/domain/cpu'))
+ cpu_model.attributes['fallback'] = 'allow'
+ cpu_model.text = 'qemu64'
+ 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?
+ 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?
+ 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
+ if !vmx_feature.nil?
+ descr_changed = true
+ cpu.delete_element(vmx_feature)
+ end
+ if !svm_feature.nil?
+ descr_changed = true
+ cpu.delete_element(svm_feature)
+ end
+ end
+ else
+ if cpu.elements.to_a.length > 0
+ descr_changed = true
+ cpu.elements.each {|elem|
+ cpu.delete_element(elem)
+ }
+ end
+ end
+
+ # Graphics
+ graphics = REXML::XPath.first(xml_descr,'/domain/devices/graphics')
+ if graphics.attributes['type'] != config.graphics_type
+ descr_changed = true
+ graphics.attributes['type'] = config.graphics_type
+ end
+ if graphics.attributes['listen'] != config.graphics_ip
+ descr_changed = true
+ graphics.attributes['listen'] = config.graphics_ip
+ graphics.delete_element('//listen')
+ end
+ if graphics.attributes['autoport'] != config.graphics_autoport
+ descr_changed = true
+ graphics.attributes['autoport'] = config.graphics_autoport
+ if config.graphics_autoport == 'no'
+ graphics.attributes['port'] = config.graphics_port
+ end
+ end
+ if graphics.attributes['keymap'] != config.keymap
+ descr_changed = true
+ graphics.attributes['keymap'] = config.keymap
+ end
+ if graphics.attributes['passwd'] != config.graphics_passwd
+ descr_changed = true
+ if config.graphics_passwd.nil?
+ graphics.attributes.delete 'passwd'
+ else
+ graphics.attributes['passwd'] = config.graphics_passwd
+ end
+ end
+
+ # Video device
+ video = REXML::XPath.first(xml_descr,'/domain/devices/video/model')
+ if video.attributes['type'] != config.video_type || video.attributes['vram'] != config.video_vram
+ descr_changed = true
+ video.attributes.each_attribute {|attr| video.attributes.delete attr}
+ video.attributes['type'] = config.video_type
+ video.attributes['vram'] = config.video_vram
+ end
+
+ # Apply
+ if descr_changed
+ begin
+ libvirt_domain.undefine
+ new_descr = ""
+ xml_descr.write new_descr
+ server = env[:machine].provider.driver.connection.servers.create(xml: new_descr)
+ rescue Fog::Errors::Error => e
+ server = env[:machine].provider.driver.connection.servers.create(xml: descr)
+ raise Errors::FogCreateServerError, error_message: e.message
+ end
+ end
+ rescue => e
+ env[:ui].error("Error when updating domain settings: #{e.message}")
+ end
+ # Actually start the domain
domain.start
rescue => e
raise Errors::FogError, :message => e.message
end