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