class BoxGrinder::GuestFSHelper

Attributes

guestfs[R]

Public Class Methods

new(disks, appliance_config, config, options = {}) click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 29
def initialize(disks, appliance_config, config, options = {})
  @disks = Array(disks)
  @appliance_config = appliance_config
  @config = config
  @log = options[:log] || LogHelper.new
end

Public Instance Methods

augeas(&block) click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 303
def augeas(&block)
  AugeasHelper.new(@guestfs, self, :log => @log).edit(&block)
end
clean_close() click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 231
def clean_close
  @log.trace "Closing guestfs..."

  @guestfs.sync
  @guestfs.umount_all
  @guestfs.close

  @log.trace "Guestfs closed."
end
customize(options = {}) { |guestfs, helper| ... } click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 172
def customize(options = {})
  initialize_guestfs(options) do
    helper = execute(options)

    yield @guestfs, helper

    clean_close
  end
end
execute(options = {}) click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 182
def execute(options = {})
  options = {
      :ide_disk => false,
      :mount_prefix => '',
      :automount => true,
      :load_selinux_policy => true
  }.merge(options)

  @log.debug "Launching guestfs..."
  @guestfs.launch

  if options[:automount]
    device = @guestfs.list_devices.first

    if @guestfs.list_partitions.size == 0
      mount_partition(device, '/', options[:mount_prefix])
    else
      mount_partitions(device, options[:mount_prefix])
    end

    load_selinux_policy if options[:load_selinux_policy]
  end

  @log.trace "Guestfs launched."

  self
