require 'nokogiri' require 'fileutils' module Veewee module Provider module Kvm module BoxCommand # Create a new vm def create(options={}) # Assemble the Virtualmachine and set all the memory and other stuff" create_server(options) create_volume(options) add_virtio_drivers if File.exists?(File.join(definition.path, 'Autounattend.xml')) self.create_floppy("virtualfloppy.img") FileUtils.move(File.join(definition.path, 'Autounattend.xml.virtio'), File.join(definition.path, 'Autounattend.xml')) if File.exists?(File.join(definition.path, 'Autounattend.xml.virtio')) add_floppy unless definition.floppy_files.nil? end def create_server(options) # set volume pool name to user specified volume pool and fall back to first available volume pool if options["pool_name"] raise Veewee::Error, "Specified storage pool #{options["pool_name"]} does not exist" if @connection.pools.select { |pool| pool.name == options["pool_name"] }.empty? volume_pool_name = options["pool_name"] end volume_pool_name ||= @connection.pools.first.name env.logger.info "Using storage pool #{volume_pool_name}" # set network name to user specified network and fall back to default network or first available network if options["network_name"] raise Veewee::Error, "Specified network #{options["network_name"]} does not exist" if @connection.networks.select { |net| net.name == options["network_name"] }.empty? network_name = options["network_name"] end network_name ||= "default" unless @connection.networks.select { |net| net.name == 'default' }.empty? network_name ||= @connection.networks.first.name env.logger.info "Using network #{network_name}" # Create the "server" attributes = { :name => name, :memory_size => definition.memory_size.to_i*1024, :cpus => definition.cpu_count.to_i, :volume_capacity => "#{definition.disk_size}M", :domain_type => options['use_emulation'] ? 'qemu' : 'kvm', :iso_file => definition.iso_file, :arch => definition.os_type_id.end_with?("_64") ? "x86_64" : "i686", :iso_dir => env.config.veewee.iso_dir, :volume_pool_name => volume_pool_name, :volume_format_type => definition.disk_format, :network_nat_network => network_name } @connection.servers.create(attributes) end # Create the volume of a new vm def create_volume(options) # Creating the volume is part of the server creation end def add_floppy env.logger.info 'Adding floppy disk' # Get a raw libvirt connection conn = @connection.client # Retrieve the domain domain=conn.lookup_domain_by_name(name) # Retrieve the existing XML from the domain domain_xml=domain.xml_desc # Convert the xml nokogiri doc domain_doc=Nokogiri::XML(domain_xml) # Find the device section devices=domain_doc.xpath('/domain/devices').first # The floppy xml representation floppy_xml="
" # Convert the floppy xml to nokogiri floppy_doc=Nokogiri::XML(floppy_xml) # Add the floppy to the devices section devices.add_child(floppy_doc.root) # Get the raw xml of the changed document new_xml=domain_doc.to_xml # Undefine the existing domain domain.undefine # Re-define the domain conn.define_domain_xml(new_xml) end def add_virtio_drivers env.logger.info 'Adding virtio drivers for windows system to the virtual machine' # Get a raw libvirt connection conn = @connection.client # Retrieve the domain domain=conn.lookup_domain_by_name(name) # Retrieve the existing XML from the domain domain_xml=domain.xml_desc # Convert the xml nokogiri doc domain_doc=Nokogiri::XML(domain_xml) # Find the device section devices=domain_doc.xpath('/domain/devices').first # get latest version of virtio drivers url ='http://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/bin/' filename = open(url).read.scan(/\"(virtio-win-.*.iso)\"/).first.first download_iso(url + filename, filename) path = File.join(env.config.veewee.iso_dir, filename) # The disk xml representation disk_xml="" # Convert the disk xml to nokogiri disk_doc=Nokogiri::XML(disk_xml) # Add the floppy to the devices section devices.add_child(disk_doc.root) # Get the raw xml of the changed document new_xml=domain_doc.to_xml # Undefine the existing domain domain.undefine # Re-define the domain conn.define_domain_xml(new_xml) env.logger.info 'Add search path for virtio drivers to Autounattend.xml' # parse Autoattend.xml to document FileUtils.copy(File.join(definition.path, 'Autounattend.xml'), File.join(definition.path, 'Autounattend.xml.virtio')) doc = Nokogiri::XML.parse(File.read(File.join(definition.path, 'Autounattend.xml'))) # determine platform and windows version platform = definition.os_type_id.end_with?("_64") ? "amd64" : "x86" version = case definition.os_type_id.downcase when /windows-?7/ 'win7' when /windows-?2008/ 'win7' when /windows-?8/ 'win8' when /xp/ 'xp' when /vista/ 'vista' else raise 'could not determine windows version' end # create new element component=Nokogiri::XML(%Q| e:\\#{version}\\#{platform} |) doc.xpath('//unattend:settings[@pass="windowsPE"]', 'unattend' => 'urn:schemas-microsoft-com:unattend').first.add_child component.root file = File.open(File.join(definition.path, 'Autounattend.xml'), 'w') file.write(doc) file.close end end #End Module end # End Module end # End Module end # End Module