lib/vagrant-libvirt/action/package_domain.rb in vagrant-libvirt-0.0.45 vs lib/vagrant-libvirt/action/package_domain.rb in vagrant-libvirt-0.1.0

- old
+ new

@@ -1,11 +1,12 @@ +require 'fileutils' require 'log4r' module VagrantPlugins module ProviderLibvirt module Action - # Action for create new box for libvirt provider + # Action for create new box for Libvirt provider class PackageDomain def initialize(app, env) @logger = Log4r::Logger.new('vagrant_libvirt::action::package_domain') @app = app env['package.files'] ||= {} @@ -19,28 +20,35 @@ ) domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s) root_disk = domain.volumes.select do |x| x.name == libvirt_domain.name + '.img' end.first + raise Errors::NoDomainVolume if root_disk.nil? boxname = env['package.output'] raise "#{boxname}: Already exists" if File.exist?(boxname) @tmp_dir = Dir.pwd + '/_tmp_package' @tmp_img = @tmp_dir + '/box.img' - Dir.mkdir(@tmp_dir) - if File.readable?(root_disk.path) - backing = `qemu-img info "#{root_disk.path}" | grep 'backing file:' | cut -d ':' -f2`.chomp - else - env[:ui].error("Require set read access to #{root_disk.path}. sudo chmod a+r #{root_disk.path}") - FileUtils.rm_rf(@tmp_dir) - raise 'Have no access' + FileUtils.mkdir_p(@tmp_dir) + env[:ui].info("Downloading #{root_disk.name} to #{@tmp_img}") + ret = download_image(@tmp_img, env[:machine].provider_config.storage_pool_name, + root_disk.name, env) do |progress,image_size| + env[:ui].clear_line + env[:ui].report_progress(progress, image_size, false) end - env[:ui].info('Image has backing image, copying image and rebasing ...') - FileUtils.cp(root_disk.path, @tmp_img) - `qemu-img rebase -p -b "" #{@tmp_img}` + # Clear the line one last time since the progress meter doesn't + # disappear immediately. + env[:ui].clear_line + backing = `qemu-img info "#{@tmp_img}" | grep 'backing file:' | cut -d ':' -f2`.chomp + if backing + env[:ui].info('Image has backing image, copying image and rebasing ...') + `qemu-img rebase -p -b "" #{@tmp_img}` + end # remove hw association with interface # working for centos with lvs default disks - `virt-sysprep --no-logfile --operations defaults,-ssh-userdir -a #{@tmp_img}` + options = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS', '') + operations = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS', 'defaults,-ssh-userdir') + `virt-sysprep --no-logfile --operations #{operations} -a #{@tmp_img} #{options}` # add any user provided file extra = '' @tmp_include = @tmp_dir + '/_include' if env['package.include'] extra = './_include' @@ -96,9 +104,47 @@ "provider": "libvirt", "format": "qcow2", "virtual_size": #{filesize} } EOF + end + + protected + + # Fog libvirt currently doesn't support downloading images from storage + # pool volumes. Use ruby-libvirt client instead. + def download_image(image_file, pool_name, volume_name, env) + begin + pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name( + pool_name + ) + volume = pool.lookup_volume_by_name(volume_name) + image_size = volume.info.allocation # B + + stream = env[:machine].provider.driver.connection.client.stream + + # Use length of 0 to download remaining contents after offset + volume.download(stream, offset = 0, length = 0) + + buf_size = 1024 * 250 # 250K, copied from upload_image in handle_box_image.rb + progress = 0 + retval = stream.recv(buf_size) + open(image_file, 'wb') do |io| + while (retval.at(0) > 0) + recvd = io.write(retval.at(1)) + progress += recvd + yield [progress, image_size] + retval = stream.recv(buf_size) + end + end + rescue => e + raise Errors::ImageDownloadError, + volume_name: volume_name, + pool_name: pool_name, + error_message: e.message + end + + progress == image_size end end end end end