end
hw_virtualization_available?() click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 38
def hw_virtualization_available?
  @log.trace "Checking if HW virtualization is available..."

  ec2 = false

  begin
    Timeout::timeout(2) { ec2 = Net::HTTP.get_response(URI.parse('http://169.254.169.254/latest/meta-data/ami-id')).code.eql?("200") }
  rescue Exception
  end

  if %xegrep '^flags.*(vmx|svm)' /proc/cpuinfo | wc -l`.chomp.strip.to_i > 0 and !ec2
    @log.trace "HW acceleration available."
    return true
  end

  @log.trace "HW acceleration not available."

  false
end
initialize_guestfs(options = {}) { || ... } click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 112
def initialize_guestfs(options = {})
  @log.debug "Preparing guestfs..."
  @log.trace "Setting libguestfs temporary directory to '#{@config.dir.tmp}'..."

  FileUtils.mkdir_p(@config.dir.tmp)
  ENV['TMPDIR'] = @config.dir.tmp

  @guestfs = Guestfs::create

  if @guestfs.respond_to?(:set_event_callback)
    @log.trace "We have event callbacks available!"
    log_callback { prepare_guestfs(options) { yield } }
  else
    @log.trace "We don't have event callbacks available :( Falling back to proxy."
    log_hack { prepare_guestfs(options) { yield } }
  end
end
load_selinux_policy() click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 210
def load_selinux_policy
  return unless @guestfs.exists('/etc/sysconfig/selinux') != 0

  @log.trace "Loading SElinux policy..."

  @guestfs.aug_init("/", 32)
  @guestfs.aug_rm("/augeas/load//incl[. != '/etc/sysconfig/selinux']")
  @guestfs.aug_load

  selinux = @guestfs.aug_get("/files/etc/sysconfig/selinux/SELINUX")

  begin
    @guestfs.sh("/usr/sbin/load_policy") if !selinux.nil? and !selinux.eql?('disabled')
    @log.trace "SElinux policy loaded."
  rescue
    @log.warn "Loading SELinux policy failed. SELinux may be not fully initialized."
  ensure
    @guestfs.aug_close
  end
end
log_callback() { || ... } click to toggle source

issues.jboss.org/browse/BGBUILD-83

# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 59
def log_callback
  default_callback = Proc.new do |event, event_handle, buf, array|
    buf.chomp!

    if event == 64
      @log.debug "GFS: #{buf}"
    else
      @log.trace "GFS: #{buf}" unless buf.start_with?('recv_from_daemon', 'send_to_daemon')
    end
  end

  # Guestfs::EVENT_APPLIANCE  => 16
  # Guestfs::EVENT_LIBRARY    => 32
  # Guestfs::EVENT_TRACE      => 64

  # Referencing int instead of constants make it easier to test
  @guestfs.set_event_callback(default_callback, 16 | 32 | 64)

  yield if block_given?
end
log_hack() { || ... } click to toggle source

If log callback aren't available we will fail to this, which sucks…

# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 81
def log_hack
  read_stderr, write_stderr = IO.pipe

  fork do
    write_stderr.close

    read_stderr.each do |l|
      @log.trace "GFS: #{l.chomp.strip}"
    end

    read_stderr.close
  end

  old_stderr = STDERR.clone

  STDERR.reopen(write_stderr)
  STDERR.sync = true

  begin
    # Execute all tasks
    yield if block_given?
  ensure
    STDERR.reopen(old_stderr)
  end

  write_stderr.close
  read_stderr.close

  Process.wait
end
mount_partition(part, mount_point, mount_prefix = '') click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 241
def mount_partition(part, mount_point, mount_prefix = '')
  @log.trace "Mounting #{part} partition to #{mount_point}..."
  @guestfs.mount_options("", part, "#{mount_prefix}#{mount_point}")
  # By the way - update the labels so we don't have to muck again with partitions
  # this will be done for every mount, but shouldn't hurt too much.
  @guestfs.set_e2label(part, Zlib.crc32(mount_point).to_s(16))
  @log.trace "Partition mounted."
end
mount_partitions(device, mount_prefix = '') click to toggle source

This mount partitions. We assume that the first partition is a root partition.

# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 252
def mount_partitions(device, mount_prefix = '')
  @log.trace "Mounting partitions..."

  partitions = mountable_partitions(device)
  mount_points = LinuxHelper.new(:log => @log).partition_mount_points(@appliance_config.hardware.partitions)
  # https://issues.jboss.org/browse/BGBUILD-307
  # We don't want to mount swap partitions at all...
  mount_points.delete("swap")
  partitions.each_index { |i| mount_partition(partitions[i], mount_points[i], mount_prefix) }
end
mountable_partitions(device, options = {}) click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 263
def mountable_partitions(device, options = {})
  options = {:list_swap => false}.merge(options)

  dev_parse = lambda { |d| d.match(/\d*$/)[0].to_i }
  
  partitions = @guestfs.list_partitions.sort do |x, y|
    dev_parse.call(x) <=> dev_parse.call(y) 
  end

  # we need to remove extended partition
  # extended partition is always #3
  partitions.delete_at(3) if partitions.size > 4

  partitions.reject { |i| !(i =~ /^#{device}/) or (@guestfs.vfs_type(i) == '') or (@guestfs.vfs_type(i) == 'swap' and !options[:list_swap]) }
end
prepare_guestfs(options = {}) { || ... } click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 130
def prepare_guestfs(options = {})
  @log.trace "Setting debug + trace..."
  @guestfs.set_verbose(1)
  @guestfs.set_trace(1)

  # https://issues.jboss.org/browse/BGBUILD-246
  memsize = ENV['LIBGUESTFS_MEMSIZE'].nil? ? 300 : ENV['LIBGUESTFS_MEMSIZE'].to_i
  @guestfs.set_memsize(memsize)

  # https://bugzilla.redhat.com/show_bug.cgi?id=502058
  @guestfs.set_append("noapic")

  @log.trace "Enabling SElinux support in guestfs..."
  @guestfs.set_selinux(1)

  unless hw_virtualization_available?
    # This wrapper is required especially for EC2 where running qemu-kvm crashes libguestfs
    qemu_wrapper = "#{File.dirname(__FILE__)}/qemu.wrapper"

    @log.trace "Setting QEMU wrapper to #{qemu_wrapper}..."
    @guestfs.set_qemu(qemu_wrapper)
    @log.trace "QEMU wrapper set."
  end

  @disks.each do |disk|
    @log.trace "Adding drive '#{disk}'..."
    if options[:ide_disk]
      @guestfs.add_drive_with_if(disk, 'ide')
    else
      @guestfs.add_drive(disk)
    end
    @log.trace "Drive added."
  end

  if @guestfs.respond_to?('set_network')
    @log.debug "Enabling networking for GuestFS..."
    @guestfs.set_network(1)
  end

  yield
end
sh(cmd, options = {}) click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 295
def sh(cmd, options = {})
  arch = options[:arch] || %xuname -m`.chomp.strip

  @log.debug "Executing '#{cmd}' command..."
  @guestfs.sh("setarch #{arch} << 'SETARCH_EOF'\n#{cmd}\nSETARCH_EOF")
  @log.debug "Command '#{cmd}' executed."
end
umount_partition(part) click to toggle source
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 279
def umount_partition(part)
  @log.trace "Unmounting partition #{part}..."
  @guestfs.umount(part)
  @log.trace "Partition unmounted."
end
umount_partitions(device) click to toggle source

Unmounts partitions in reverse order.

# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 287
def umount_partitions(device)
  partitions = mountable_partitions(device)

  @log.trace "Unmounting partitions..."
  partitions.reverse.each { |part| umount_partition(part) }
  @log.trace "All partitions unmounted."
end