class VirtP2V::Converter

name User entry memory Editable cpus Editable arch Detected: cpuflags contains lm (long mode) features Detected: apic, acpi, pae disks Editable, default to all

device        Detected
path          Detected
is_block      1
format        raw

removables Editable, default to all

device        Detected
type          Detected

nics Editable, default to all connected

mac           Detected, option to generate new
vnet          Set to nic name
vnet_type     bridge

Attributes

arch[RW]
connection[R]
cpus[RW]
debug[RW]
disks[R]
features[R]
memory[RW]
name[RW]
nics[R]
profile[RW]
removables[R]

Public Class Methods

new() click to toggle source
# File lib/virt-p2v/converter.rb, line 96
def initialize()
    @profile = nil
    @connection = nil
    @connection_listeners = []
    @debug = false

    # Initialize basic system information
    @name = '' # There's no reasonable default for this

    # Get total memory from /proc/meminfo
    File.open('/proc/meminfo', 'r') do |fd|
        fd.each { |line|
            next unless line =~ /^MemTotal:\s+(\d+)\b/

            @memory = Integer($~[1]) * 1024
            break
        }
    end

    # Get the total number of cpu threads from hwloc-info
    hwloc = Document.new %xhwloc-info --of xml`
    @cpus = XPath.match(hwloc, "//object[@type='PU']").length

    # Get cpu architecture and features from the first flags entry in
    # /proc/cpuinfo
    File.open('/proc/cpuinfo', 'r') do |fd|
        fd.each { |line|
            next unless line =~ /^flags\s*:\s(.*)$/

            flags = $~[1]

            # x86_64 if flags contains lm (long mode), i686 otherwise. We
            # don't support anything else.
            @arch = flags =~ /\blm\b/ ? 'x86_64' : 'i686'

            # Pull some select features from cpu flags
            @features = []
            [ 'apic', 'acpi', 'pae' ].each { |f|
                @features << f if flags =~ /\b#{f}\b/
            }
            break
        }
    end

    # Initialise empty lists for optional devices. These will be added
    # according to the user's selection
    @disks = []
    @removables = []
    @nics = []

    @debug = false
end

Public Instance Methods

connection=(connection) click to toggle source
# File lib/virt-p2v/converter.rb, line 58
def connection=(connection)
    @connection = connection
    @connection_listeners.each { |cb|
        cb.call(connection)
    }
end
convert(status, progress, &completion) click to toggle source
# File lib/virt-p2v/converter.rb, line 65
def convert(status, progress, &completion)
    iterate([
        lambda { |cb| @connection.set_profile(@profile, &cb) },
        lambda { |cb| @connection.metadata(meta, &cb) },
        lambda { |cb|
            iterate(@disks.map { |dev|
                lambda { |cb2|
                    disk(dev, status, progress, cb2)
                }
            }, cb)
        },
        lambda { |cb|
            if @debug
                begin
                    @connection.options({ "DEBUG" => 1 }, &cb)
                rescue VirtV2V::Connection::UnsupportedOperationError
                    cb.call(true)
                end
            else
                cb.call(true)
            end
        },
        lambda { |cb|
            status.call('Converting')
            @connection.convert(&cb)
        }
    ], completion)
end
on_connection(&cb) click to toggle source
# File lib/virt-p2v/converter.rb, line 54
def on_connection(&cb)
    @connection_listeners << cb
end

Private Instance Methods

disk(dev, status, progress, completion) click to toggle source
# File lib/virt-p2v/converter.rb, line 149
def disk(dev, status, progress, completion)
    path = "/dev/#{dev}"
    size = FixedBlockDevice[dev].size
    status.call("Transferring #{dev}")
    iterate([
        lambda { |cb| @connection.path(size, path, &cb) },
        lambda { |cb| @connection.container('RAW', &cb) },
        lambda { |cb|
            io = nil
            begin
                io = File.new(path, 'r')
            rescue => ex
                cb.call(ex)
            end
            pc = 0
            @connection.send_data(io, size, lambda { |total|
                npc = Float(total) * 100 / size
                # Only update the progress if it has increased by
                # at least 1%
                if Integer(npc) > pc then
                    pc = Integer(npc)
                    progress.call(dev, pc)
                end
            }, &cb)
        }
    ], completion)
end
iterate(stages, completion) click to toggle source
# File lib/virt-p2v/converter.rb, line 177
def iterate(stages, completion)
    i = 0
    cb = lambda { |result|
        if result.kind_of?(Exception) then
            completion.call(result)
        else
            i += 1
            if i == stages.length then
                completion.call(true)
            else
                stages[i].call(cb)
            end
        end
    }
    stages[0].call(cb)
end
meta() click to toggle source
# File lib/virt-p2v/converter.rb, line 194
def meta
    {
        'name'      => @name,
        'cpus'      => @cpus,
        'memory'    => @memory,
        'arch'      => @arch,
        'features'  => @features,
        'disks'     => @disks.map { |device|
            {
                'device'    => device,
                'path'      => "/dev/#{device}"
            }
        },
        'removables' => @removables.map { |device|
            removable = RemovableBlockDevice[device]
            {
                'device'    => removable.device,
                'type'      => removable.type
            }
        },
        'nics'      => @nics.map { |device|
            nic = NetworkDevice[device]
            {
                'mac'       => nic.mac,
                'vnet'      => nic.name,
                'vnet_type' => 'bridge'
            }
        }
    }
end